UFLDL学习笔记5(Building Deep Networks for Classification)
UFLDL学习笔记5(Building Deep Networks for Classification)
最近在学习UFLDL Tutorial,这是一套关于无监督学习的教程。在此感觉Andrew Ng做的真的是非常认真。下面把我的代码贴出来,方便大家学习调试。所有代码已经过matlab调试通过。
Building Deep Networks for Classification练习
这一章是用fine-tune的多层网络进行mnist数字的识别。特征提取层使用unlabeld数据训练多层的sparse autoencoder,分类层使用labeled数据训练softmax regression分类器,最后再用labeled数据对整个网络进行fine-tune。本章需要用到前面几章的一些.m文件。因此需要先做前面章节的练习。
本章识别mnist的网络结构图如下
流程
(1)逐层训练Sparse Autoencoder权重(先W1,再W2)
(2)以Sparse Autoencoder的输出训练Softmax分类器权重(W3)
(3)用labeled的数据fine-tune所有权重。
优点
(1)物理意义更明显,逐层抽取特征。
(2)与普通ANN相比,避免陷入局部最优。
其它
(1)若labeled数据多则fine-tune有效。
(2)层间的非线性映射函数是为了增加非线性表征力,若层间是线性映射则无论多少层都是线性的。
代码编写
好了,下面贴出我的matlab代码。一共有3个.m文件需要自己编写。
一、stackedAEExercise.m 主函数。
Step 0. 参数设置。无需编写
Step 1. 读取mnist数据。无需编写。
Step 2. 训练第一层Sparse Autoencoer权重。代码:
- % 参考前面章节给出的代码
- addpath minFunc/
- sae1options.Method = 'lbfgs';
- sae1options.maxIter = 100;<span style="white-space:pre"> </span> % 迭代次数,调试时可设为较小值
- sae1options.display = 'on';
- [sae1OptTheta,cost] = minFunc( @(p) sparseAutoencoderCost(p, ...
- inputSize, hiddenSizeL1, ...
- lambda, sparsityParam, ...
- beta, trainData), ...
- sae1Theta, sae1options);
Step 3. 训练第二层Sparse Autoencoder权重。代码:
- % 参考前面章节给出的代码
- ftoptions.Method = 'lbfgs';
- ftoptions.maxIter = 100; % 迭代次数,调试时可设为较小值
- ftoptions.display = 'on';
- [sae2OptTheta,cost] = minFunc( @(p) sparseAutoencoderCost(p, ...
- hiddenSizeL1, hiddenSizeL2, ...
- lambda, sparsityParam, ...
- beta, sae1Features), ...
- sae2Theta, ftoptions);
Step 4. 训练Softmax分类器权重。代码:
- smOptions.maxIter = 100; %Softmax训练迭代次数
- sampleN = size(sae2Features,2); %[输入维数,样本数]
- [softmaxModel] = softmaxTrain(hiddenSizeL2, numClasses, lambda, sae2Features, trainLabels, smOptions); %训练Softmax分类器
- saeSoftmaxOptTheta = reshape(softmaxModel.optTheta,hiddenSizeL2*numClasses,1);
Step 5. Finetune softmax model。代码:
- % 参考前面章节给出的代码
- ftoptions.Method = 'lbfgs';
- ftoptions.maxIter = 100; % 迭代次数,调试时可设为较小值
- ftoptions.display = 'on';
- [stackedAEOptTheta,cost] = minFunc( @(p) stackedAECost(p, ...
- inputSize, ...
- hiddenSizeL2, numClasses, netconfig, ...
- lambda, trainData, trainLabels), ...
- stackedAETheta, ftoptions);
二、stackedAEPredict.m 根据模型预测结果。代码:
- W1 = stack{1}.w;
- b1 = stack{1}.b;
- W2 = stack{2}.w;
- b2 = stack{2}.b;
- sampleN = size(data,2);
- h1 = sigmoid(W1*data + repmat(b1,1,sampleN));
- h2 = sigmoid(W2*h1 + repmat(b2,1,sampleN));
- y = softmaxTheta*h2;
- [tmp,pred] = max(y);
三、stackedAECost.m 计算整个模型的误差和所有权重梯度。用于fine-tune。这个.m文件花了我很长很长时间。。原本想尽量用矩阵形式去掉for,但是最后还是保留了两个,为了结构清晰。我的建议是,求导仔细,大胆编程。代码:
- % ----------初始化值-------------------
- format long
- sampleN = size(data,2);
- outputSize = size(groundTruth,1);
- W1 = stack{1}.w;
- b1 = stack{1}.b;
- W2 = stack{2}.w;
- b2 = stack{2}.b;
- W3 = softmaxTheta;
- N2 = size(W2,2); %第一隐层节点数
- N3 = size(W3,2); %第二隐层节点数
- A1 = data;
- A2 = sigmoid(W1*A1+repmat(b1,1,sampleN));
- A3 = sigmoid(W2*A2+repmat(b2,1,sampleN));
- A4 = exp(W3*A3) ./ repmat(sum(exp(W3*A3)),outputSize,1);
- P = A4; %输出值
- X = A1; %输入值
- Y = groundTruth; %label值
- % -----------损失函数--------------------
- cost = -1/sampleN * sum(sum(Y.*log(P))); %损失函数
- % -----------softmax层权值梯度-----------
- softmaxThetaGrad = -1/sampleN * (Y-P)*A3'; %softmax层权值梯度
- % -----------第二隐层权值梯度-------------
- % 完全按照求导公式来,弄了很久
- dEdA3 = zeros(N3,sampleN);
- sumK = zeros(N3,sampleN);
- for k = 1:outputSize
- sumL = zeros(N3,sampleN);
- for l = 1:outputSize
- sumL = sumL + (W3(l,:)-W3(k,:))' * exp((W3(l,:)-W3(k,:))*A3);
- end
- sumK = sumK + repmat(Y(k,:),N3,1) .* repmat(A4(k,:),N3,1) .* sumL;
- end
- dEdA3 = sumK;
- dEdO3 = dEdA3.*A3.*(1-A3);
- stackgrad{2}.w = 1/sampleN * dEdO3*A2';
- stackgrad{2}.b = 1/sampleN * sum(dEdO3,2);
- % -----------第一隐层权值梯度-------------
- dEdO2 = W2'*dEdO3.*A2.*(1-A2);
- stackgrad{1}.w = 1/sampleN * dEdO2*X';
- stackgrad{1}.b = 1/sampleN * sum(dEdO2,2);
运行结果
这个表是我在debug的过程中得到的,由表中可看到经过fine-tune的结果要好很多。
小结
本章的练习花了好几天的时间,最主要在Softmax对前面求导花了很长时间。推算也比较复杂。这一章做的效率不高,但做完后就会有一种豁然开朗的感觉。建议各位自行推导这些公式。