52matlab技术网站,matlab教程,matlab安装教程,matlab下载

标题: 四大经典轻量级网络之二:SqueezeNet [打印本页]

作者: matlab的旋律    时间: 2020-9-1 19:00
标题: 四大经典轻量级网络之二:SqueezeNet
本帖最后由 matlab的旋律 于 2020-9-1 19:14 编辑

1.前言
从上世纪90年代以 LeNet为开始代表的卷积神经网络,2012年又以AlexNet为起始点爆发,在深度学习领域中成为炙手可热的网络框架,特别是在机器视觉领域更是超群绝伦。此后的ZF-Net到VGG-Nets,GoogleNet再到ResNet以及DenseNet,以追求提升识别精确率为主要目的,采用手段的主要方向包括加深网络结构和增强卷积模块功能,同时这也导致了整个用于识别的网络越来越复杂,需要的内存和算力也大大增加。SqueezeNet开辟了另外一个方向:在保证模型精度不降低的前提下,最大程度的提高运算速度。它能够在ImageNet数据集上达到近似AlexNet的效果,但是参数量相比AlexNet少了50倍,同时结合模型压缩技术 Deep Compression,SqueezeNet模型文件相比AlexNet小约510倍。
SqueezeNet与几乎同一时期提出的MobileNet、ShuffleNet和Xception被称为当前的四大轻量级模型,但SqueezeNet是最早在arXiv上公开的。
[attach]305[/attach]
2.网络结构
SqueezeNet创新点在于提出了fire module,包括两个部分,squeeze和expand,如下图所示。
[attach]306[/attach]
其中的squeeze 在 SqueezeNet的结构中表示一个 squeeze 层,该层采用 1*1 卷积核对上一层 feature map进行卷积,其主要目的是降低feature map 的维数。expand使用的Inception结构,包括1*1和3*3卷积,然后拼接,Matlab实现的代码如下:
  1. lgraph = layerGraph();
  2. tempLayers = [
  3.     convolution2dLayer([1 1],16,"Name","fire2-squeeze1x1")
  4.     reluLayer("Name","fire2-relu_squeeze1x1")];
  5. lgraph = addLayers(lgraph,tempLayers);
  6. tempLayers = [
  7.     convolution2dLayer([3 3],64,"Name","fire2-expand3x3","Padding",[1 1 1 1])
  8.     reluLayer("Name","fire2-relu_expand3x3")];
  9. lgraph = addLayers(lgraph,tempLayers);

  10. tempLayers = [
  11.     convolution2dLayer([1 1],64,"Name","fire2-expand1x1")
  12.     reluLayer("Name","fire2-relu_expand1x1")];
  13. lgraph = addLayers(lgraph,tempLayers);

  14. tempLayers = [
  15. depthConcatenationLayer(2,"Name","fire2-concat")];

  16. lgraph = addLayers(lgraph,tempLayers);
  17. lgraph = connectLayers(lgraph,"fire2-relu_squeeze1x1","fire2-expand3x3");
  18. lgraph = connectLayers(lgraph,"fire2-relu_squeeze1x1","fire2-expand1x1");
  19. lgraph = connectLayers(lgraph,"fire2-relu_expand1x1","fire2-concat/in1");
  20. lgraph = connectLayers(lgraph,"fire2-relu_expand3x3","fire2-concat/in2");
  21. plot(lgraph)%绘图
复制代码
得到的流程图如下图图所示:
[attach]307[/attach]
由于两个卷积过程使用的stride都是1,因此输出的数据结构仅仅在于通道数上的差异,拼接后的数据是1*1和3*3卷积后的数据在通道上之和。其中所有的1*1和3*3卷积使用的padding方式分别为[0,0,0,0]和[1,1,1,1]。

整个SqueezeNet的结构使用Matlab中plot函数对深度学习网络结构的表示如下图所示:
[attach]308[/attach]
从图中可以看出SqueezeNet中一共包含了8个fire module,其中在第3和第5个fire module使用了3*3的最大池化,对应池化层的stride都为2*2,将进行下采样的池化层下移动的原因是作者认为较大的Feature Map含有更多的信息。当然这样的操作虽然会提升网络的精度,但同时也带来一个问题,也就是会导致网络的计算量增加。
3.模型迁移
在深度学习行业内一个普遍存在的问题就是在面对某一领域的某一特定问题时,找到足够充分的训练数据非常困难。因此,如果能够使用其他数据集训练得到的成熟模型,经过一定的修改和完善,然后可以复用在与之类似的领域,这样就可以大大的缓解数据源不足导致的问题。当前,能够解决这个问题的一个关键技术就是迁移学习。
迁移学习主要过程包括:
1)      使用现成的数据集训练好模型,保存为预训练模型;
2)      在预训练模型中定位输出为可复用特征(feature)的层次(layer);
3)      将可复用特征的层次的输出作为新模型的输入,进行重新训练。
其中,这里进行预训练的数据集和迁移学习的数据集可以对应完全不同的待解问题,例如样本的尺寸相同,样本标签数目却不一样等。由于此前的预训练模型已经学习得到了数据的组织模式,因此进行迁移学习的网络只需要学习数据集中针对某一特定问题的相关性问题就可以了。简而言之,迁移学习具有的优势可以总结为:
1)      适应小样本,迁移学习能够将大样本数据进行训练的模型迁移到只有小样本的数据领域,实现小样本数据的落地。
2)      提高鲁棒性,通过迁移学习所得到的模型具有普适性,可以迁移到多个不同的领域而不至于产生显著的性能下降。
3)      个性化定制,对应每个问题的个性化样本规模可能不大,但是在通过大数据训练的模型基础上进行迁移学习,就能很好的解决个性化的问题,也可以形象的比如为站在巨人的肩膀上。

下面使用小迈步视频课程上的一个例子,对SqueezeNet进行迁移学习用于Cap、Cube、MWBottle、NFSQ、PlayingCards、Screwdriver和Torch七大类物品的识别。对应的迁移学习步骤和代码如下:
  1. %加载Squeezenet模型并修改
  2. net = squeezenet();

  3. lgraph = layerGraph(net);
  4. inputSize = net.Layers(1).InputSize;
  5. numClasses = numel(categories(imdsTrain.Labels));

  6. % 删除squeezenet的最后5层   
  7. lgraph = removeLayers(lgraph, {'conv10', 'relu_conv10', ...
  8. 'pool10', 'prob', 'ClassificationLayer_predictions'});

  9. %定义一个卷积核大小为2的卷积层           
  10. conv10 = convolution2dLayer( ...
  11.                 1, numClasses, ...
  12.                 'Stride', 1, ...
  13.                 'Padding', 0, ...
  14.                 'Name', 'conv10');

  15. relu_conv10 = reluLayer('Name', 'relu_conv10');

  16. pool10 = averagePooling2dLayer( 14, 'Stride', 1, 'Padding', 0, 'Name', 'pool10');

  17. %其中新网络的最后5层如下:
  18. newLayers = [
  19.                 conv10
  20.                 relu_conv10
  21.                 pool10
  22.                 softmaxLayer('Name', 'softmax')
  23.                 classificationLayer('Name', 'classoutput')];

  24. % 添加并连接到网络的最后一层 'drop9'层
  25. lgraph = addLayers(lgraph, newLayers);
  26. lgraph = connectLayers(lgraph, 'drop9', 'conv10');
复制代码
4.实验结果
对上述迁移学习的模型进行训练,其中具体训练的参数设置可以点击阅读原文参看对应的Matlab源码。其中训练过程详细图示如下图。可以看出经过20轮训练集和验证集都达到了100%的准确率,损失函数值也收敛到了近0值,另外使用的时间仅为42秒。
[attach]309[/attach]
如下图所示,通过对测试集4张图片的识别其结果也完全正确,这些也说明轻量级网络SqueezeNet在迁移学习上高效性,以及部署到性能较低的单片机上的可行性。
[attach]310[/attach]
参考文献:
博客:https://blog.csdn.net/cumttzh/article/details/79822766
视频:https://www.bilibili.com/video/BV1Kt4y1D7H6?p=3
论文:SQUEEZENET: ALEXNET-LEVEL ACCURACYWITH 50X FEWER PARAMETERS AND <0.5MB MODEL SIZE
欢迎加入深度学习算法交流群学习交流。

[attach]311[/attach]


作者: matlab的旋律    时间: 2020-9-1 19:16
本帖最后由 matlab的旋律 于 2020-9-1 19:20 编辑

用于迁移学习测试的实例程序
  1. %准备训练及测试用图片集
  2. %载入图库
  3. imds = imageDatastore('TrainData',...
  4.     'IncludeSubfolders',true,...
  5.     'LabelSource','foldernames');
  6. [imdsTrain,imdsValidation] = splitEachLabel(imds,0.7,'randomized');

  7. %加载Squeezenet模型并修改
  8. net = squeezenet();

  9. lgraph = layerGraph(net);
  10. inputSize = net.Layers(1).InputSize;
  11. numClasses = numel(categories(imdsTrain.Labels));

  12. % Remove last 5 layers   
  13. lgraph = removeLayers(lgraph, {'conv10', 'relu_conv10', ...
  14. 'pool10', 'prob', 'ClassificationLayer_predictions'});

  15. % define a conv layer with a filter size of 2           
  16. conv10 = convolution2dLayer( ...
  17.                 1, numClasses, ...
  18.                 'Stride', 1, ...
  19.                 'Padding', 0, ...
  20.                 'Name', 'conv10');

  21. relu_conv10 = reluLayer( ...
  22.                 'Name', 'relu_conv10');

  23. pool10 = averagePooling2dLayer( ...
  24.                 14, ...
  25.                 'Stride', 1, ...
  26.                 'Padding', 0, ...
  27.                 'Name', 'pool10');

  28. % Last 5 layers of the new network would be
  29. newLayers = [
  30.                 conv10
  31.                 relu_conv10
  32.                 pool10
  33.                 softmaxLayer('Name', 'softmax')
  34.                 classificationLayer('Name', 'classoutput')];

  35. % Add and connect to the last layer of the network 'drop9'
  36. lgraph = addLayers(lgraph, newLayers);
  37. lgraph = connectLayers(lgraph, 'drop9', 'conv10');
  38. plot(lgraph)

  39. %调整图库
  40. pixelRange = [-30 30];
  41. scaleRange = [0.9 1.1];
  42. imageAugmenter = imageDataAugmenter( ...
  43.     'RandXReflection',true, ...
  44.     'RandXTranslation',pixelRange, ...
  45.     'RandYTranslation',pixelRange, ...
  46.     'RandXScale',scaleRange, ...
  47.     'RandYScale',scaleRange);
  48. augimdsTrain = augmentedImageDatastore(inputSize(1:2),imdsTrain,...
  49.     'DataAugmentation',imageAugmenter);

  50. augimdsValidation = augmentedImageDatastore(inputSize(1:2),imdsValidation);

  51. %进行模型训练
  52. options = trainingOptions('sgdm',...
  53.     'ExecutionEnvironment','gpu',...
  54.     'MiniBatchSize',10,...
  55.     'MaxEpochs',20,...
  56.     'InitialLearnRate',0.0001,...
  57.     'ValidationData',augimdsValidation,...
  58.     'ValidationFrequency',3,...
  59.     'ValidationPatience',Inf,...
  60.     'Verbose',false,...
  61.     'Plots','training-progress',...
  62.     'ExecutionEnvironment','gpu');    % 此处为GPU训练,可改为CPU或PCT

  63. net = trainNetwork(augimdsTrain,lgraph,options);

  64. %测试训练好的模型

  65. [YPred,scores] = classify(net,augimdsValidation);
  66. idx = randperm(numel(imdsValidation.Files),4);
  67. figure
  68. for i = 1:4
  69.     subplot(2,2,i)
  70.     I = readimage(imdsValidation,idx(i));
  71.     imshow(I)
  72.     label = YPred(idx(i));
  73.     title(string(label));
  74. end
复制代码



作者: matlab的旋律    时间: 2023-10-31 02:08
本帖最后由 matlab的旋律 于 2023-10-31 03:18 编辑

上述迁移学习方法是在预训练模型上根据具体需求修改最后几个层(最常见的是修最后几个全连接层和最后的输出层),然后在预训练模型参数基础重新训练模型。这种在预训练模型基础不冻结参数进行微调的迁移学习方法,具有一下四方面的优势:       总得来说,不冻结层参数的迁移学习可能增加过拟合的风险,有限制模型学习能力的问题,并且可能无法适应新任务的特征需求。此外,训练时间也可能较长。为了避免过拟合、保持特征提取能力、保持预训练模型的适应性和提高训练效率,同时在迁移学习中可以更好地利用预训练模型的知识,针对新任务进行微调,一种方法是冻结预训练模型中部分层参数。还是以squeezenet为例给出matlab程序:
  1. %准备训练及测试用图片集
  2. %载入图库
  3. imds = imageDatastore('TrainData',...
  4.     'IncludeSubfolders',true,...
  5.     'LabelSource','foldernames');
  6. [imdsTrain,imdsValidation] = splitEachLabel(imds,0.7,'randomized');

  7. %加载Squeezenet模型并修改
  8. net = squeezenet();

  9. lgraph = layerGraph(net);
  10. inputSize = net.Layers(1).InputSize;
  11. numClasses = numel(categories(imdsTrain.Labels));

  12. % Remove last 5 layers   
  13. lgraph = removeLayers(lgraph, {'conv10', 'relu_conv10', ...
  14. 'pool10', 'prob', 'ClassificationLayer_predictions'});

  15. % define a conv layer with a filter size of 2           
  16. conv10 = convolution2dLayer( ...
  17.                 1, numClasses, ...
  18.                 'Stride', 1, ...
  19.                 'Padding', 0, ...
  20.                 'Name', 'conv10');

  21. relu_conv10 = reluLayer( ...
  22.                 'Name', 'relu_conv10');

  23. pool10 = averagePooling2dLayer( ...
  24.                 14, ...
  25.                 'Stride', 1, ...
  26.                 'Padding', 0, ...
  27.                 'Name', 'pool10');

  28. % Last 5 layers of the new network would be
  29. newLayers = [
  30.                 conv10
  31.                 relu_conv10
  32.                 pool10
  33.                 softmaxLayer('Name', 'softmax')
  34.                 classificationLayer('Name', 'classoutput')];

  35. % Add and connect to the last layer of the network 'drop9'
  36. lgraph = addLayers(lgraph, newLayers);
  37. lgraph = connectLayers(lgraph, 'drop9', 'conv10');

  38. %由于lgraph声明为layerGraph类,而layerGraph的属性Layers为只读类型,因此需要使用replaceLayer实现对应冻结层的参数替换
  39. Layers = freezeWeights(lgraph.Layers(1:16));%freezeWeights函数将对应层的学习率设置为0达到冻结该层参数的目的
  40. for k = 1:16
  41.     lgraph = replaceLayer(lgraph,lgraph.Layers(k).Name,Layers(k));
  42. end
  43. %由于冻结层的梯度不需要进行计算,从而在训练过程中冻结层的参数并不会更新,因此能够加快网络训练

  44. plot(lgraph)

  45. %调整图库
  46. pixelRange = [-30 30];
  47. scaleRange = [0.9 1.1];
  48. imageAugmenter = imageDataAugmenter( ...
  49.     'RandXReflection',true, ...
  50.     'RandXTranslation',pixelRange, ...
  51.     'RandYTranslation',pixelRange, ...
  52.     'RandXScale',scaleRange, ...
  53.     'RandYScale',scaleRange);
  54. augimdsTrain = augmentedImageDatastore(inputSize(1:2),imdsTrain,...
  55.     'DataAugmentation',imageAugmenter);

  56. augimdsValidation = augmentedImageDatastore(inputSize(1:2),imdsValidation);

  57. %进行模型训练
  58. options = trainingOptions('sgdm',...
  59.     'ExecutionEnvironment','gpu',...
  60.     'MiniBatchSize',10,...
  61.     'MaxEpochs',20,...
  62.     'InitialLearnRate',0.0001,...
  63.     'ValidationData',augimdsValidation,...
  64.     'ValidationFrequency',3,...
  65.     'ValidationPatience',Inf,...
  66.     'Verbose',false,...
  67.     'Plots','training-progress',...
  68.     'ExecutionEnvironment','gpu');    % 此处为GPU训练,可改为CPU或PCT

  69. net = trainNetwork(augimdsTrain,lgraph,options);

  70. %测试训练好的模型

  71. [YPred,scores] = classify(net,augimdsValidation);
  72. idx = randperm(numel(imdsValidation.Files),4);
  73. figure
  74. for i = 1:4
  75.     subplot(2,2,i)
  76.     I = readimage(imdsValidation,idx(i));
  77.     imshow(I)
  78.     label = YPred(idx(i));
  79.     title(string(label));
  80. end
复制代码
训练过程的曲线如下图:
[attach]361[/attach]
通过对比在预训练模型基础不冻结参数进行微调的迁移学习方法的训练过程曲线,可以看出,冻结预训练模型部分参数的迁移学习方法收敛更快,鲁棒性也更强。







欢迎光临 52matlab技术网站,matlab教程,matlab安装教程,matlab下载 (http://test.52matlab.com/) Powered by Discuz! X3.2