本文介绍了如何使用ailia SDK在 iOS 和 Android 上使用Pytorch训练的 AI 模型。
在边缘设备上应用AI模型的挑战
将在PC上使用Pytorch训练过的AI模型用于iPhone或Android等边缘设备时可能会遇到一些挑战,ailia SDK可以帮助解决这些问题。
针对平台的框架
iOS设备通常使用Apple提供的CoreML运行AI模型,而Android开发者通常选择TensorFlowLite。每个平台都必须使用不同的API,并针对各自进行优化。
ailia SDK是一个统一的框架,它可以在Windows、macOS、Linux、iOS和Android上使用通用的API进行推理。
平台特定语言
iOS必须使用ObjectiveC或Swift,而Android必须使用Java或Kotlin,而ailia SDK与Unity游戏引擎兼容,并且可以通过C#进行交互,然后可以在iOS和Android设备上执行。
模型转换错误
从Pytorch转换到不同框架时可能会发生模型转换错误。AI模型近年来越来越复杂,特别是在使用5D张量或在每帧的张量形状动态变化时,极易出现问题。
使用ailia SDK,通用的ONNX模型可以在PC和智能手机上使用,无需模型转换。因此,如果模型在PC上确认可以运行,那么它就可以保证在iOS和Android上照常运行,而无需担心模型转换错误。
GPU不可用
TensorFlowLite中的GPU委托只支持很少的层,因此GPU在Android上经常无法高效使用。
使用ailia SDK,可以在Android上通过Vulkan使用GPU推理,而在iOS上可用Metal以及CoreML。
使用ailia SDK的开发流程
将Pytorch模型转换为ONNX后,你可以直接在Python中使用它,以确认推理工作正常。下一步是在Unity中使用同样的模型,并在智能手机上运行应用程序。
因为 ailia SDK 使用 ONNX 格式,首先使用 torch.onnx.export 将 Pytorch 模型转换为 ONNX。
当输入具有固定形状时,可以通过使用下面命令中的 torch 模型,即下文中的 argumentmodel,以及作为参数的输入张量,即由 x 表示的输入张量来调用 export 以输出 ONNX。
torch.onnx.export(model, x, 'output.onnx', verbose=False, opset_version=11)'output.onnx', verbose=False, opset_version=11)
如果输入的形状是动态指定的,请使用 dynamic_axes。在这个例子中,两个变量 x1 和 x2 被用作输入,其中 x1 的 axis0 和 axis3 是可变的。
torch.onnx.export(model, (x1, x2), 'output.onnx', verbose=False, opset_version=11, input_names=["input1", "input2"], dynamic_axes={"input1": {0: "batch_size", 3:"samples"}})'output.onnx', verbose=False, opset_version=11, input_names=["input1", "input2"], dynamic_axes={"input1": {0: "batch_size", 3:"samples"}})
ONNX 的推论
使用ONNX Runtime导出的ONNX模型可以使用ONNX Runtime或ailia SDK进行测试。
import onnxruntime
model = onnxruntime.InferenceSession("input.onnx")
output = model.run(None, {"input1":tensor.numpy()})[0]
output = torch.from_numpy(output.astype(np.float32)).clone()
使用ailia SDK
import ailia
model = ailia.Net(None, "input.onnx")
output = model.run({"input1":tensor.numpy()})[0]
output = torch.from_numpy(output.astype(np.float32)).clone()
可以使用以下命令轻松设置运行ailia SDK的Python环境:
cd ailia_sdk/python
python3 bootstrap.py
pip3 install .
从Unity中进行推理
将ailia SDK的Unity包导入到Unity中。将转换后的ONNX文件放置在StreamingAsstes文件夹中。下面显示了一个推理代码的示例:
float [] infer(float [] input1){
// Open model file
AiliaModel model=new AiliaModel();
#if UNITY_ANDROID
model.OpenFile(null,Application.temporaryCachePath+"/input.onnx");
#else
model.OpenFile(null,Application.streamingAssetsPath+"/input.onnx");
#endif
// Set input
Ailia.AILIAShape shape=new Ailia.AILIAShape();
shape.x=input1.Length;
shape.y=1;
shape.z=1;
shape.w=1;
shape.dim=4;
model.SetInputBlobShape(shape, model.FindBlobIndexByName("input1"));
model.SetInputBlobData(input1, model.FindBlobIndexByName("input1"));
// Infer
model.Update();
// Get output
Ailia.AILIAShape output_shape=model.GetOutputShape();
float [] output=new float[output_shape.x * output_shape.y * output_shape.z * output_shape.w];
model.GetBlobData(output,(int)model.GetOutputBlobList()[0]);
model.Close();
return output;
}
对于Android,将StreamingAssets文件复制到temporaryCachePath,因为无法直接访问它。
private void CopyModelToTemporaryCachePath (string file_name)
{
#if UNITY_ANDROID && !UNITY_EDITOR
string prefix="";
#else
string prefix="file://";
#endif
string path = prefix+Application.streamingAssetsPath + "/" + file_name;
string toPath = Application.temporaryCachePath + "/" + file_name;
Debug.Log("Copy "+path+" to "+toPath);
if (System.IO.File.Exists(toPath) == true)
{
FileInfo fileInfo = new System.IO.FileInfo(toPath);
if (fileInfo.Length != 0)
{
Debug.Log("Already exists : " + toPath + " " + fileInfo.Length);
return;
}
}
WWW www = new WWW(path);
while (!www.isDone)
{
// NOP.
}
File.WriteAllBytes(toPath, www.bytes);
}
最终将这个Unity程序部署至你的智能手机上进行最后的测试。
ailia SDK 支持库
概述
Pytorch模型可以使用上述程序与ailia SDK一起使用,然而,一些特性例如torch_audio、Transformers的分词器可能会被使用,这些只能通过Python访问。
ailia.audio
这个库相当于torch_audio和librosa。它支持音频的mel频谱转换等功能。
结论
通过使用ailia SDK及其支持库,用Pytorch训练的模型可以轻松地在边缘设备上运行。