转载自:http://www.cnblogs.com/tornadomeet/archive/2013/03/20/2970724.html
前言:
现在来进入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++程序中的引用。
实验流程:
首先运行主程序train.m中的步骤1,即随机采样出10000个小的patch,并且显示出其中的204个patch图像,图像显示如下所示:
然后运行train.m中的步骤2和步骤3,进行损失函数和梯度函数的计算并验证。进行gradient checking的时间可能会太长,我这里大概用了1个半小时以上(反正1个多小时还没checking完,所以去睡觉了),当用gradient checking时,发现误差只有6.5101e-11,远小于1e-9,所以说明前面的损失函数和偏导函数程序是对的。后面就可以接着用优化算法来求参数了,本程序给的是优化算法是L-BFGS。经过几分钟的优化,就出结果了。
最后的W1的权值如下所示:
实验代码:
train.m:
sampleIMAGES.m:
initializeParameters.m:
sparseAutoencoderCost.m:
computeNumericalGradient.m:
checkNumericalGradient.m:
display_network.m:
实验总结:
实验结果显示的那些权值图像代表什么呢?参考了内容Visualizing a Trained Autoencoder可以知道,如果输入的特征满足二泛数小于1的约束,即满足:
那么可以证明只有当输入的x中的每一维满足:时,其对隐含层的active才最大,也就是说最容易是隐含层的节点输出为1,可以看出,输入值和权值应该是正相关的。
2013.5.6补:
以前博文中在用vector的方式写sparseAutoencoderCost.m文件时,一直不成功,现已经解决该问题了,解决方法是:把以前的Iweight换成Jweight即可。
参考资料:
Exercise:Sparse Autoencoder
Deep learning:八(Sparse Autoencoder)
Autoencoders and Sparsity
Visualizing a Trained Autoencoder
UFLDL练习(Sparse Autoencoder)
http://code.google.com/p/nlsbook/source/browse/trunk/nlsbook/cs294ps1/starter/?r=28
版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/bcyy/47895.html