深度学习使用包含许多处理层的神经网络架构,包括卷积层。深度学习模型通常在大型标记数据上工作。对这些模型进行推断是计算密集的,消耗大量的内存。神经网络使用内存来存储输入数据,参数(权重)和从每个层的激活,因为输入传播通过网络。在MATLAB培训的深度神经网络使用单精度浮点数据类型。甚至较小的网络甚至需要相当大量的存储器和硬件来执行这些浮点算术运算。这些限制可以禁止将深度学习模型的部署部署到具有低计算能力和更小的内存资源的设备。通过使用较低的精度来存储权重和激活,可以降低网络的内存要求。
您可以使用深度学习工具箱与深度学习工具箱模型量化库支持包来使用深度学习工具箱,通过量化权重,偏置和卷积层的激活来降低深度神经网络的内存占用空间,并卷积层为8位缩放整数数据类型。金宝app然后,您可以使用Matlab Coder™为量化网络生成优化的代码。生成的代码通过使用ARM Compute库利用ARM®处理器SIMD。生成的代码可以作为源代码,静态或动态库或可执行文件集成到您的项目中,或者可以部署到各种ARM CPU平台(如Raspberry PI™)。
这个例子展示了如何为卷积神经网络生成c++代码,该网络使用ARM计算库并在8位整数中执行推理计算。
Matlab在线不支持此示例。金宝app
第三方先决条件
在此示例中,您使用MATLAB编码器为量化的深卷积神经网络生成用于量化的深度卷积神经网络的Optized C ++代码并对图像进行分类。该示例使用预磨挤压
(深度学习工具箱)卷积神经网络。
SqueezeNet在包含1000个对象类别的图像的ImageNet数据集上进行了训练。该网络学习了丰富的特征表示范围广泛的图像。该网络以一幅图像作为输入,输出图像中对象的标签以及每个对象类别的概率。
这个例子包括四个步骤:
修改SqueezeNet神经网络,使用迁移学习对包含五个对象类别的图像进行更小的分类。
量化修改的挤压网网络。
使用Codegen命令为量化网络生成代码。生成的代码通过PIL执行在Raspberry PI目标上运行。
在树莓派上执行生成的PIL MEX。
为了对一组新的图像进行分类,您必须使用迁移学习对预先训练的SqueezeNet卷积神经网络进行微调。在迁移学习中,你将一个预先训练好的网络作为学习新任务的起点。使用迁移学习对网络进行微调,通常比用随机初始化权值从头开始训练网络更快、更容易。通过使用少量的训练图像,您可以快速地将学习到的特征转移到新的任务中。
解压缩并将新图像加载为图像数据存储。这imageDatastore
功能根据文件夹名称自动标记图像,并将数据存储为imageageAtastore.
对象。图像数据存储使您能够存储大的图像数据,包括内存中不适合的数据,并在卷积神经网络训练期间有效地读取批量图像。
解压缩(“MerchData.zip”);imd = imageDatastore ('merchdata'那......“IncludeSubfolders”,真的,......“LabelSource”那'foldernames');[IMDStrain,IMDSValidation] = SpliteachLabel(IMDS,0.7,“随机”);numTrainImages =元素个数(imdsTrain.Labels);idx = randperm (numTrainImages 4);img = imtile (imd,'框架',IDX);图imshow(img)标题(“来自训练数据集的随机图像”);
加载预先训练好的SqueezeNet网络。
网= squeezenet;
物体净
包含了Dagnetwork.
对象。第一层是接受大小227-×227-3的输入图像的图像输入层,其中3是颜色通道的数量。使用分析
(深度学习工具箱)功能要显示网络架构的交互式可视化,以检测网络中的错误和问题,并显示有关网络层的详细信息。图层信息包括层激活和学习参数的大小,学习参数的总数,以及经常性层的状态参数的大小。
inputSize = net.Layers (1) .InputSize;analyzeNetwork(净);
网络提取图像的卷积层的图像特征是最后一种学习层和最终分类层用于对输入图像进行分类。这两层,'conv10'
和'classificationlayer_predictions'
在SqueezeNet中,包含了如何将网络提取的特征组合成类别概率、损失值和预测标签的信息。
要重新培训备用网络以对新图像进行分类,请将这两层替换为适合新数据集的新图层。您可以手动执行此操作或使用辅助功能findLayersToReplace
自动查找这些层。
这是findLayersToReplace
辅助功能:
类型findLayersToReplace.m
% findLayersToReplace(lgraph)查找单层分类层和% graph层的%前面的可学习层(完全连接或卷积)。function [learnabllayer,classLayer] = findLayersToReplace(lgraph) if ~isa(lgraph,' net.cnn.LayerGraph') error('Argument must be a LayerGraph object.') end %获取源、目标和层名。src =字符串(lgraph.Connections.Source);dst =字符串(lgraph.Connections.Destination);layerNames =字符串({lgraph.Layers.Name} ');找到分类层。层图必须有一个%分类层。= arrayfun(@(l)…(isa (l, nnet.cnn.layer.ClassificationOutputLayer) | isa (l ' nnet.layer.ClassificationLayer ')),…lgraph.Layers); if sum(isClassificationLayer) ~= 1 error('Layer graph must have a single classification layer.') end classLayer = lgraph.Layers(isClassificationLayer); % Traverse the layer graph in reverse starting from the classification % layer. If the network branches, throw an error. currentLayerIdx = find(isClassificationLayer); while true if numel(currentLayerIdx) ~= 1 error('Layer graph must have a single learnable layer preceding the classification layer.') end currentLayerType = class(lgraph.Layers(currentLayerIdx)); isLearnableLayer = ismember(currentLayerType, ... ['nnet.cnn.layer.FullyConnectedLayer','nnet.cnn.layer.Convolution2DLayer']); if isLearnableLayer learnableLayer = lgraph.Layers(currentLayerIdx); return end currentDstIdx = find(layerNames(currentLayerIdx) == dst); currentLayerIdx = find(src(currentDstIdx) == layerNames); end end
要使用此功能来替换最终图层,请运行这些命令:
Lgraph = LayerGraph(网);[LearalableLayer,ClassLayer] = findlayerstoreplace(LAPHAGE);numclasses = numel(类别(imdstrain.labels));newconvlayer = convolution2dlayer([1,1],numcrasses,'wexerlearnratefactor'那......10,'biaslearnratefactor'10,“名称”那'new_conv');Lgraph =替换剂(LGROPE,'conv10', newConvLayer);newClassificatonLayer = classificationLayer ('名称'那“new_classoutput”);Lgraph =替换剂(LGROPE,'classificationlayer_predictions',newclassificatonlayer);
该网络要求所有输入图像具有尺寸227-×227-3,但图像数据存储中的每个图像具有不同的大小。使用增强图像数据存储来自动调整培训图像的大小。指定要在训练图像上执行的这些附加增强操作:随机翻转训练图像围绕垂直轴,并随机将其水平和垂直多达30个像素。数据增强有助于防止网络过度拟合并记住培训图像的确切细节。
pixelRange = [-30 30];imageAugmenter = imageDataAugmenter (......“RandXReflection”,真的,......'randxtranslation',pixelrange,......'randytranslation',pixelrange);Augimdstrain = AugmentedimageGedataStore(Inputsize(1:2),IMDstrain,......'dataaugmentation', imageAugmenter);
要自动调整验证图像的大小而不执行进一步的数据增强,请使用增强图像数据存储,而无需指定任何其他预处理操作。
augimdsValidation = augmentedImageDatastore (inputSize (1:2), imdsValidation);
指定培训选项。对于转移学习,将特征与预磨料网络的早期层保持(转移的层重量)保持。为了减慢转移层的学习,将初始学习率设置为小值。在上一步中,您可以增加卷积层的学习率因子,以加速新的最终层的学习。这种学习速率设置的组合只会在新层次中快速学习,并在其他层中的学习较慢。在进行转移学习时,您不需要为尽可能多的时期训练。epoch是整个培训数据集的完整培训周期。指定迷你批量大小为11,以便在每个时代,您考虑所有数据。在培训期间,软件在每个培训期间验证网络验证频繁
迭代。
选择= trainingOptions ('sgdm'那......“MiniBatchSize”,11,......'maxepochs'7,......'italllearnrate',2e-4,......'洗牌'那“every-epoch”那......“ValidationData”,augimdsvalidation,......“ValidationFrequency”3,......'verbose'、假);
培训由转移和新层组成的网络。
Nettransfer = Trainnetwork(Augimdstrain,Lgraph,选项);ClassNames = NetTransfer.Layers(END).Classes;节省('mysqueezenet.mat'那“netTransfer”);
创建一个dlquantizer.
对象,并指定要量化的网络。
QuantObj = DlQuantizer(NetTransfer,“ExecutionEnvironment”那'中央处理器');
使用校准
使用示例输入锻炼网络并收集范围信息的功能。这校准
功能练习网络,并在网络的卷积和完全连接的层中收集权重和偏置的动态范围,以及网络的所有层中激活的动态范围。该函数返回一个表。表中的每一行包含用于优化网络的学习参数的范围信息。
Calresults = Quantobj.Calibrate(Augimdstrain);节省(“squeezenetCalResults.mat”那'calresults');节省(“squeezenetQuantObj.mat”那'quantobj');
在本例中,您为入口点函数生成代码predict_int8
。此功能使用Coder.LoadDeePlearningnetwork.
函数加载深度学习模型和构建和设置CNN类。然后,入口点函数通过使用该响应来预测响应预测
(深度学习工具箱)函数。
类型预测_INT.M.
函数out = predict_int8(netfile,in)持久性mynet;如果是isempty(mynet)mynet = coder.loaddeeplearinnnetwork(netfile);结束=预测(Mynet,In);结尾
要生成PIL MEX功能,请为静态库创建代码配置对象,并将验证模式设置为“公益诉讼”
。将目标语言设置为C ++。
cfg = coder.config (“自由”那'ecoder',真正的);cfg。VerificationMode =“公益诉讼”;cfg.targetlang ='c ++';
为ARM Compute库创建一个深度学习配置对象,并指定库版本。对于此示例,假设Raspberry PI硬件中的ARM计算库为版本20.02.1。
dlcfg =编码器。DeepLearningConfig (“arm-compute”);dlcfg。ArmComputeVersion ='20 .02.1';
设置的属性dlcfg.
为低精度/INT8推断生成代码。
dlcfg.calibrationResultfile =.“squeezenetQuantObj.mat”;dlcfg.datatype =.“int8”;
6.设置DeepLearningConfig
的属性CFG.
到dlcfg.
。
cfg.deeplearningconfig = dlcfg;
7.使用MATLAB支持包的树莓派金宝app函数,raspi.
,创建与Raspberry PI的连接。在以下代码中,替换:
raspiname.
使用覆盆子pi的名称
用户名
用你的用户名
密码
用你的密码
% r = raspiname ('raspiname','username','password');
8.创建A.编码器。硬件
raspberry pi对象并将其附加到代码生成配置对象。
% hw =编码器。硬件(覆盆子π);% cfg。硬件= hw;
9.使用使用方法生成PIL MEX功能Codegen.
命令
% codegen -config cfg predict_int8 -args {code . constant ('mySqueezenet.mat'), ones(227,227,3,'uint8')}
输入图像的大小应与网络的输入大小相同。读取要分类的图像,并将其调整为网络的输入大小。这个大小调整稍微改变了图像的宽高比。
% testImage = imread("MerchDataTest.jpg");%testimage = imresize(testimage,输入(1:2));
比较深入学习工具箱的预测预测
功能和赋予的PIL MEX功能predict_int8_pil
,分别对输入图像调用这两个函数。
% predictScores(:,1) = predict(netTransfer, testestimate)';%predictscores(:,2)= predict_int8_pil('mysqueezenet.mat',testimage);
将预测的标签及其相关概率显示为直方图。
% h =数字;%H.Position(3)= 2 * H.Position(3);% ax1 = subplot(1,2,1);% ax2 = subplot(1,2,2);%图像(AX1,Testimage);% barh (ax2 predictScores)%包含(ax2,“概率”)%YTicklabels(AX2,ClassNames)%ax2.xlim = [0 1.1];% ax2。YAxisLocation = '左';% legend('Matlab Single','arm-compute 8位整数');% sgtitle('使用Squeezenet预测')% saveas (gcf SqueeznetPredictionComparison.jpg);%关闭(GCF);imshow ('squeeznetpredictioncomparison.jpg');
Codegen.
|Coder.LoadDeePlearningnetwork.
|校准
(深度学习工具箱)|dlquantizationOptions.
(深度学习工具箱)|dlquantizer.
(深度学习工具箱)|证实
(深度学习工具箱)