MatConvNet训练自己的网络

  根据MatConvNet的官网介绍,MatConvNet是一个基于适用在Matlab的卷积神经网络(CNN)的工具包,支持CPU和GPU。 事实上,这个工具包并不仅仅支持CNN,同时也支持一些其它的一些网络如RNN, LSTM等。 这个工具包包含了一些深度学习的基本操作如卷积,隔空卷积,池化,非线性激活函数等。

  MatConvNet里面有两个非常重要的部件,一个是SimpleNN 另外一个是 DagNN。

  SimpleNN是一个简单的DNN的版本,主要适合一些简单的串行结构的也就是说一个卷积后面加上非线性激活最后pooling等。

  DagNN可以实现更加复杂的网络结构,如实现两个层之间的skipping等等。 因为现在深度学习很多时候是改结构的,所以后面和 DagNN打交道会比较多。

  MatConvNet也同时为我们提供了一些已经训练好的模型,比如说 AlexNet, GoogleNet, VGG等等。大家可以通过 vlfeat的官网下载模型。 另外,MatConvNet 在Github上也有自己的开源主页,同时也集成可一些优秀的第三方的代码,比如说 autonn, mcnRFCN, mcnSSD等。值得推荐的是autonn, 它对MatConvNet进行了更加高级的封装,可以让大家以更加简洁的代码来实现自己的网络,具体的文档可以参照autonn 的 Tutorial。

  MatConvNet初学

  好了,简单地知道了MatConvNet之后,我们先开始着手玩玩一下MatConvNet。 首先我们到官网下载已经训练好的AlexNet模型。然后在Matlab中通过net=dagnn.DagNN.loadobj(‘imagenet-matconvnet-alex.mat‘) 导入这个模型。

  首先我们在Matlab中输入net.layers 查看这个网络的每一层所包含的信息。得到输出结果如下:

  name

  inputs

  outputs

  params

  inputIndexes

  outputIndexes

  paramIndexes

  forwardTime

  backwardTime

  block

  1

  2

  3

  4

  5

  6

  7

  8

  9

  10

  这里解释一下各个关键的几个名词的含义: name: 即网络的每一层起的名字,比如说第一层的卷积层(conv1)。 inputs 当前层的输入,对于第一层的话就是我们的数据集,对于后面的层来说是当前层的前一层。 outputs 当前层的输出,也即是下一个层的输入。 params 代表的是需要确定的参数的列表,比如说对于卷积层它的参数就是卷积核的参数如果有bias 还有bias的信息。对于relu由于没有参数,所以参数为空。 paramIndexes 训练的参数的index比如说对于卷积层的话就是卷积核的参数和一些bias的参数。

  同时也可以通过输入net.vars查看各个层的变量信息。net.params查看需要确定的变量信息。可以通过net.print()查看整个网络的信息。比如说对于AlexNet它的输出如下:

  func| conv1|relu1| pool1| conv2|relu2| pool2| conv3|relu3| conv4|relu4| conv5|relu5| pool5| fc6|relu6| fc7|relu7| fc8|

  -------|-------------|-----|-------|-------------|-----|-------|-------------|-----|-------------|-----|-------------|-----|-------|---------|-----|---------|-----|----------|

  type| Conv| ReLU|Pooling| Conv| ReLU|Pooling| Conv| ReLU| Conv| ReLU| Conv| ReLU|Pooling| Conv| ReLU| Conv| ReLU| Conv|

  inputs| input| x1| x3| x4| x5| x7| x8| x9| x11| x12| x14| x15| x17| x18| x19| x21| x22| x24|

  outputs| x1| x3| x4| x5| x7| x8| x9| x11| x12| x14| x15| x17| x18| x19| x21| x22| x24|prediction|

  郑州人流多少钱:http://www.zztj120.com/

  郑州人流医院:http://www.zztj120.com/

  params|conv1f conv1b| | |conv2f conv2b| | |conv3f conv3b| |conv4f conv4b| |conv5f conv5b| | |fc6f fc6b| |fc7f fc7b| | fc8f fc8b|

  pad| 0| n/a| 0| 2| n/a| 0| 1| n/a| 1| n/a| 1| n/a| 0| 0| n/a| 0| n/a| 0|

  stride| 4| n/a| 2| 1| n/a| 2| 1| n/a| 1| n/a| 1| n/a| 2| 1| n/a| 1| n/a| 1|

  func| prob|

  -------|----------|

  type| SoftMax|

  inputs|prediction|

  outputs| prob|

  params| |

  pad| n/a|

  stride| n/a|

  params|233MB|

  vars| 0B|

  total|233MB|

  1

  2

  3

  4

  5

  6

  7

  8

  9

  10

  11

  12

  13

  14

  15

  16

  17

  18

  19

  20

  21

  22

  说了这么多了,我们可以输入一张图像来测试一下我们的网络。主要过程如下:

  读入图像。 我们就读入我们图像处理的peppers的图像,并且转换为single。im = single(imread(‘peppers.png‘));

  然后对读入的图像进行resize:im_ = imresize(im_,net.meta.normalization.imageSize(1:2));

  接着减去训练集合的average image :im_ = bsxfun(@minus, im_, net.meta.normalization.averageImage) ;

  接着用我们的网络对当前的输入进行评估:net.eval({‘input‘,im_}); 这里的input和我们在第一层定义的输入变量要一一对应。

  输出得到的概率数值scores = net.vars(net.getVarIndex(‘prob‘)).value ;scores = squeeze(gather(scores)) ; 同样,这里的prob也要和我们在最后一层定义的变量名称一致。

  得到得分最大的类别及其对应的标记信息。[bestScore, best] = max(scores) ; figure(1) ; clf ; imagesc(im) ; title(sprintf(‘%s (%d), score %.3f‘,... net.meta.classes.description{best}, best, bestScore)) ;

  至此我们就完成了一个数据的测试过程。

  用MatConvNet来训练自己定义的网络

  下面我们将以Mnist数据为例,来看看用MatConvNet训练自己的网络过程。

  准备数据集

  首先我们从祖师爷的官网上下载MNIST数据集,主要有以下四个

  train-images-idx3-ubyte.gz:训练集 train-labels-idx1-ubyte.gz:训练集标签 t10k-images-idx3-ubyte.gz:测试集 t10k-labels-idx1-ubyte.gz:测试集标签

  1

  2

  3

  4

  然后通过下面的代码来构造我们的数据集:

  f=fopen(fullfile(dataDir,‘train-images-idx3-ubyte‘),‘r‘);

  x1=fread(f,inf,‘uint8‘);

  fclose(f);

  x1=permute(reshape(x1(17:end),28,28,60e3),[2 1 3]);

  f=fopen(fullfile(dataDir,‘t10k-images-idx3-ubyte‘),‘r‘);

  x2=fread(f,inf,‘uint8‘);

  fclose(f);

  x2=permute(reshape(x2(17:end),28,28,10e3),[2 1 3]);

  f=fopen(fullfile(dataDir, ‘train-labels-idx1-ubyte‘),‘r‘) ; % Open training labels file for reading

  y1=fread(f,inf,‘uint8‘); % Read file and store

  fclose(f) ; % Close training labels

  y1=double(y1(9:end)‘)+1 ; % Format and store

  f=fopen(fullfile(dataDir, ‘t10k-labels-idx1-ubyte‘),‘r‘) ; % Open testing labels for reading

  y2=fread(f,inf,‘uint8‘); % Read file and store

  fclose(f) ; % Close testing labels

  y2=double(y2(9:end)‘)+1 ;

  set = [ones(1,numel(y1)) 3*ones(1,numel(y2))]; % Assign sets to the data (Training, Validation, Testing)

  data = single(reshape(cat(3, x1, x2),28,28,1,[])); % Convert to single precision and reshape

  dataMean = mean(data(:,:,:,set == 1), 4); % Zero Mean

  data = bsxfun(@minus, data, dataMean) ; % Finalize Zero Mean

  imdb.images.data = data ; % Assign IMDB images data

  imdb.images.data_mean = dataMean; % Assign IMDB data mean

  imdb.images.labels = double(cat(2, y1, y2)) ; % Assign IMDB labels

  imdb.images.set = set ; % Assign IMDB Set

  imdb.meta.sets = {‘train‘, ‘val‘, ‘test‘} ; % meta = miscellaneous, in this case set names

  imdb.meta.classes = arrayfun(@(x)sprintf(‘%d‘,x),0:9,‘uniformoutput‘,false) ;

  fprintf(‘\n***** IMBD.mat has been created! *****\n‘);

  save(‘imdb.mat‘, ‘imdb‘, ‘-v7.3‘);

  1

  2

  3

  4

  5

  6

  7

  8

  9

  10

  11

  12

  13

  14

  15

  16

  17

  18

  19

  20

  21

  22

  23

  24

  25

  26

  27

  28

  29

  30

  31

  32

  33

  34

  35

  这里主要需要处理的有1. 计算图像的均值,并且对训练集进行归一化。 2.把数据集分成训练集,测试集和验证集三部分。3.对数据的类别标签进行统计

  初始化网络的训练信息

  有了我们自己的数据集之后,我们需要定义我们自己的网络结构信息主要是每一层的功能,输入输出和参数信息。同时我们也需要对优化的算法进行初始化比如说 batchsize, epoch, learning rate 是否用GPU等等。

  %--------------------------------------------------------------

  % Initialize Parameters

  %--------------------------------------------------------------

  opts.train.batchSize = 80; % 设置网络的batchsize:主要指明了每个随机梯度下降(SGD)的样本大小。

  opts.train.numEpochs = 15 ; % % 每一个Epochs表示所有数据访问。 这里的意思是所有数据被迭代15次之后,输出网络的权重。 其实这个就可以理解为做矩阵分解收敛所需要迭代的次数。

  opts.train.continue = true ; % 这里主要是为了出现突然间断电等情况下,网络接着上一轮的训练继续完成。

  opts.train.gpus = [1] ; % 设置是否使用GPU 1 表示使用,[]表示不用

  opts.train.learningRate = 1e-3; %

  设置学习率,也可以对不同的Epochs设置不同的learning rate。比如说后面的Epochs的学习权值可以设置小一些。opts.train.learningRate =[0.001*ones(1,100), 0.1 *ones(1,200)];

  opts.train.expDir = ‘epoch_data‘; % Directory for storing epoch files, will create if not already made

  opts.train.numSubBatches = 1; % Keep at 1

  % opts.train.weightDecay = 3e-4;

  % Weight decay value, usually set small. Default is present in cnn_train_dag.m

  % opts.train.momentum = 0.9; % Incorporate this, once convergence is reached, Default is present in cnn_train_dag.m

  bopts.useGpu = numel(opts.train.gpus) > 0 ; % Usually keep at 0, seems to only work with 3D data.

  load(‘imdb.mat‘); % 加载我们之前所构造的数据信息。

  1

  2

  3

  4

  5

  6

  7

  8

  9

  10

  11

  12

  13

  14

  15

  16

  17

  18

  19

  定义自己的网络结构

  有了网络的一些训练信息之后,我们就要进入重点了。这个也是很多论文的重点,毕竟有些人黑深度学习是改结构,改Loss,网络拼接嘛。

  首先我们声明一个网络:

  net=dagnn.DagNN();

  1

  然后初始化每一层的网络结构信息,它的基本单元包括: 卷积层(Convolution layer), 反卷积层(Convolution transpose layer), 归一化层(Normalization layer), 激活函数(Activation functions), 池化层( Pooling layer),全连接层(Fully connected layer),损失函数, ROI pooling等。

  下面是我自己定义的网络结构信息:

  net.addLayer(‘conv1‘, dagnn.Conv(‘size‘, [5 5 1 32], ‘hasBias‘, true, ‘stride‘, [1, 1], ‘pad‘, [0 0 0 0]), {‘input‘}, {‘conv1‘}, {‘conv1f‘ ‘conv1b‘});

  % 一个卷积层,名字为conv1, 总共包括32个神经元每一个神经元的depth是1,大小为5X5.有bias,两个卷积之间的间隔为1X1,边缘部分补0, 输入的变量名字为input,输出的变量名字为conv1,输出的参数为conv1f:卷积核的信息, conv1b 卷积的bias信息。

  net.addLayer(‘relu1‘, dagnn.ReLU(), {‘conv1‘}, {‘relu1‘}, {});

  % 一个非线性激活函数Relu,只需要定义输入和输出即可

  net.addLayer(‘pool1‘, dagnn.Pooling(‘method‘, ‘max‘, ‘poolSize‘, [2, 2], ‘stride‘, [2 2], ‘pad‘, [0 0 0 0]), {‘relu1‘}, {‘pool1‘}, {});

  % 一个池化层。主要定义了池化的方法maxpooling, 每2x2个cell进行一次池化。 池化间隔为2x2. 边缘的填充为0. 接着就是输入和输出的变量信息。

  % Block #2

  net.addLayer(‘conv2‘, dagnn.Conv(‘size‘, [5 5 32 32], ‘hasBias‘, true, ‘stride‘, [1, 1], ‘pad‘, [0 0 0 0]), {‘pool1‘}, {‘conv2‘}, {‘conv2f‘ ‘conv2b‘});

  net.addLayer(‘relu2‘, dagnn.ReLU(), {‘conv2‘}, {‘relu2‘}, {});

  net.addLayer(‘pool2‘, dagnn.Pooling(‘method‘, ‘max‘, ‘poolSize‘, [2, 2], ‘stride‘, [2 2], ‘pad‘, [0 0 0 0]), {‘relu2‘}, {‘pool2‘}, {});

  % Block #3

  net.addLayer(‘conv3‘, dagnn.Conv(‘size‘, [4 4 32 64], ‘hasBias‘, true, ‘stride‘, [1, 1], ‘pad‘, [0 0 0 0]), {‘pool2‘}, {‘conv3‘}, {‘conv3f‘ ‘conv3b‘});

  %Fully Connected Layer

  net.addLayer(‘fc1‘, dagnn.Conv(‘size‘, [1 1 64 256], ‘hasBias‘, true, ‘stride‘, [1, 1], ‘pad‘, [0 0 0 0]), {‘conv3‘}, {‘fc1‘}, {‘conv5f‘ ‘conv5b‘});

  %一个全连接层。采用的是1x1的卷积实现

  net.addLayer(‘relu5‘, dagnn.ReLU(), {‘fc1‘}, {‘relu5‘}, {});

  net.addLayer(‘classifier‘, dagnn.Conv(‘size‘, [1 1 256 10], ‘hasBias‘, true, ‘stride‘, [1, 1], ‘pad‘, [0 0 0 0]), {‘relu5‘}, {‘classifier‘}, {‘conv6f‘ ‘conv6b‘});

  net.addLayer(‘prediction‘, dagnn.SoftMax(), {‘classifier‘}, {‘prediction‘}, {});% 将前面层得到的信息进行归一化转化为分类目标的概率信息。

  net.addLayer(‘objective‘, dagnn.Loss(‘loss‘, ‘log‘), {‘prediction‘, ‘label‘}, {‘objective‘}, {}); % 定义训练损失函数为cross entropy

  net.addLayer(‘error‘, dagnn.Loss(‘loss‘, ‘classerror‘), {‘prediction‘,‘label‘}, ‘error‘) ; % 定义在验证集上的误差函数

  1

  2

  3

  4

  5

  6

  7

  8

  9

  10

  11

  12

  13

  14

  15

  16

  17

  18

  19

  20

  21

  22

  23

  24

  网络权值初始化

  有了网络结构,我们需要对网络中的参数进行初始化,主要是对网络的learningRate, weightDecay 和卷积的参数进行初始化。主要代码如下:

  function initNet(net, f)

  net.initParams(); % Initalize local weight decay

  for l=1:length(net.layers)

  if(strcmp(class(net.layers(l).block), ‘dagnn.Conv‘))

  f_ind = net.layers(l).paramIndexes(1); % 得到第一层卷积层的卷积核参数

  b_ind = net.layers(l).paramIndexes(2);% 得到第一层bias的参数

  % 初始化参数为一个高斯分布。

  net.params(f_ind).value = f*randn(size(net.params(f_ind).value), ‘single‘); net.params(f_ind).learningRate = 1; %设置预防overfitting的正则化参数

  net.params(f_ind).weightDecay = 1;

  net.params(b_ind).value = f*randn(size(net.params(b_ind).value), ‘single‘); net.params(b_ind).learningRate = 0.5;

  net.params(b_ind).weightDecay = 1;

  end

  end

  end

  1

  2

  3

  4

  5

  6

  7

  8

  9

  10

  11

  12

  13

  14

  15

  设置每一个batch的数据

  这个步骤的目的是设置每一个batch的数据和相应的label信息。主要代码如下:

  function inputs = getBatch(opts, imdb, batch) % This fucntion is what generates new mini batch

  images = imdb.images.data(:,:,:,batch) ; % Generates specified number of images

  labels = imdb.images.labels(1,batch) ; % Gets the associated labels

  if opts.useGpu > 0

  images = gpuArray(images) ;

  end

  inputs = {‘input‘, images, ‘label‘, labels} ; % Assigns images and label to inputs

  end

  1

  2

  3

  4

  5

  6

  7

  8

  9

  10

  网络训练与测试

  调用MatConvNet的cnn_train_dag 函数进行网络训练。 主要需要传入的参数有:网络结构信息,数据信息,每一个batch的信息, 训练参数信息,验证集信息。最后通过saveobj对训练好的网络进行保存。

  info = cnn_train_dag(net, imdb, @(i,b) getBatch(bopts,i,b), opts.train, ‘val‘, find(imdb.images.set == 3)) ; % MatConvNet DagNN Training Function

  myCNN = net.saveobj(); % Save the DagNN trained CNN

  save(‘myCNNdag.mat‘, ‘-struct‘, ‘myCNN‘)

  1

  2

  3

  4

  5

  至此我们就完成了一个网络的训练过程。我们可以通过上面的AlexNet的测试步骤对输入的数据进行测试。

  使用AutoNN简化训练过程

  从前面的过程我们发现,训练一个自己的网络太麻烦了,要自己addLayer传太多的参数了。有人开始对MatConvNet进行封装,即AutoNN。 在AutoNN中,MatConvNet中一些基本的函数被重新定义,我们不需要指定各个层的名字和层的输入和输出,而且自动给网络的参数进行初始化(当然你也可以用Param原语对网络进行初始化)。另外,AutoNN也实现了一些经典网络ResNet等的架构。使用AutoNN,上面的网络训练代码可以改为:

  images = Input(‘images‘) ;

  labels = Input(‘labels‘) ;

  f=1/100;

  %block one

  x=vl_nnconv(images,‘size‘,[5,5,1,32],‘weightScale‘,f);

  x=vl_nnrelu(x);

  x=vl_nnpool(x,2,‘method‘,‘max‘,‘stride‘,2);

  %block 2

  x=vl_nnpool(vl_nnrelu(vl_nnconv(x,‘size‘,[5 5 32 32],‘weightScale‘,f)),2,‘method‘,‘max‘,‘stride‘,2);

  %block 3

  x=(vl_nnconv(x,‘size‘,[4 4 32 64],‘weightScale‘,f));% conv

  x=vl_nnrelu(vl_nnconv(x,‘size‘,[1 1 64, 256],‘weightScale‘,f));% fc+relu

  x=vl_nnconv(x,‘size‘,[1 1 256 10]);

  output=vl_nnsoftmax(x);

  objective = vl_nnloss(output, labels, ‘loss‘, ‘log‘) ;

  error = vl_nnloss(output, labels, ‘loss‘, ‘classerror‘) ;

  Layer.workspaceNames() ;

  net = Net(objective, error) ;

  info = cnn_train_autonn(net, imdb, @(i,b) getBatch(bopts,i,b), opts.train, ‘val‘, find(imdb.images.set == 3)) ; % MatConvNet DagNN Training Function

  myCNN = net.saveobj();

  1

  2

  3

  4

  5

  6

  7

  8

  9

  10

  11

  12

  13

  14

  15

  16

  17

  18

  19

  20

  21

  22

  23

  24

  25

  26

  27

  28

  29

  是不是感觉代码简洁了好多了。

  最后的最后

  虽然MatConvNet 提供了一个用Matlab训练deep learning的方法,但是建议还是用Python的一些库如Pytorch来进行训练,因为这些网络的开源社区的人更多,出了问题也更容易查到解决方案。

原文地址:https://www.cnblogs.com/wode1/p/MatConvNet.html

时间: 2024-10-12 13:14:55

MatConvNet训练自己的网络的相关文章

Caffe训练好的网络对图像分类

对于训练好的Caffe 网络 输入:彩色or灰度图片 做minist 下手写识别分类,不能直接使用,需去除均值图像,同时将输入图像像素归一化到0-1直接即可. #include <caffe/caffe.hpp>#include <opencv2/core/core.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv2/imgproc/imgproc.hpp>#include <iosf

一块GPU就能训练语义分割网络,百度PaddlePaddle是如何优化的?

一. 图像语义分割模型DeepLab v3 随着计算机视觉的发展,语义分割成为了很多应用场景必不可少的一环. 比如网络直播有着实时剔除背景的要求,自动驾驶需要通过语义分割识别路面,与日俱增的应用场景对语义分割的精度和速度的要求不断提高.同时,语义分割数据集也在不断地进化,早期的Pascal VOC2,其分辨率大多数在1000像素以下.而Cityscape的语义分割数据集分辨率全部达到了1024*2048,总共5000张图片(精细标注),包含19类.这些数据集对研究者,计算设备,甚至框架都带来了更

训练深度学习网络时候,出现Nan是什么原因

说法1: 说法2:说法3: 原文地址:https://www.cnblogs.com/Allen-rg/p/10066764.html

使用CNN(convolutional neural nets)检测脸部关键点教程(五):通过前训练(pre-train)训练专项网络

第九部分 训练专项网络 还记得在刚开始的时候我们丢掉的70%的训练数据吗?如果我们想要得到一个在Kaggle排行榜上有竞争力的成绩,那不是一个好主意.在70%的数据中,还有相当多的特征我们没有看到. 所以改变之前只训练一个模型的方式,我们训练几个专项网络,每一个都可以预测不同的目标集合.我们训练一个模型预测left_eye_center和right_eye_center,另一个模型预测nose_tip--:最终,我们有6个模型,使得我们可以完全利用训练数据,希望能够得到更好的预测效果. 这6个专

基于Triplet loss函数训练人脸识别深度网络(Open Face)

Git:  http://cmusatyalab.github.io/openface/ FaceNet's innovation comes from four distinct factors: (a) thetriplet loss, (b) their triplet selection procedure, (c) training with 100 million to 200 million labeled images, and (d) (not discussed here)

Batch_Size对网络训练结果的影响

最近在跑一些网络时发现,训练完的网络在测试集上的效果总是会受Batch_Size 大小的影响.这种现象跟以往自己所想象的有些出入,于是出于好奇,各种搜博客,大致得出了自己想要的答案,现写一篇博客记录一下. 在训练过程中,一般有三种方式来从数据集中抽取数据,更新参数.一种是取所有的样本算出梯度(Full Batch Learning),另一种是每次迭代只取一个样本进行更新,也即在线学习(Online Learning),取Batch_Size = 1,还有一种是批梯度下降法(Mini-batche

从零到一:caffe-windows(CPU)配置与利用mnist数据集训练第一个caffemodel

一.前言 本文会详细地阐述caffe-windows的配置教程.由于博主自己也只是个在校学生,目前也写不了太深入的东西,所以准备从最基础的开始一步步来.个人的计划是分成配置和运行官方教程,利用自己的数据集进行训练和利用caffe来实现别人论文中的模型(目前在尝试的是轻量级的SqueezeNet)三步走.不求深度,但求详细.因为说实话caffe-windows的配置当初花了挺多时间的,目前貌似还真没有从头开始一步步讲起的教程,所以博主就争取试着每一步都讲清楚吧. 这里说些题外话:之所以选择Sque

学习笔记TF016:CNN实现、数据集、TFRecord、加载图像、模型、训练、调试

AlexNet(Alex Krizhevsky,ILSVRC2012冠军)适合做图像分类.层自左向右.自上向下读取,关联层分为一组,高度.宽度减小,深度增加.深度增加减少网络计算量. 训练模型数据集 Stanford计算机视觉站点Stanford Dogs http://vision.stanford.edu/aditya86/ImageNetDogs/ .数据下载解压到模型代码同一路径imagenet-dogs目录下.包含的120种狗图像.80%训练,20%测试.产品模型需要预留原始数据交叉验

CNN网络--AlexNet

ImageNet Classification with Deep Convolutional Neural Networks AlexNet是Hinton和他的学生Alex Krizhevsky在12年ImageNet Challenge使用的模型结构,刷新了Image Classification的几率,从此deep learning在Image这块开始一次次超过state-of-art,甚至于搭到打败人类的地步,看这边文章的过程中,发现了很多以前零零散散看到的一些优化技术 Referenc