今天來做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數據集本身就已經對數據進行了歸一化的處理因此我們就不用畫蛇添足了。