卷积神经网络Step by Step(五)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wblgers1234/article/details/74937509

卷积神经网络Step by Step(五)

来到卷积神经网络详解的最后一章,在前面四篇博客里,我们首先对CNN的整体框架进行讲解,然后结合代码对卷积层、池化处理、全连接网络层以及计算cost的前向传播,计算梯度值的反向传播都分别进行讲解。这一章,我们要把这些全部捏合起来,构建一个CNN神经网络,并在MNIST数据集上进行分类训练和测试。

在那之前,我们还有两个在工程中很实用的概念没有提到:

  • Stochastic Gradient Descent,以下简称SGD
  • Momentum

随机梯度下降(SGD)

在标准的梯度下降算法中,我们对目标函数 J(θ) 按照以下公式进行参数更新:

θ=θαθE[J(θ)]

从上式可以看到,传统的GD算法中的cost和gradient是将整个训练集的数据考虑进去,再进行更新的。

而SGD的思路是,每次进行参数学习更新时,只考虑一个训练样本或者一部分训练样本的贡献。那每次迭代的参数更新变为:

θ=θαθJ(θ;set[x(i),y(i)])

从上式可以看到,SGD算法的参数更新的每一次迭代只考虑一个batch的训练数据,一般来说,最小的batch size取值为256。

SGD的优点:
- 减小在参数更新中的方差,让训练的收敛更平稳;
- 可以利用高度并行化的设计来提升算法的效率。

冲量(Momentum)

基于冲量的参数更新:

v=γv+αθJ(θ;set[x(i),y(i)])

θ=θv

每一步梯度下降的大小和方向,我们也参考上一步的v,要是方向一致,就大步往前走;要是忽左忽右,就快步走出这个区域。加入冲量的思想可以很好解决局部最优,加快网络的收敛。

γ 的取值一般在 (0,1] 范围内,一般来说,在初始化的训练稳定之前, γ 取0.5,之后取值0.9及更大。

% 冲量
mom = 0.5;
momIncrease = 20;
velocity = zeros(size(theta));

%%======================================================================
%% 随机梯度下降
it = 0;
for e = 1:epochs

    % 随机打乱训练样本的顺序
    rp = randperm(m);

    for s=1:minibatch:(m-minibatch+1)
        it = it + 1;

        % 在每一次it达到momIncrease时,更新冲量
        if it == momIncrease
            mom = options.momentum;
        end;

        % 按照minibatch获取训练数据
        mb_data = data(:,:,rp(s:s+minibatch-1));
        mb_labels = labels(rp(s:s+minibatch-1));

        % 计算目标函数值
        [cost grad] = funObj(theta,mb_data,mb_labels);


        % 更新theta,ufldl教程Optimization: Stochastic Gradient Descent
        velocity = mom*velocity+alpha*grad;
        theta = theta-velocity;
        fprintf('Epoch %d: Cost on iteration %d is %f\n',e,it,cost);
    end;

    % 每次迭代后衰减learning rate
    alpha = alpha/2.0;

end;

在我们的实现代码中,冲量的初始取值为0.5,当迭代次数达到momIncrease后,冲量取值变为0.9。

cnnTrain.m

cnnTrain.m是整个CNN网络训练分类MNIST数据集的主函数,对每部分的代码分别进行介绍。

参数初始化

这部分的代码是为网络训练做准备,包括载入MNIST训练集,参数初始化等。

%% 第一步:初始化参数,载入训练数据

% 参数配置

% MNIST数据库图片的大小为28×28
imageDim = 28;

% 要分类的类别数
numClasses = 10;

%卷积层的特征提取模块的维数(滤波器维数)
filterDim = 9; 

% 特征提取滤波器的个数
numFilters = 20;

% 池化的维数,应该整除imageDim-filterDim+1
poolDim = 2;

% 载入MNIST数据库的训练数据
addpath function/;

images = loadMNISTImages('../MNIST/train-images-idx3-ubyte');
images = reshape(images,imageDim,imageDim,[]);
labels = loadMNISTLabels('../MNIST/train-labels-idx1-ubyte');
% 将分类标签0重新映射到10
labels(labels==0) = 10;

% 初始化参数
theta = cnnInitParams(imageDim,filterDim,numFilters,poolDim,numClasses);

CNN训练

minibatch大小设置为256,冲量取值为0.95,总的迭代次数是3。

%% 训练CNN网络

options.epochs = 3;
options.minibatch = 256;
options.alpha = 1e-1;
options.momentum = .95;

opttheta = minFuncSGD(@(x,y,z) cnnCost(x,y,z,numClasses,filterDim,...
                      numFilters,poolDim),theta,images,labels,options);

测试CNN网络

% 载入MNIST数据库的测试集
testImages = loadMNISTImages('../MNIST/t10k-images-idx3-ubyte');
testImages = reshape(testImages,imageDim,imageDim,[]);
testLabels = loadMNISTLabels('../MNIST/t10k-labels-idx1-ubyte');
testLabels(testLabels==0) = 10;

[~,cost,preds]=cnnCost(opttheta,testImages,testLabels,numClasses,...
                filterDim,numFilters,poolDim,true);

acc = sum(preds==testLabels)/length(preds);

% 打印出测试集的分类准备率
fprintf('Accuracy is %f\n',acc);

在完成3次迭代后,整个CNN网络收敛,在测试数据集上的预测准确率达到97.1%。结果如下:

.
.
.
Epoch 3: Cost on iteration 687 is 0.119978
Epoch 3: Cost on iteration 688 is 0.126712
Epoch 3: Cost on iteration 689 is 0.087837
Epoch 3: Cost on iteration 690 is 0.100424
Epoch 3: Cost on iteration 691 is 0.112769
Epoch 3: Cost on iteration 692 is 0.062723
Epoch 3: Cost on iteration 693 is 0.120102
Epoch 3: Cost on iteration 694 is 0.144303
Epoch 3: Cost on iteration 695 is 0.126082
Epoch 3: Cost on iteration 696 is 0.140024
Epoch 3: Cost on iteration 697 is 0.074275
Epoch 3: Cost on iteration 698 is 0.123467
Epoch 3: Cost on iteration 699 is 0.154408
Epoch 3: Cost on iteration 700 is 0.095232
Epoch 3: Cost on iteration 701 is 0.098181
Epoch 3: Cost on iteration 702 is 0.111052
Accuracy is 0.971000

代码地址

整个工程代码我已经上传到github上,欢迎下载运行,有很详细的注释帮助理解卷积神经网络的每一步。

后续我还会用pytorch来实现这个cnn网络,对比效果,同时也练练手。请关注代码的github地址:

https://github.com/wblgers/stanford_dl_cnn

参考资料

http://ufldl.stanford.edu/tutorial/supervised/OptimizationStochasticGradientDescent/
http://blog.csdn.net/nuoman_cheng/article/details/50426943

猜你喜欢

转载自blog.csdn.net/wblgers1234/article/details/74937509