利用MatConvNet搭建自己的网络并训练(调参)

本文转载于博客:https://blog.csdn.net/qq_20259459 和 作者邮箱( jinweizhi93@gmai.com )。

有关调参该作者也给出了详细的介绍(https://blog.csdn.net/qq_20259459/article/details/70316511

前期工作:下载安装matlab和下载MatConvNet以及下载GPU相关文件和配置GPU。
具体请参见我之前的文章:
1. 深度学习 2. MatConvNet(CNN)的配置和相关实验结果,CNN学习使用 :
http://blog.csdn.net/qq_20259459/article/details/54092277
2. 深度学习 3. MatConvNet (CNN)的介绍和下载以及CPU和GPU的安装配置,Matlab2016 :
http://blog.csdn.net/qq_20259459/article/details/54093550


准备工作:
1. 打开Matlab,配置相关文件的路径(http://blog.csdn.net/qq_20259459/article/details/54092277)
2. 输入 mex -setup cpp
3. 输入 vl_compilenn
4. 输入 compileGPU
没有报错则配置完成。


开始,新建编辑页 cnn_cifar_my :

这是外层调参和构建imdb结构体的code。

关于调参我会在后面单取一篇来介绍。

函数相互调用顺序:主函数 function [net, info] = cnn_cifar_my(varargin) :

一、. 首先初始化网络:

opts.batchNormalization = false ;                   %选择batchNormalization的真假
opts.network = [] ;                                 %初始化一个网络
opts.networkType = 'simplenn' ;                     %选择网络结构 %%% simplenn %%% dagnn
[opts, varargin] = vl_argparse(opts, varargin) ;    %调用vl_argparse函数

sfx = opts.networkType ;                                                %sfx=simplenn
if opts.batchNormalization, sfx = [sfx '-bnorm'] ; end                  %这里条件为假
opts.expDir = fullfile(vl_rootnn, 'data', ['cifar10-' sfx]) ;    %选择数据存放的路径:data\cifar-baseline-simplenn
[opts, varargin] = vl_argparse(opts, varargin) ;                        %调用vl_argparse函数

opts.dataDir = fullfile(vl_rootnn, 'data', 'cifar10') ;                   %选择数据读取的路径:data\matconvnet-1.0-beta23\data\cifar
opts.imdbPath = fullfile(opts.expDir, 'imdb.mat');                      %选择imdb结构体的路径:data\data\cifar-baseline-simplenn\imdb
opts.whitenData = true ;
opts.contrastNormalization = true ;
opts.train = struct() ;                                                 %选择训练集返回为struct型
opts = vl_argparse(opts, varargin) ;                                    %调用vl_argparse函数

%选择是否使用GPU,使用opts.train.gpus = 1,不使用:opts.train.gpus = []。
%有关GPU的安装配置请看我的博客:http://blog.csdn.net/qq_20259459/article/details/54093550
if ~isfield(opts.train, 'gpus'), opts.train.gpus = [1]; end; 

二、 调用网络结构函数 cnn_cifar_init_my (这个函数用于构造自己的网络结构) :

if isempty(opts.network)                                                    %如果原网络为空:
  net = cnn_cifar_init_my('batchNormalization', opts.batchNormalization, ...   %   则调用cnn_cifat_init网络结构
    'networkType', opts.networkType) ;
else                                                                        %否则:
  net = opts.network ;                                                      %   使用上面选择的数值带入现有网络
  opts.network = [] ;
end

三、 接下来将调用得到imdb的相关函数(用于训练的数据集):

if exist(opts.imdbPath, 'file')                         %如果cifar中存在imdb的结构体:
  imdb = load(opts.imdbPath) ;                          %   载入imdb
else                                                    %否则:
  imdb = getMnistImdb(opts) ;                           %   调用getMnistImdb函数得到imdb并保存
  mkdir(opts.expDir) ;                                  
  save(opts.imdbPath, '-struct', 'imdb') ;
end
%arrayfun函数通过应用sprintf函数得到array中从1到10的元素并且将其数字标签转化为char文字型
net.meta.classes.name = arrayfun(@(x)sprintf('%d',x),1:10,'UniformOutput',false) ;

四、 然后调用网络类型(simplenn,dagnn):

switch opts.networkType                                     %选择网络类型:
  case 'simplenn', trainfn = @cnn_train ;                   %   1.simplenn
  case 'dagnn', trainfn = @cnn_train_dag ;                  %   2.dagnn
end

%调用训练函数,开始训练:find(imdb.images.set == 3)为验证集的样本
[net, info] = trainfn(net, imdb, getBatch(opts), ...        
  'expDir', opts.expDir, ...
  net.meta.trainOpts, ...
  opts.train, ...
  'val', find(imdb.images.set == 3)) ;

 

综上所述,我们的流程是:1. 输入网络和参数的初始值。2. 构建训练网络结构。3. 建立训练数据集。4. 选择训练网络的类型

 

注:
imdb结构体:

1. 这是用于cnn_train中的结构体,也就是实际训练的部分。

2. 该结构体内共有4个部分,由data,label,set,class组成。

            data:包含了train data和test data。

             label:包含了train label和test label。

            set:set的个数与label的个数是相等的,set=1表示这个数据是train data,set=3则表示这个数据是test data。   以此方法用于计算机自己判断的标准。

            class:与数据中的class完全一样。

3. imdb构造时遵循train在上层,test在下层的顺序。

4. 相关的data需要进行泛化处理。


下面以我自己的数据为例构建一个自己的imdb:

function imdb = getMnistImdb(opts)
%% --------------------------------------------------------------
%   函数名:getMnistImdb
%   功能:  1.从mnist数据集中获取data
%           2.将得到的数据减去mean值
%           3.将处理后的数据存放如imdb结构中
% ------------------------------------------------------------------------
% Preapre the imdb structure, returns image data with mean image subtracted

load('TR.mat'); 
load('TT.mat');
load('TRL.mat');
load('TTL.mat');

x1 = TR;
x2 = TT;
y1 = TRL;
y2 = TTL;

%set = 1 对应训练;set = 3 对应的是测试
set = [ones(1,numel(y1)) 3*ones(1,numel(y2))];              %numel返回元素的总数
data = single(reshape(cat(3, x1, x2),128,256,1,[]));          %将x1的训练数据集和x2的测试数据集的第三个维度进行拼接组成新的数据集,并且转为single型减少内存
dataMean = mean(data(:,:,:,set == 1), 4);                   %求出训练数据集中所有的图像的均值
data = bsxfun(@minus, data, dataMean) ;                     %利用bsxfun函数将数据集中的每个元素逐个减去均值

%将数据存入imdb结构中
imdb.images.data = data ;                                   %data的大小为[128 256 1 70000]。 (60000+10000) 这里主要看上面的data的size。
imdb.images.data_mean = dataMean;                           %dataMean的大小为[128 256]
imdb.images.labels = cat(2, y1', y2') ;                       %拼接训练数据集和测试数据集的标签,拼接后的大小为[1 70000]
imdb.images.set = set ;                                     %set的大小为[1 70000],unique(set) = [1 3]
imdb.meta.sets = {'train', 'val', 'test'} ;                 %imdb.meta.sets=1用于训练,imdb.meta.sets=2用于验证,imdb.meta.sets=3用于测试

%arrayfun函数通过应用sprintf函数得到array中从0到9的元素并且将其数字标签转化为char文字型
imdb.meta.classes = arrayfun(@(x)sprintf('%d',x),0:9,'uniformoutput',false) ;

注:
1. data = single(reshape(cat(3, x1, x2),128,256,1,[]));  这里[128,256,1]是我的数据的size。如果你是三维的数据,比如是cifar则需要将这里的1变为3。且cat的3需要变为4。
2. 针对三维数据切勿轻易使用reshape函数,尽可能的用cat函数组建,因为reshape是基于纵向来构造的。


下面我将为大家介绍如何构建自己的网络:

1. Conv.layer:

net.layers{end+1} = struct('type', 'conv', ...          %卷积层C,randn函数产生4维标准正态分布矩阵,设置偏置有20个
                           'weights', {{0.05*randn(3,3,1,32, 'single'), ...
                           zeros(1, 32, 'single')}}, ...  %filter大小是3*3*1
                           'learningRate', lr, ...
                           'stride', 1, ...             %stride = 1
                           'pad', 0) ;         

注:
(1)weights既是filter。这里的3*3为filter的大小(长和宽),1是input的图片的厚度(如果图片是rgb则这里将是3),32是此层filter的个数。
(2)stride等于该filter的移动步伐。
(3)当filter的size等于1*1的时候,表示为fully connection。

2. Rule.layer:

net.layers{end+1} = struct('type', 'relu') ; 

3. maxPooling.layer:

net.layers{end+1} = struct('type', 'pool', ...          %池化层P
                           'method', 'max', ...
                           'pool', [2 2], ...           %池化核大小为2*2
                           'stride', 2, ...
                           'pad', 0) ;

4. dropout.layer:

net.layers{end+1} = struct('type', 'dropout', 'name', 'dropout2', 'rate', 0.5) ;

注:这里我们给的drop rate 是0.5 。

5. softmax.layer:

net.layers{end+1} = struct('type', 'softmaxloss') ;     %softmax层


下面我将说明网络构建的思路:
1. 一般来说作为最原始的lenet的网络结构,我们最好的构造是C-R-C-R-P为一个block。
2. C层之后一定要加上R层,这是构建原理之一,linear的C加上nonlinear的R,相信学过NN的或者能用的这个人都会知道吧。
3. softmax的input必须为1*1的size。为了实现这个就必须计算整体网络的构造,我的建议是画图,自己先在纸上画好自己的网络结构,计算好最后为1*1。
4. 关于图片缩小的计算公式:
      (1)Conv.layer: [(N-F)/stride]+1
               这里N是input的size,F是filter的size。
      (2)Pooling.layer: 一般说来pooling层是不用改变的,都是缩小2分之1。
5. 如果data的size过小,而希望增加C层来进行深度的网络构造,那么我们就需要用到padding。
公式:padding size = (F-stride)/2 这里F是filter的size。这样我们的C层就不会减小图片,从而进行构造深度网络。


整体思路:
我们训练的过程中用到的无非就三个大的步骤:得到数据,训练,结果分析。
数据:
1.得到好的且可以训练的数据是很重要的,许多时候不能收敛的情况都是坏的或者错误的数据处理操作导致的。因为我们大部分用的是现有的数据库,所以我们在下载数据库之后需要了解清楚数据库的构成,比如Cifar-10和-100的数据库就是条状的,需要进行相关的处理。这个我们前面也说过。
2.数据的分成一般来说是train data =70% validation data =15% test data =15%. 
3.数据输入正确以后,我们需要进行相关的normalization的处理。(这部非常的重要)
4.正则化处理结束之后,我们就可以将相关的data,label, class,class name都放入imdb结构体中,imdb我在前一篇说过了,这才是训练的本体结构。
训练:
1.如果我们确认input的数据是对的,那么我们可以开始我们的训练了。
2.构建训练的网络。网络的构建或者是网络中某一层的创建都是现在深度学习论文的大热,好的网络结构的提出也是论文的大热。所以我们需要不断的训练,不断的改参数,才能自己找到更好的网络结构。在之前的文章中我一直都是用的是LeNet的网络结构和vgg的网络结构。因为这些都是最基础的网络构型,其他的比如NIN这种后代网络都是衍生体。所以我还是会使用LeNet的网络结构来介绍。如果大家有兴趣的话可以阅读相关的paper。
3. 我们知道最最常用的网络单元有:Convolution, ReLu, Pooling(max,average), Dropout., Fully connection, Softmax.
4. 对于LeNet中,我们习惯用C-R-P的block。而在vgg中提出了小的filter组合提升性能的想法:C-R-C-R-P的block。
5.Dropout一般来说我们使用在FC层之前的,不过在最新的论文中也有人提出将D层用在前面的网络中减轻参数。这里我还是提倡大家不要轻易多增加D层,只要在FC前添加即可,rate一般为0.5
6. FC和S层没有什么好说的,不过在之前GoogleNet的网络中已经去除了FC,从而大大的降低了参数。不过这里GN只是一个特列我们不要轻易模仿。
7.我个人最最提倡的还是vgg的构型,我个人的训练中vgg的构型还是效果非常好的。
8.整个网络我们为的就是得到有效的features。
9. FC层的input的大小需为1*1,因此我这里建议正方形的数据库,个人尝试过长方形,可以通过改变filter最终得到1*1的FC的input。但是效果非常不好,我也不能一定说长方形不好,但是还是再次强调大家的数据库的大小最好是为正方形。(这也是目前大家所默认的)
10. 为了得到FC的input是1*1的大小,我们就需要巧妙的用C层和P层来减小原始输入数据的大小。这里的两个公式是需要大家记好的:
关于图片缩小的计算公式:
(1)Conv.layer:   [(N-F)/stride]+1   这里N是input的size,F是filter的size。
(2)如果data的size过小,而希望增加C层来进行深度的网络构造,那么我们就需要用到padding。 公式:padding size = (F-stride)/2 这里F是filter的size。这样我们的C层就不会减小图片,从而进行构造深度网络。
(3)MaxPooling: output = [(N-F)/stride]+1 这里N是input的size,F是filter的size。 但是一般来说我们使用 F=2,S=2的结构,也就是缩小一半。这里的意思就是我们取每一个2*2的区域内最大值(feature最为突出的值)组成新的feature maps。



原文:https://blog.csdn.net/qq_20259459/article/details/65633407 

原文:https://blog.csdn.net/qq_20259459/article/details/69526065 

  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 深度学习是当今计算机科学领域最为热门的研究方向之一,其在图像分类、语言识别、自然语言处理等诸多领域都有广泛的应用。而卷积神经网络(CNN)是深度学习中最为核心的模型之一,它能够有效地提取图像的特征并进行分类。本文将介绍如何使用matlab搭建卷积神经网络。 首先,我们需要准备好所需的数据集,这是构建卷积神经网络的必要条件。可以在网上找到一些现成的数据集,如MNIST手写数字数据集,CIFAR-10图像分类数据集等等。 接下来,我们需要创建一个卷积神经网络。在matlab中,可以使用Deep Learning Toolbox来创建卷积神经网络模型。我们需要指定网络的层数、每层的神经元个数、激活函数等参数,以及网络的损失函数、优化算法等参数。 然后,我们需要将数据集分成训练集和测试集,并将其加载到matlab的工作空间中。可以使用matlab自带的数据集加载函数或者自己编写数据集加载函数来完成这一步骤。 接下来,我们需要对数据进行预处理,以便将其交给卷积神经网络进行训练。预处理包括图像的标准化、图像增强、数据扩充等操作。 最后,我们需要使用trainNetwork函数来训练我们的卷积神经网络,并使用testNetwork函数来测试网络的性能。网络训练完毕后,可以保存模型以备将来使用。 总的来说,用matlab进行卷积神经网络搭建十分方便,并且matlab还提供了许多实用的工具箱和函数来辅助网络训练和测试。若想深入研究深度学习,matlab是一个不错的选择。 ### 回答2: 深度学习是现代计算机科学的热门领域,它通过神经网络的层次结构来学习复杂的模式,特别是在图像、语音和自然语言处理上表现突出。Matlab是一种广泛用于数学建模、数据分析和科学计算的软件工具,也被用于深度学习领域。本文将介绍如何使用Matlab从零开始搭建卷积神经网络CNN。 首先,我们需要导入一些深度学习常用的库。例如 MatConvNet 和 VLFeat,这两个库都是由Matlab编写的,方便用户在Matlab中实现卷积神经网络。接下来,我们需要构建神经网络的模型,包括卷积层、池化层、全连接层等。这里,我们将使用卷积层、池化层交替的组合来搭建CNN模型,并设置相关的参数,例如数目、步长和大小等。 然后,我们需要准备好训练数据和测试数据,这些数据可以是图像、语音或文本等。我们需要将数据集进行预处理,例如归一化、预处理等,以确保数据数据量相等和格式标准化。接下来,我们需要定义模型的训练方法,例如使用反向传播算法以最小化误差和损失函数,而优化器可以选择常用的SGD、Adam或Adagrad等。 最后,我们需要对我们训练好的模型进行测试,测试过程中会给出一些输入样例,然后模型会输出对应的预测结果,我们可以根据这些结果来评估模型的性能和准确度。如果模型的性能不好,我们可以使用更多的层数、更多的节点或更多的数据来改善模型。 总之,使用Matlab搭建卷积神经网络的过程比较复杂,需要对深度学习的知识有一定的了解,并具备一定的程序能力。通过本文的介绍,相信读者能够初步了解到如何搭建卷积神经网络,并在实践中逐渐提高自己的能力。 ### 回答3: 在进行深度学习研究时,卷积神经网络(CNN)是一种非常常见的网络结构。使用Matlab可以高效地实现并训练CNN。下面将以一个简单的手写数字识别任务为例,从0开始介绍如何在Matlab中搭建训练卷积神经网络。 首先需要导入手写数字数据集。在Matlab中已经内置了一个手写数字数据集,可以使用以下命令导入: ``` digitDatasetPath = fullfile(matlabroot,'toolbox','nnet','nndemos','nndatasets','DigitDataset'); imds = imageDatastore(digitDatasetPath, 'IncludeSubfolders', true, 'LabelSource', 'foldernames'); ``` 接下来,需要设置网络结构和超参数。这里选择一个包含两个卷积层和两个全连接层的CNN,同时设置学习率、迭代轮数等超参数。 ``` layers = [ imageInputLayer([28 28 1]) convolution2dLayer(3,16,'Padding','same') batchNormalizationLayer reluLayer maxPooling2dLayer(2,'Stride',2) convolution2dLayer(3,32,'Padding','same') batchNormalizationLayer reluLayer maxPooling2dLayer(2,'Stride',2) fullyConnectedLayer(256) batchNormalizationLayer reluLayer fullyConnectedLayer(10) softmaxLayer classificationLayer]; options = trainingOptions('adam', ... 'MaxEpochs',20,... 'MiniBatchSize',128, ... 'InitialLearnRate',0.001, ... 'Shuffle','every-epoch', ... 'Verbose',false, ... 'Plots','training-progress'); ``` 然后可以开始训练模型。使用以下命令可以开始训练: ``` net = trainNetwork(imds,layers,options); ``` 最后,可以使用测试集对训练好的模型进行评估,并计算出模型的准确率: ``` YPred = classify(net,augimdsTest); YTest = imdsTest.Labels; accuracy = sum(YPred == YTest)/numel(YTest); ``` 通过这个例子,可以看出使用Matlab搭建训练卷积神经网络是非常简单的。同时,Matlab提供了许多预训练模型和工具箱,可以方便地进行深度学习研究和应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值