读研期间pytorch用的比较多,工作后用simulink进行仿真和代码生成更多一点,虽然simulink工具箱里也提供了针对深度学习的基础组件,但自己搭建费时费力,matlab提供的网络模型又很古老,遂决定用pytorch训练网络做微调,在simulink中进行数据交互。
matlab与pytorch交互
- matlab与pytorch有两种交互方式,直接相互调用或模型权重转化后调用。
- 第一种方式非常灵活方便,用python封装好接口后在matlab里使用Python Interface就可以直接调用啦,但运行效率较低,适合功能测试。
- 为提高运行效率,在这里选择第二种方式。
环境配置
matlab早期的版本中,tensorflow和caffe可以直接导入权重,pytorch需要先转为onnx格式才能调用,但在2022b及后续版本中支持了.pt模型直接导入,有需要的话可以先升级matlab版本,并安装Deep Learning Toolbox Converter for PyTorch Models工具包。
追踪模型并保存
注意,pytorch训练的模型需要先使用torch.jit.trace转为TorchScript,跟踪模型的执行过程,这里使用torchvision 自带的模型进行演示,如下:
import torch
from torchvision import models
model = models.mobilenet_v2(pretrained=True)
model.eval().to("cpu")
# BCHW
X = torch.rand(1, 3, 224, 224)
traced_model = torch.jit.trace(model.forward, X)
traced_model.save('traced_mobilenetv2.pt')
在matlab中进行模型推理
注意,importNetworkFromPyTorch函数不会自动添加输入层,需手动添加一个与模型InputSizes相同的输入层或初始化模型。
modelfile = "traced_mobilenetv2.pt";
net = importNetworkFromPyTorch(modelfile,PyTorchInputSizes=[NaN,3,224,224])
% 或下面的方式
modelfile = "traced_mobilenetv2.pt";
net = importNetworkFromPyTorch(modelfile)
InputSize = [224 224 3];
inputLayer = imageInputLayer(InputSize,Normalization="none");
net = addInputLayer(net,inputLayer,Initialize=true);
% 读取图片并推理
Im = imread("peppers.png");
Im = imresize(Im,InputSize(1:2));
Im = rescale(Im,0,1);
meanIm = [0.485 0.456 0.406];
stdIm = [0.229 0.224 0.225];
Im = (Im - reshape(meanIm,[1 1 3]))./reshape(stdIm,[1 1 3]);
% Convert the image to a dlarray object. Format the image with the dimensions "SSCB" (spatial, spatial, channel, batch).
Im_dlarray = dlarray(single(Im),"SSCB");
% Get the class names from squeezenet, which is also trained with ImageNet images.
[~,ClassNames] = imagePretrainedNetwork("squeezenet");
prob = predict(net,Im_dlarray);
[~,label_ind] = max(prob);
ClassNames(label_ind)
检查模型
运行结果
simulink进行仿真
用PyTorch Model Predict模块加载预训练权重
添加输入输出并测试
>> fileNames = ["sherlock.jpg","peacock.jpg","lighthouse.png","llama.jpg", ...
"trailer.jpg"];
filePath = fullfile(matlabroot,"toolbox","images","imdata")+filesep;
filePathNames = strcat(filePath,fileNames);
imds = imageDatastore(filePathNames);
>> InputSize = [224 224 3];
meanIm = [0.485 0.456 0.406];
stdIm = [0.229 0.224 0.225];
for i = 1:5
Im = imread(imds.Files{i});
Im = imresize(Im,InputSize(1:2));
Im = rescale(Im,0,1);
Im = (Im - reshape(meanIm,[1 1 3]))./reshape(stdIm,[1 1 3]);
displayIms(:,:,:,i) = Im;
end
montage(displayIms,size=[1 NaN]);
>> inputIms = single(displayIms);
>> mnasnetfile = matlab.internal.examples.downloadSupportFile("nnet", ...
"data/PyTorchModels/mnasnet1_0.pt");
copyfile(mnasnetfile)
>> modelOutput = sim("slexImagePyTorchModelPredictExample");
>> [~,ClassNames] = imagePretrainedNetwork("squeezenet");
>> tiledlayout(1,size(inputIms,4),TileSpacing="none");
for i = 1:size(inputIms,4)
nexttile
imshow(displayIms(:,:,:,i))
prob =(modelOutput.yPred.Data(:,:,i));
[~,label_ind] = max(prob);
title([ClassNames{label_ind}],FontSize=12)
end
>>
预测结果
部署与代码生成
手写代码嵌入过程繁琐且无法和simulink联合仿真,simulink提供了代码生成工具,可以直接生成C++,CUDA代码,部署到目标平台。
根据部署硬件有无CUDA加速,可将模型转为ONNX或TensorRT格式,后续推文将更新把模型转为TensorRT格式并部署。