UFLDL作业记录
2016-04-23 12:05
337 查看
UFLDL-Sparse Autoencoder
稀疏自编码的作业,在这里。1. 实现sampleIMAGES
IMAGES.mat是一个512x512x10的10张已将白化过的图片。sampleIMAGES,故名思议,就是采样IMAGES。
用
imagesc(IMAGES(:,:,4)), colormap gray
可以看到图像的灰度的样子,比如第四张图片:
我们想要采的样本是10000个8x8的样本,因为sampleIMAGES里已经这么初始化了。
patchsize = 8; % we'll use 8x8 patches numpatches = 10000; patches = zeros(patchsize*patchsize, numpatches);
patches被初始化程成了一个64x10000的矩阵。
Idea很简单:
随机从10张图片里选一张,随机从x坐标里选8个像素,随机从y坐标里选8个像素。
其实我们只要定下10000个随机的点,作为8x8的样本的左上角就可以了。
设,左上角的点的坐标是(a,b,c),显然(a+8-1,b+8-1,c)要不大于(512,512,10)
先选x坐标的值:
a = randi(512-8+1,1,10000);
在选y坐标的值:
b = randi(512-8+1,1,10000);
最后选图片到底是第几张:
c = randi(10,1,10000);
于是,10000张8x8的图像,其实就是:
d = IMAGES(a:a+8-1,b:b+8-1,c)
所以patches就是:
for i = 1:10000 pathces(:,i) = reshape(d(:,:,i),1,64); end
综合起来,就是:
tic image_size = size(IMAGES); a = randi(image_size(1) - patchsize + 1, 1, numpatches); b = randi(image_size(2) - patchsize + 1, 1, numpatches); c = randi(image_size(3), 1, numpatches); d = IMAGES(a:a+8-1, b:b+8-1, c) for num = 1 : numpatches patches(:,num)=reshape(d(:,:,num),1,patchsize*patchsize); end toc
2. 构建Sparse autoencoder objective
可以看到,train.m里,已经设定了hiddenSize = 25,所以这个网络结构其实是:64x25x64,隐层有25个单元。先按正常的神经网络的训练顺序来
2.1 前向传播
Θ已经在initializeParameters里定义好了,所以 W~1~(25x64),W~2~(64x25)和b~1~(25x1),b~2~(64x1) 已经有了,可以直接开始算前向传播:B_1 = repmat(b_1,1,10000);%截距 Z_2 = (W_1*patches) + B_1;%输入 A_2 = sigmoid(Z_2);%隐层输出 B_2 = repmat(b_2,1,10000);%截距 Z_3 = (W_2*A_2) + B_2;%输入 A_3 = sigmoid(Z_3);%结果
2.2 稀疏性保证
接着要计算ρ^,号称是隐层的平均输出,文中给的公式是:ρ^j=1m∑mi=1[a(2)j(x(i))]
它说,这里取的平均,是在测试集上的平均(averaged over the training set),我觉得很奇怪。
我们知道A_2是一个25x10000的矩阵,那这个m,到底是25还是10000?我怎么感觉都是25,不是说是隐层的平均输出么?
我们想让ρ^尽量的小,最好是某个挺小的值ρ,这个ρ也叫稀疏性参数
为了完成上述要求,我们要把ρ^和ρ的相对熵算一下:
KL(ρ||ρ^j)=ρlogρρ^j+(1−ρ)log1−ρ1−ρ^j
把下面这个东西放进代价函数里,来实现稀疏性的控制:
∑s2j=1KL(ρ||ρ^j)
文中说,说这里的S~2~是隐层节点数,也就是25。这里的ρ又是个标量,显然上面的那个ρ^里的m是10000了。
那么,代码这么写:
mean_A_2 = sum(A_2,2)./10000; rho = sparsityParam KL = sum(rho.*log(rho./mean_A_2)+(1-rho).*log((1-v)/(1.-mean_A_2));
2.3 代价函数
代价函数J:Jsparse(W,b)=J(W,b)+β∑s2j=1KL(ρ||ρ^j)
其中,J(W,b),按照反向传播来算是:
J(W,b)=[1m∑mi=1(12∥∥hW,b(x(i))−y(i)∥∥2)]+λ2∑nl−1l=1∑sli=1∑sl+1j=1(W(l)ji)2
所以,
J=(1/2*10000)*sum(sum((A_3-patches).^2))+lambda/2*(sum(sum(W_1.^2))+sum(sum(W_2.^2)))+beta*KL;
2.4梯度下降
daoshu_Z_3 = sigmoid(A_3).*(1-sigmoid(A_3); delta_3 = -(patches-A_3).*daoshu_Z_3;
对于delta_2,文中说:
δ(2)i=((∑s2j=1W(2)jiδ(3)j)+β(−ρρ^i+1−ρ1−ρ^i))f′(z(2)i)
这么写比较省事。所以:
sparity_penalty = (-rho./mean_A_2+(1-rho)./(1-mean_A_2)); daoshu_Z_2 = sigmoid(A_2).*(1-sigmoid(A_2); delta_2=(W_2'*delta_3+repmat(beta*sparity_penalty,1,mm)).*daoshu_Z_2;
则,W偏导,b偏导为:
∇W(l)J(W,b;x,y)=δ(l+1)(a(l))T
∇b(l)J(W,b;x,y)=δ(l+1)
所以W,和b的偏导代码是:
W1_pd = delta_2 * pathces'; W2_pd = delta_3 * A_2'; b1_pd = sum(delta_2,2); b2_pd = sum(delta_3,2);
W,b的梯度:
ΔW(l):=ΔW(l)+∇W(l)J(W,b;x,y)
Δb(l):=Δb(l)+∇b(l)J(W,b;x,y)
W1grad = W1grad + W1_pd; W2grad = W2grad + W2_pd; b1grad = b1grad + b1_pd; b2grad = b2grad + b2_pd;
最终更新权重:
b1grad=b1grad/10000; b2grad=b2grad/10000; W1grad=W1grad/10000+lambda*W_1; W2grad=W2grad/10000+lambda*W_2;
至此,代价函数就写完了。
3.检验梯度
最后,还要保证梯度算的没错。。。。文中提到了这样的检测方法:
g(θ)≈J(θ+EPSILON)−J(θ−EPSILON)2×EPSILON.
那么,我们就要对代价函数做上述的检测:
eps = 1e-4; m = size(theta,1); for i=1:m theta_p = theta; theta_p(i,:) = theta_p(i,:) + eps; theta_m = theta; theta_m(i,:) = theta_m(i,:) - eps; numgrad(i,:) = (J(theta_p) - J(theta_m))/(eps*2.0); end
其实有向量化的方法:
eps = 1e-4; m = size(theta,1); E = eye(m); for i = 1:m delta = E(:,i)*eps; numgrad(i) = (J(theta+delta)-J(theta-delta))/(eps*2.0); end
m一大,eye就超出了matlab的限制了,所以,我用的上一个。
这一步句,巨慢无比,因为要进行mx2次的J函数的运算。。。。
4.结果
相关文章推荐
- UFLDL Exercise: Convolutional Neural Network
- UFLDL稀疏编码器练习实现
- UFLDL矢量化编程练习:翻译
- UFLDL矢量化编程练习:遇到问题
- UFLDL矢量化编程练习:用MNIST数据集的稀疏自编码器训练实现
- UFLDL Exercise:Sparse Autoencoder
- UFLDL Exercise:PCA in 2D
- UFLDL Exercise:PCA and Whitening
- UFLDL Exercise:Softmax Regression
- UFLDL Exercise:Self-Taught Learning
- 稀疏自编码器及其实现——如何搞基
- 矢量化编程——以MNIST为例
- 主成分分析(PCA)——以2维图像为例
- 主成分分析与白化预处理
- Softmax回归——识别MINST数据库
- 自我学习(Self-Taught Learning)
- 从自我学习到深层网络——建立你的第1个深度网络分类器
- 线性解码器——解决数据缩放问题
- 卷积特征提取与池化(Pooling)——处理大型图像
- UFLDL Tutorial 线性回归