matlab——深度学习NN
==========================================================================================最近⼀直在看Deep Learning ,各类博客、论⽂看得不少
baro但是说实话,这样做有些疏于实现,⼀来呢⾃⼰的电脑也不是很好,⼆来呢我⽬前也没能⼒⾃⼰去写⼀个toolbox 只是跟着Andrew Ng 的 写了些已有框架的代码(这部分的代码见)后来发现了⼀个matlab 的Deep Learning 的,发现其代码很简单,感觉⽐较适合⽤来学习算法再⼀个就是matlab 的实现可以省略掉很多数据结构的代码,使算法思路⾮常清晰
所以我想在解读这个toolbox 的代码的同时来巩固⾃⼰学到的,同时也为下⼀步的实践打好基础(本⽂只是从代码的⾓度解读算法,具体的算法理论步骤还是需要去看paper 的
我会在⽂中给出⼀些相关的paper 的名字,本⽂旨在梳理⼀下算法过程,不会深究算法原理和公式)
==========================================================================================使⽤的代码: ,下载地址:,感谢该toolbox 的作者
香奈儿英文==========================================================================================第⼀章从分析NN(neural network)开始,因为这是整个deep learning 的⼤框架,参见
==========================================================================================⾸先看⼀下\tests\test_example_NN.m ,跳过对数据进⾏normalize 的部分,最关键的就是:(为了注释显⽰有颜⾊,我把matlab 代码中的%都改成了//)翻译腔
很简单的⼏步就训练了⼀个NN ,我们发现其中最重要的⼏个函数就是nntup,nntrain 和nntest 了那么我们分别来分析着⼏个函数,\NN\nntup.m
nntup [cpp]
1. nn = nntup([784 100 10]);
2. opts.numepochs = 1; // Number of full sweeps through data
3. opts.batchsize = 100; // Take a mean gradient step over this many samples
4. [nn, L] = nntrain(nn, train_x, train_y, opts);happening
5. [er, bad] = nntest(nn, test_x, test_y);
nntrain
tup⼤概就这样⼀个过程,下⾯就到了train了,打开\NN\nntrain.m
我们跳过那些检验传⼊数据是否正确的代码,直接到关键的部分
denoising 的部分请参考论⽂:Extracting and Composing Robust Features with Denoising Autoencoders
下⾯分析三个函数nnff,nnbp和nnapplygrads
nnff
nnff就是进⾏feedforward pass,其实⾮常简单,就是整个⽹络正向跑⼀次就可以了
当然其中有dropout和sparsity的计算
具体的参见论⽂“Improving Neural Networks with Dropout“和
[cpp]
new什么意思1. function nn = nnff(nn, x, y)
2. //NNFF performs a feedforward pass
3. // nn = nnff(nn, x, y) returns an neural network structure with updated
4. // layer activations, error and loss (nn.a, nn.e and nn.L)
5.
6. n = nn.n; //nn.n=numel(nn.size)就是⼀共多少层
7. m = size(x, 1); //就是⼀共多少个数据
8.
9. x = [ones(m,1) x]; //在x中加⼊⼀组元素为1 的列向量,⽬的是作为偏置,并且通过前⾯权值
的初始化过程中我们可以看得到,在权值的数量(输⼊层神经元个数*输出神经元个数)设置
上,在输⼊层的数⽬上加了1,就是作为偏置的权重。
10. nn.a{1} = x; //x的值作为整个⽹络神经元的第⼀个元素
11.
12. //feedforward pass
13. for i = 2 : n-1
14. //根据选择的激活函数不同进⾏正向传播计算
/
/你可以回过头去看nntup⾥⾯的第⼀个参数activation_function
1. //sigm就是sigmoid函数,tanh_opt就是tanh的函数,这个toolbox好像有⼀点改变
2. //tanh_opt是1.7159*tanh(2/
3.*A)
3. switch nn.activation_function
4. ca'sigm'
5. // Calculate the unit's outputs (including the bias term)
6. nn.a{i} = sigm(nn.a{i - 1} * nn.W{i - 1}');
7. ca'tanh_opt'
8. nn.a{i} = tanh_opt(nn.a{i - 1} * nn.W{i - 1}');
9. end
10.
11. //dropout的计算部分部分 dropoutFraction 是nntup中可以设置的⼀个参数
12. if(nn.dropoutFraction > 0)
13. sting) //现在是训练阶段所以执⾏的el后⾯的部分
14. nn.a{i} = nn.a{i}.*(1 - nn.dropoutFraction);
15. el
16. nn.dropOutMask{i} = (rand(size(nn.a{i}))>nn.dropoutFraction);//随机⽣成⼀组满⾜丢包
率的伯努利分布的0/1数组
nn.a{i} = nn.a{i}.*nn.dropOutMask{i}
end
车身划痕修复方法
end
1. //计算sparsity,nonSparsityPenalty 是对没达到sparsitytarget的参数的惩罚系数
2. //calculate running exponential activations for u with sparsity
3. SparsityPenalty>0)
4. nn.p{i} = 0.99 * nn.p{i} + 0.01 * mean(nn.a{i}, 1);
5. end
6.
7. //Add the bias term
8. nn.a{i} = [ones(m,1) nn.a{i}];
9. end
10. switch nn.output
11. ca'sigm'
12. nn.a{n} = sigm(nn.a{n - 1} * nn.W{n - 1}');
13. ca'linear'
14. nn.a{n} = nn.a{n - 1} * nn.W{n - 1}';
15. ca'softmax'
16. nn.a{n} = nn.a{n - 1} * nn.W{n - 1}';
17. nn.a{n} = exp(bsxfun(@minus, nn.a{n}, max(nn.a{n},[],2)));
18. nn.a{n} = bsxfun(@rdivide, nn.a{n}, sum(nn.a{n}, 2));
19. end
20. //error and loss
21. //计算error
22. nn.e = y - nn.a{n};
23.
24. switch nn.output踢足球的英文
25. ca {'sigm', 'linear'}
26. nn.L = 1/2 * sum(sum(nn.e .^ 2)) / m;
27. ca'softmax'
28. nn.L = -sum(sum(y .* log(nn.a{n}))) / m;因为是女子下载
29. end
30. end
nnbp
代码:\NN\nnbp.m
nnbp 呢是进⾏back propagation 的过程,过程还是⽐较中规中矩,和ufldl 中的讲的基本⼀致
值得注意的还是dropout 和sparsity 的部分
这只是实现的内容,代码中的d{i}就是这⼀层的delta 值,在ufldl 中有讲的
dW{i}基本就是计算的gradient 了,只是后⾯还要加⼊⼀些东西,进⾏⼀些修改
具体原理参见论⽂“Improving Neural Networks with Dropout “ 以及 的内容
nnapplygrads
代码⽂件:\NN\nnapplygrads.m
这个内容就简单了,nn.weightPenaltyL2 是weight decay 的部分,也是nntup 时可以设置的⼀个参数
有的话就加⼊weight Penalty ,防⽌过拟合,然后再根据momentum 的⼤⼩调整⼀下,最后改变nn.W{i}即可nntestbecau we can
nntest 再简单不过了,就是调⽤⼀下nnpredict ,在和test 的集合进⾏⽐较[cpp]
1.
for i = (n - 1) : -1 : 2 % Derivative of the activation function switch nn.activation_function ca 'sigm' d_act = nn.a{i} .* (1 - nn.a{i}); ca 'tanh_opt' d_act = 1.7159 * 2/3 * (1 - 1/(1.7159)^2 * nn.a{i}.^2); end 2. if (nn.nonSparsityPenalty>0) 3. pi = repmat(nn.p{i}, size(nn.a{i}, 1), 1); //pi 的初始值赋值是0,nn.p{i} = zeros(1, nn.size(i));4.
sparsityError = [zeros(size(nn.a{i},1),1) nn.nonSparsityPenalty * (-nn.sparsityTarget ./ pi + (1 - nn.sparsityTarget) ./ (1 - pi))]; 5. end 6. 7. // Backpropagate first derivatives 8. if i+1==n % in this ca in d{n} there is not the bias term to be removed 9. d{i} = (d{i + 1} * nn.W{i} + sparsityError) .* d_act; // Bishop (5.56) 10. el // in this ca in d{i} the bias term has to be removed 11. d{i} = (d{i + 1}(:,2:end) * nn.W{i} + sparsityError) .* d_act; 12. end 13. 14. if (nn.dropoutFraction>0) 15. d{i} = d{i} .* [ones(size(d{i},1),1) nn.dropOutMask{i}]; 16. end
[cpp]
1. for i = 1 : (nn.n - 1)
2. if (nn.weightPenaltyL2>0)
3. dW = nn.dW{i} + nn.weightPenaltyL2 * nn.W{i};
4. el
5. dW = nn.dW{i};
6. end
7.
8. dW = nn.learningRate * dW;
9. 10. if (nn.momentum>0) 11. nn.vW{i} = nn.momentum*nn.vW{i} + dW; 12. dW = nn.vW{i}; 13. end 14. 15. nn.W{i} = nn.W{i} - dW; 16. end
nnpredict
代码⽂件:\NN\nnpredict.m
继续⾮常简单,predict 不过是nnff ⼀次,得到最后的output~~
max(nn.a{end},[],2); 是返回每⼀⾏的最⼤值以及所在的列数,所以labels 返回的就是标号啦(这个test 好像是专门⽤来test 分类问题的,我们知道nnff 得到最后的值即可)
总结
总的来说,神经⽹络的代码⽐较常规易理解,基本上和 中的内容相差不⼤
只是加⼊了dropout 的部分和denoising 的部分
本⽂的⽬的也不奢望讲清楚这些东西,只是给出⼀个路线,可以跟着代码去学习,加深对算法的理解和应⽤能⼒[cpp]
1. function [er, bad] = nntest(nn, x, y)
2. labels = nnpredict(nn, x);
3. [~, expected] = max(y,[],2);
4. bad = find(labels ~= expected);
5. er = numel(bad) / size(x, 1);
6. end [cpp]
1. function labels = nnpredict(nn, x)
2. nn.testing = 1;
3. nn = nnff(nn, x, zeros(size(x,1), nn.size(end)));
4. nn.testing = 0;
5.
6. [~, i] = max(nn.a{end},[],2);
7. labels = i;
8. end
bleeder