在不知道算法原理的情況下,如何閱讀理解算法的matlab程序
很多的時候,對於一個好的算法,我們沒有它相關的第一手材料,如其相關的論文、期刊文章、會議報告、專門課程、專門的講座、個人博客、百度文獻、維基百科、谷歌搜索內容等等。沒有這些材料,對算法原理的理解無疑猶如水中撈月,比登天還難。但是,我們只有算法的matlab程序。這時,如何只通過算法的matlab程序去理解算法的原理變爲很重要了。這種情景就像你剛進一家公司,上一屆的負責人把項目的程序扔給你後就拍屁股走人,沒有給你任何項目的相關材料,叫你一個人去研究項目的程序,在程序裏自己領悟。那怎樣從matlab程序中哪些抽象的常量、變量、函數等去理解其中算法的原理呢?
單從算法的五個特性來看,這就相當從算法的輸入與輸出找出算法原理(本質是處理數據的過程)。
下面我將我通過一個例子來講解“如何只通過算法的matlab程序去理解算法的原理”。
我們主要從幾方面去把握:
(1)把算法當成一個簡單的數據處理系統,即只有三大塊:輸入、輸出、處理過程。
(2)輸出量的定位反追蹤,即根據輸出量的表達式去尋找算法處理數據的步驟。
(3)思維的遷移,程序中各量的含義,三個層次:數學意義、物理意義、實際當中具體的例子
例子程序的代碼如下:
% Version 1.000
%
% Code provided by Ruslan Salakhutdinov and Geoff Hinton
%
% Permission is granted for anyone to copy, use, modify, or distribute this
% program and accompanying programs and documents for any purpose, provided
% this copyright notice is retained and prominently displayed, along with
% a note saying that the original programs are available from our
% web page.
% The programs and documents are distributed without any warranty, express or
% implied. As the programs were written for research purposes only, they have
% not been tested to the degree that would be advisable in any important
% application. All use of these programs is entirely at the user's own risk.
function [f, df] = CG_MNIST(VV,Dim,XX);
l1 = Dim(1);
l2 = Dim(2);
l3 = Dim(3);
l4= Dim(4);
l5= Dim(5);
l6= Dim(6);
l7= Dim(7);
l8= Dim(8);
l9= Dim(9);
N = size(XX,1);
% Do decomversion.
w1 = reshape(VV(1:(l1+1)*l2),l1+1,l2);
xxx = (l1+1)*l2;
w2 = reshape(VV(xxx+1:xxx+(l2+1)*l3),l2+1,l3);
xxx = xxx+(l2+1)*l3;
w3 = reshape(VV(xxx+1:xxx+(l3+1)*l4),l3+1,l4);
xxx = xxx+(l3+1)*l4;
w4 = reshape(VV(xxx+1:xxx+(l4+1)*l5),l4+1,l5);
xxx = xxx+(l4+1)*l5;
w5 = reshape(VV(xxx+1:xxx+(l5+1)*l6),l5+1,l6);
xxx = xxx+(l5+1)*l6;
w6 = reshape(VV(xxx+1:xxx+(l6+1)*l7),l6+1,l7);
xxx = xxx+(l6+1)*l7;
w7 = reshape(VV(xxx+1:xxx+(l7+1)*l8),l7+1,l8);
xxx = xxx+(l7+1)*l8;
w8 = reshape(VV(xxx+1:xxx+(l8+1)*l9),l8+1,l9);
XX = [XX ones(N,1)];
w1probs = 1./(1 + exp(-XX*w1)); w1probs = [w1probs ones(N,1)];
w2probs = 1./(1 + exp(-w1probs*w2)); w2probs = [w2probs ones(N,1)];
w3probs = 1./(1 + exp(-w2probs*w3)); w3probs = [w3probs ones(N,1)];
w4probs = w3probs*w4; w4probs = [w4probs ones(N,1)];
w5probs = 1./(1 + exp(-w4probs*w5)); w5probs = [w5probs ones(N,1)];
w6probs = 1./(1 + exp(-w5probs*w6)); w6probs = [w6probs ones(N,1)];
w7probs = 1./(1 + exp(-w6probs*w7)); w7probs = [w7probs ones(N,1)];
XXout = 1./(1 + exp(-w7probs*w8));
f = -1/N*sum(sum( XX(:,1:end-1).*log(XXout) + (1-XX(:,1:end-1)).*log(1-XXout)));
IO = 1/N*(XXout-XX(:,1:end-1));
Ix8=IO;
dw8 = w7probs'*Ix8;
Ix7 = (Ix8*w8').*w7probs.*(1-w7probs);
Ix7 = Ix7(:,1:end-1);
dw7 = w6probs'*Ix7;
Ix6 = (Ix7*w7').*w6probs.*(1-w6probs);
Ix6 = Ix6(:,1:end-1);
dw6 = w5probs'*Ix6;
Ix5 = (Ix6*w6').*w5probs.*(1-w5probs);
Ix5 = Ix5(:,1:end-1);
dw5 = w4probs'*Ix5;
Ix4 = (Ix5*w5');
Ix4 = Ix4(:,1:end-1);
dw4 = w3probs'*Ix4;
Ix3 = (Ix4*w4').*w3probs.*(1-w3probs);
Ix3 = Ix3(:,1:end-1);
dw3 = w2probs'*Ix3;
Ix2 = (Ix3*w3').*w2probs.*(1-w2probs);
Ix2 = Ix2(:,1:end-1);
dw2 = w1probs'*Ix2;
Ix1 = (Ix2*w2').*w1probs.*(1-w1probs);
Ix1 = Ix1(:,1:end-1);
dw1 = XX'*Ix1;
df = [dw1(:)' dw2(:)' dw3(:)' dw4(:)' dw5(:)' dw6(:)' dw7(:)' dw8(:)' ]';
一、算法三大塊
輸入:在matlab函數定義的時候,我們可以看到有那幾個輸入量
輸出:在matlab函數定義的時候,我們可以看到有那幾個輸出量
處理過程:這一塊,我們主要看整個程序的階段性註釋。好的程序可讀性都很強。我們通過程序塊的註釋瞭解程序處理大體的步驟。
二、確定已知量和未知量
要從函數的定義、程序的註釋、變量的定義當中去確定那個量是已知的,那個是未知的。這個環節很重要。它可以幫你理清程序是如何求解的。因爲在數學中,我們都是用已知量來求解未知量的,而且未知量一定有其求解的過程。
三、輸出量的定位反追蹤
輸出量的定位:(1)確定各個輸出量最後一次被賦值的位置
反追蹤:(1)由輸出量的最後一次被賦值的位置開始,由下往上追蹤輸出量的變化,畫出輸出量由下而上變化的流線圖
(2)有用下而上的變化流線圖寫出由上至下的變化流線圖,即是程序求解輸出量的過程
四、思維的遷移
至此,我們已經知道了變量的整個求解過程。那麼,接下來,我們要弄清在輸出量、輸出量表達式中的變量和求解輸出量過程中所涉及的變量的最抽象層數學含義、處於次層的物理意義、最具體的最形象的代表事例。這個環節對算法的理解是非常重要的,也是最實際的。在此階段,我們不但掌握了算法的原理,還可以把算法應用到相關的領域。
..............