SparseAutoEncoder 稀疏编码详解(Andrew ng课程系列)

SparseAutoEncoder 稀疏编码详解(Andrew ng课程系列)

先简单叙述问题,源码详细解析在下面

前言      

首先介绍sparse autoencoder的一个实例练习,参考Ng的网页教程:Exercise:Sparse Autoencoder。这个例子所要实现的内容大概如下:从给定的很多张自然图片中截取出大小为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]。

  使用函数句柄的作用:

  不使用函数句柄的情况下,对函数多次调用,每次都要为该函数进行全面的路径搜索,直接影响计算速度,借助句柄可以完全避免这种时间损耗。也就是直接指定了函数的指针。函数句柄就像一个函数的名字,有点类似于C++程序中的引用。

以上部分摘自博客:

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; 

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

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函数输出值匹配

2)initializeParameters函数

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

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

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

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

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

2)计算损失函数和梯度

由于画图和矩阵的原因,原稿使用ppt来制作的,现在就只能通过贴图的方式展现了,有需要ppt的可以私信我

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

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

STEP 3: 通过l-bfgs算法优化

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

 

posted @ 2015-11-11 16:23  菜鸡一枚  阅读(426)  评论(0编辑  收藏  举报