小白学《神经网络与深度学习》笔记之二-利用稀疏编码器找图像的基本单位(1)MatLab实现SparseAutoEncoder

前言

学完稀疏自编码器,参考http://deeplearning.stanford.edu/wiki/index.php/UFLDL%E6%95%99%E7%A8%8B中的Exercise:Sparse Autoencoder

使用MatLab完成练习要求。这个例子所要实现的内容大概如下:从给定的数据文件IMAGES.mat(这是一个512*512*10的三维数组,里面存了10张图片,每张图片像素为262144)中截取出大小为8*8的小patches图片共10000张,现在需要用sparse autoencoder的方法训练出一个隐含层网络所学习到的特征。该网络共有3层,输入层是64个节点,隐含层是25个节点,输出层当然也是64个节点了。

实验基础:

其实实现该功能的主要步骤还是需要计算出网络的损失函数以及其偏导数,具体的公式可以参考这篇博文Deep learning:八(Sparse Autoencoder)。下面用简单的语言大概介绍下这个步骤,方便大家理清算法的流程。

1. 计算出网络每个节点的输入值(即程序中的z值)和输出值(即程序中的a值,a是z的sigmoid函数值)。

2. 利用z值和a值计算出网络每个节点的误差值(即程序中的delta值)。

3. 这样可以利用上面计算出的每个节点的a,z,delta来表达出系统的损失函数以及损失函数的偏导数了,当然这些都是一些数学推导,其公式就是前面的博文Deep learning:八(Sparse Autoencoder)了。

其实步骤1是前向进行的,也就是说按照输入层——》隐含层——》输出层的方向进行计算。而步骤2是方向进行的(这也是该算法叫做BP算法的来源),即每个节点的误差值是按照输出层——》隐含层——》输入层方向进行的。

一些malab函数:

bsxfun:

C=bsxfun(fun,A,B)表达的是两个数组A和B间元素的二值操作,fun是函数句柄或者m文件,或者是内嵌的函数。在实际使用过程中fun有很多选择比如说加,减等,前面需要使用符号’@’.一般情况下A和B需要尺寸大小相同,如果不相同的话,则只能有一个维度不同,同时A和B中在该维度处必须有一个的维度为1。比如说bsxfun(@minus, A, mean(A)),其中A和mean(A)的大小是不同的,这里的意思需要先将mean(A)扩充到和A大小相同,然后用A的每个元素减去扩充后的mean(A)对应元素的值。

rand:

生成均匀分布的伪随机数。分布在(0~1)之间
主要语法:rand(m,n)生成m行n列的均匀分布的伪随机数
rand(m,n,'double')生成指定精度的均匀分布的伪随机数,参数还可以是'single'
rand(RandStream,m,n)利用指定的RandStream(我理解为随机种子)生成伪随机数

randn:

生成标准正态分布的伪随机数(均值为0,方差为1)。主要语法:和上面一样

randi:

生成均匀分布的伪随机整数
主要语法:randi(iMax)在闭区间(0,iMax)生成均匀分布的伪随机整数
randi(iMax,m,n)在闭区间(0,iMax)生成mXn型随机矩阵
r = randi([iMin,iMax],m,n)在闭区间(iMin,iMax)生成mXn型随机矩阵

exist:

测试参数是否存在,比如说exist('opt_normalize', 'var')表示检测变量opt_normalize是否存在,其中的’var’表示变量的意思。

colormap:

设置当前常见的颜色值表。

floor:

floor(A):取不大于A的最大整数。

ceil:

ceil(A):取不小于A的最小整数。

imagesc:

imagesc和image类似,可以用于显示图像。比如imagesc(array,'EraseMode','none',[-1 1]),这里的意思是将array中的数据线性映射到[-1,1]之间,然后使用当前设置的颜色表进行显示。此时的[-1,1]充满了整个颜色表。背景擦除模式设置为node,表示不擦除背景。

repmat:

该函数是扩展一个矩阵并把原来矩阵中的数据复制进去。比如说B = repmat(A,m,n),就是创建一个矩阵B,B中复制了共m*n个A矩阵,因此B矩阵的大小为[size(A,1)*m size(A,2)*m]。

SUM(X,DIM) :

sums along the dimension DIM.

If   X = [0 1 2; 3 4 5]
then sum(X, 1) is [3 5 7] and sum(X, 2) is [3; 12]

以上部分摘自博客:

http://www.cnblogs.com/tornadomeet/archive/2013/03/20/2970724.html

Andrew ng原文:http://deeplearning.stanford.edu/wiki/index.php/Exercise:Sparse_Autoencoder

源码以及数据:http://ufldl.stanford.edu/wiki/resources/sparseae_exercise.zip

程序过程解析

step0:参数初始化

visibleSize = 8*8;   % 输入特征数,也是每个小图片的维数
hiddenSize = 25;     % 隐层节点数
sparsityParam = 0.01;   % 期望稀疏值
lambda = 0.0001;     % 权值惩罚参数      
beta = 3;                     % weight of sparsity penalty term

step1:调用sampleIMAGES函数,加载并处理数据

patches = sampleIMAGES;  %patches函数的作用就是把每个小patch拉成一个列向量
display_network(patches(:,randi(size(patches,2),200,1)),8); %显示200个patch的随机样本
theta = initializeParameters(hiddenSize, visibleSize);

1)sampleIMAGE函数关键部分解析

for imageNum = 1:10%在每张图片中随机选取1000个patch,共10000个patch
    [rowNum colNum] = size(IMAGES(:,:,imageNum));
    for patchNum = 1:1000%实现每张图片选取1000个patch
        xPos = randi([1,rowNum-patchsize+1]);%randi用于生产随机整数矩阵randi([min max],m,n)
        yPos = randi([1, colNum-patchsize+1]);
        patches(:,(imageNum-1)*1000+patchNum) = reshape(IMAGES(xPos:xPos+7,yPos:yPos+7,...
                                                        imageNum),64,1);%reshap函数,将8*8的方阵,变形为64*1的列向量
    end
end

处理数据

patches = normalizeData(patches);normalizeData()函数先使用标准差使数据范围变为-1到1,之后再变换到[0.1,0.9],以便和sigmoid函数输出值匹配

function patches = normalizeData(patches) 

% Squash data to [0.1, 0.9] since we use sigmoid as the activation 
% function in the output layer 

% Remove DC (mean of images).  
patches = bsxfun(@minus, patches, mean(patches)); 

% Truncate to +/-3 standard deviations and scale to -1 to 1 
pstd = 3 * std(patches(:)); 
patches = max(min(patches, pstd), -pstd) / pstd; 

% Rescale from patches:[-1,1] to [0.1,0.9] 
patches = (patches + 1) * 0.4 + 0.1; 

2)initializeParameters函数

通过输入层和隐层节点数,初始化权值矩阵和偏置项矩阵。

初始化权值矩阵是,是通过在[-r, r]区间内随机初始化矩阵r  = sqrt(6) / sqrt(hiddenSize+visibleSize+1)=0.2582;(这个我不不清楚为啥,只知道Andrew教程中权值初始值要随机,且随机数值不应过大)

W1 = rand(hiddenSize, visibleSize) * 2 * r - r;
W2 = rand(visibleSize, hiddenSize) * 2 * r - r;

b1 = zeros(hiddenSize, 1);
b2 = zeros(visibleSize, 1);

theta = [W1(:) ; W2(:) ; b1(:) ; b2(:)];把矩阵向量化,通过向量来传递参数;个人猜测应该是通过向量传参效率高

STEP 2: 实现 sparseAutoencoderCost,稀疏损失函数

[cost, grad] = sparseAutoencoderCost(theta, visibleSize, hiddenSize, lambda, ...
                                     sparsityParam, beta, patches);

1)通过反转向量,把向量还原为权值矩阵

2)计算损失函数和梯度

最后把矩阵权值向量化,当做参数传递出来

grad = [W1grad(:) ; W2grad(:) ; b1grad(:) ; b2grad(:)];

STEP 3: 通过l-bfgs算法优化训练稀疏矩阵

theta = initializeParameters(hiddenSize, visibleSize);

%  Use minFunc to minimize the function
addpath minFunc/
options.Method = 'lbfgs'; % Here, we use L-BFGS to optimize our cost
                          % function. Generally, for minFunc to work, you
                          % need a function pointer with two outputs: the
                          % function value and the gradient. In our problem,
                          % sparseAutoencoderCost.m satisfies this.
options.maxIter = 400;	  % Maximum number of iterations of L-BFGS to run 
options.display = 'on';

[opttheta, cost] = minFunc( @(p) sparseAutoencoderCost(p, ...
                                   visibleSize, hiddenSize, ...
                                   lambda, sparsityParam, ...
                                   beta, patches), ...
                              theta, options);

STEP4:可视化学习到的权值矩阵W1.

W1 = reshape(opttheta(1:hiddenSize*visibleSize), hiddenSize, visibleSize);
display_network(W1', 12); 
print -djpeg weights.jpg   % save the visualization to a file 
 
weights 
 

参考:http://blog.csdn.net/whiteinblue/article/details/20639629

https://github.com/danluu/ufldl-tutorial

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值