今天来做UFLDL的第二个实验,向量化。我们都知道,在matlab里面基本上如果使用for循环,程序是会慢的一逼的(可以说基本就运行不下去)所以在这呢,我们需要对程序进行向量化的处理,所谓向量化就是将matlab里面所有的for循环用矩阵运算的方法实现,在这里呢,因为之前的实验我已经是按照向量化的形式编写的代码,所以这里我只把我对代码修改的部分发上来供大家参考吧。本文为本人原创,参考了UFLDL的教程,是我自己个人对于这一系列教程的理解以及自己的实验结果。非盈利性质网站转载请在文章开头处著名本文作者:77695,来源http://www.cnblogs.com/cj695/。盈利性质网站转载请与作者联系,联系方式在文章后面。如未联系,本人将通过一切可能且合法的途径追缴相应稿酬。请在转载时保留此声明。
这是我们使用的数据集,采用的是MNIST数据库里面的手写字符。读取数据集有一定的方法,这个现成的代码在UFLDL的教程里面是可以下载的。读取完数据集显示效果如下:
最后训练得到的结果如下
代码第一处要修改的是在train的地方,要把参数修改为这次实验的参数:
visibleSize = 28*28; % number of input units hiddenSize = 14*14; % number of hidden units sparsityParam = 0.1; % desired average activation of the hidden units. % (This was denoted by the Greek alphabet rho, which looks like a lower-case "p", % in the lecture notes). lambda = 0.003; % weight decay parameter beta = 3; % weight of sparsity penalty term
其次在computeNumericalGradient的地方,把梯度检测数目减小:
for i=1 :min(size(theta,1),2) e = zeros(size(theta)); e(i)=EPSILON; cha=(J(theta+e)-J(theta-e)); numgrad(i)=cha/(2*EPSILON); end
最后,取样图片,使用UFLDL提供的现成的读取MNIST数据库的函数即可:
function patches = sampleIMAGES() img=loadMNISTImages(‘train-images.idx3-ubyte‘); patches=img(:,10001:20000); % patches = normalizeData(patches); % 在实现手写字符识别时,是不需要对其做归一化处理的 end
注意:在做手写字符识别时,使用MNIST的数据库是不需要再对数据做归一化处理的,如果做了归一化处理,结果可能反而会出错。
上图是做了归一化之后的结果,可以很明显的看到,归一化之后,每一个数字的格子之间的背景亮度是有一定差距的。
使用归一化之后的数据经性训练,最后得到的结果如下图:
可以看到,这个结果与之前的结果比的话,并不能足矣用这些基来表达整个数据,因此是不好的。
为什么会出现这样一个结果呢,我们来看一下归一化之后的结果:
下面是没有归一化的结果
可以看到没有归一化数据是从0-0.99的,变化范围大,而归一化后,数据变化范围只有0.5,这显然是不对的。要清楚的是,MINIST数据集本身就已经对数据进行了归一化的处理因此我们就不用画蛇添足了。