这篇文章只要是基于BP网络代码的简单分析,基于公式推导的文章请参阅:BP神经网络部分具体的推导。
工具箱下载
下载地址:
https://github.com/rasmusbergpalm/DeepLearnToolbox
总体测试代码
\tests\test_example_NN.m
nn = nnsetup([784 100 10]);
opts.numepochs = 1; // Number of full sweeps through data
opts.batchsize = 100; // Take a mean gradient step over this many samples
[nn, L] = nntrain(nn, train_x, train_y, opts);
[er, bad] = nntest(nn, test_x, test_y);
很简单的几步就训练了一个NN,我们发现其中最重要的几个函数就是nnsetup
,nntrain
和nntest
了。
nnsetup
NNSETUP
创建前向反馈神经网络。
代码解释
详细代码如下:
function nn = nnsetup(architecture)
%NNSETUP creates a Feedforward Backpropagate Neural Network
% nn = nnsetup(architecture) returns an neural network structure with n=numel(architecture)
% layers, architecture being a n x 1 vector of layer sizes e.g. [784 100 10]
nn.size = architecture;
nn.n = numel(nn.size);
nn.activation_function = 'tanh_opt'; % Activation functions of hidden layers: 'sigm' (sigmoid) or 'tanh_opt' (optimal tanh).
nn.learningRate = 1; % learning rate Note: typically needs to be lower when using 'sigm' activation function and non-normalized inputs.
nn.momentum = 0.5; % Momentum 权值动量因子
nn.scaling_learningRate = 1; % Scaling factor for the learning rate (each epoch) 学习率变化因子 (each epoch)
nn.weightPenaltyL2 = 0; % L2 regularization
nn.nonSparsityPenalty = 0; % Non sparsity penalty 非稀疏惩罚
nn.sparsityTarget = 0.05; % Sparsity target 稀疏目标值
nn.inputZeroMaskedFraction = 0; % Used for Denoising AutoEncoders 自动编码的去噪作用
nn.dropoutFraction = 0; % Dropout level (http://www.cs.toronto.edu/~hinton/absps/dropout.pdf)
nn.testing = 0; % Internal variable. nntest sets this to one. 一个标志参数--在nntest.m这个函数中会用到
nn.output = 'softmax'; % output unit 'sigm' (=logistic), 'softmax' and 'linear'
for i = 2 : nn.n
% weights and weight momentum
nn.W{i - 1} = (rand(nn.size(i), nn.size(i - 1)+1) - 0.5) * 2 * 4 * sqrt(6 / (nn.size(i) + nn.size(i - 1)));
nn.vW{i - 1} = zeros(size(nn.W{i - 1}));
% average activations (for use with sparsity)
nn.p{i} = zeros(1, nn.size(i));
end
end
nnsetup初始化网络结构以及一系列参数。对照着代码,看一下具体含义。
nn = nnsetup(architecture)
返回一个神经网络结构,architecture
为结构参数。architecture
是一个n x 1 向量,表示每一层神经元的个数。
比如architecture=[784 100 10]
,表示输入层为784维输入,100个隐含层,10个输出层
为什么是输入为784:因为每一个手写体大小为28*28的,也就是784维度
隐含层为什么是100:随便设置的,可以随意修改,需要设计
输出为什么是10:手写体有0-9这10种结果,所以为10
//对每一层的网络结构进行初始化,一共三个参数W,vW,p,其中W是主要的参数
//vW
是更新参数时的临时参数,p是所谓的sparsity
,(等看到代码了再细讲)
##使用实例
nn=nnsetup([size(feature,2) 200 200 length(azimuth)]);
nntrain
截取出的主要框架为:
for i = 1 : numepochs
for l = 1 : numbatches
nn = nnff(nn, batch_x, batch_y);
nn = nnbp(nn);
nn = nnapplygrads(nn);
L(n) = nn.L;
n = n + 1;
end
end
第一层for循环为迭代次数。第二次为遍历所有的batch。其中,先计算前向传播(ff
),在计算反向传播(bp
),接着更新参数(nnapplygrads
),最后计算损失函数(代价函数)L。
下面分析三个函数nnff
,nnbp
和nnapplygrads
。
nnff
nnff就是进行feedforward pass
,其实非常简单,就是整个网络正向跑一次就可以了
当然其中有dropout和sparsity的计算,具体的参见论文“Improving Neural Networks with Dropout
“和Autoencoders and Sparsity
提取出主要框架为:
for i = 2 : n-1 (遍历隐含层)
//根据激活函数计算隐层输出
//隐层的dropout计算,舍弃部分输出
//计算sparsity,nonSparsityPenalty 是对没达到sparsitytarget的参数的惩罚系数
//Add the bias term
end
//根据输出层的结构计算输出层的输出。
//计算误差以及损失函数
nnbp
代码:\NN\nnbp.m
nnbp呢是进行back propagation
的过程。值得注意的还是dropout和sparsity的部分。
提取出主要框架为:
①计算输出层的输出
②依次反向计算隐层输出
for i = (n - 1) : -1 : 2 (反向遍历隐层)
d_act为隐层 激活函数的导数
d{i}为隐层输出函数的导数。 计算中用到非稀疏惩罚项,以及dropout
end
③计算权值的导数nn.dW{i}
dW{i}基本就是计算的gradient
(梯度)了,只是后面还要加入一些东西,进行一些修改。
nnapplygrads
代码文件:\NN\nnapplygrads.m
for i = 1 : (nn.n - 1)
//应用weightPenaltyL2,learningRate ,momentum修正dW
nn.W{i} = nn.W{i} - dW; //权值W更新
end
这个内容就简单了,nn.weightPenaltyL2
是weight decay
的部分,也是nnsetup时可以设置的一个参数
有的话就加入weight Penalty
,防止过拟合,然后再根据momentum
的大小调整一下,最后改变nn.W{i}
即可
nntest
function [er, bad] = nntest(nn, x, y)
labels = nnpredict(nn, x);
[~, expected] = max(y,[],2);
bad = find(labels ~= expected);
er = numel(bad) / size(x, 1);
end
nntest
再简单不过了,就是调用一下nnpredict
,在和test的集合进行比较
nnpredict
代码文件:\NN\nnpredict.m
function labels = nnpredict(nn, x)
nn.testing = 1;
nn = nnff(nn, x, zeros(size(x,1), nn.size(end)));
nn.testing = 0;
[~, i] = max(nn.a{end},[],2);
labels = i;
end
继续非常简单,predict
不过是nnff
一次,得到最后的output~~
max(nn.a{end},[],2);
是返回每一行的最大值以及所在的列数,所以labels返回的就是标号啦
(这个test好像是专门用来test分类问题的,我们知道nnff得到最后的值即可)
总结
这篇文章只要是基于代码的简单分析,基于公式推导的文章请参阅:BP神经网络部分具体的推导。