深度学习部署到移动端除了苹果的MLCore,还有NCNN,MNN,这篇文章尝试用工具转换.pth模型到iOS适用的.mlmodel。
笔者希望将研究生阶段做的CGAN一直到ios端,由于是image segment,资料不是特别多,遇到许多坑,这里分享出来帮助大家排坑,共同学习。
pytorch to CoreML
这里不做太多介绍,直接看流程图

1. 保存pytroch模型.pth文件
#在train.py的里面有torch.save()
2. pth2onnx
我的模型是Unet,在models.network里定义好了
from models.networks import *
model = UnetGenerator(3,3,8)#input_nc=3,output_nc=3,num_downs=8(数字越大层级越复杂,模型也越臃肿)
model.load_state_dict(torch.load("Unet.pth")) # pytorch模型加载
print(model)
batch_size =1 #批处理大小
input_shape = (3,256,256) #输入数据
x = torch.randn(batch_size,*input_shape) # 生成张量
torch.onnx.export(model, x, "Unet.onnx", verbose=True,input_names=['inputImage'],output_names=['outputImage'])#输入输出名要和后面保持一致
3. onnx2mlmodel
坑来了:一开始发现onnx的input尺寸是对的,但是转换成mlmodel后并不是Image,而是,直到在这个issue里找到了问题的所在。
https://github.com/onnx/onnx-coreml/issues/92
指定顺利解决
import sys
from onnx import onnx_pb
from onnx_coreml import convert
model_in = sys.argv[1]
model_out = sys.argv[2]
model_file = open(model_in, 'rb')
model_proto = onnx_pb.ModelProto()
model_proto.ParseFromString(model_file.read())
coreml_model = convert(model_proto,minimum_ios_deployment_target='13',preprocessing_args={'image_scale':1.0/(255.0*0.5),'red_bias':-0.5/0.5,'green_bias':-0.5/0.5,'blue_bias':-0.5/0.5,'is_bgr':False},deprocessing_args={'image_scale':255.0},image_input_names=['inputImage'],image_output_names=['outputImage'])
coreml_model.save(model_out)
执行下面语句运行
python onnx_to_coreml.py ./saved_models/Unet.onnx ./saved_models/Unet.mlmodel
另一个坑是preprocessing_args和deprocessing_args。由于我的Unet模型都是转成0~1的tensor处理的,所以要将输入图片除255,再将输出乘255。这个问题网上没有找到解释的很明确的。
其中还有个均值方差的问题,查了下面的链接后才知道为啥我的结果和电脑上的不一样。 https://zhuanlan.zhihu.com/p/110269410 ‘image_scale’:1.0/(255.0*0.5),’red_bias’:-0.5/0.5,’green_bias’:-0.5/0.5,’blue_bias’:-0.5/0.5 因为在pytorch训练时归一化transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))均值和方差都是0.5
4. 找一个写好的Xcode程序换模型
我希望是通过上传图片再转换的形式,下面这个项目挺合适,是风格迁移
https://github.com/kirualex/NSTDemo
5. 修改参数
注意划红线部分

就可以愉快的用手机实现深度学习的应用啦!
作者 [张巍]
2020 年 04月 28日