1. 程式人生 > >[斯坦福大學2014機器學習教程筆記]第五章-向量

[斯坦福大學2014機器學習教程筆記]第五章-向量

    在這節中,我們將學習有關向量化的內容。無論你是用Ocatve,還是別的語言,比如MATLAB或者你正在用Python、NumPy 或Java、C、C++,所有這些語言都具有內建的,容易閱讀和獲取的各種線性代數庫,它們通常寫得很好,已經經過高度優化,通常是數值計算方面的博士或者專業人士開發的。而當你實現機器學習演算法時,如果你能好好利用這些線性代數庫,或者數值線性代數庫,並聯合調用它們,而不是自己去做那些函式庫可以做的事情。如果是這樣的話,那麼通常你會發現:首先,這樣更有效,也就是說執行速度更快,並且更好地利用你的計算機裡可能有的一些並行硬體系統等等;其次,這也意味著你可以用更少的程式碼來實現你需要的功能。因此,實現的方式更簡單,出錯的可能性也就越小。舉個具體的例子:與其自己寫程式碼做矩陣乘法。如果你只在Octave中輸入a乘以b,它會利用一個非常有效的做法,計算兩個矩陣相乘。有很多例子可以說明,如果你用合適的向量化方法來實現,你的程式碼就會簡單得多,也有效得多。

    讓我們來看一些例子:這是一個常見的線性迴歸假設函式:hθ(x) = Σθjxj。如果你想要計算hθ(x),注意到右邊是求和,那麼你可以自己計算 j=0 到 j=n 的和。但換另一種方式來想想,把hθ(x)看作θTX,那麼你就可以寫成兩個向量的內積,其中θ就是θ0,θ1,θ2。如果你有兩個特徵量,如果n=2,並且如果你把x看作x0、x1、x2,這兩種思考角度,會給你兩種不同的實現方式。

    下面是未向量化的程式碼。未向量化的意思是沒有向量化。

    首先,我們初始化變數prediction的值為0.0,而這個變數prediction的最終結果就是hθ

(x),然後我要用一個for 迴圈,j 從1取值到n+1,變數prediction每次就通過自身加上θjxj的值,這個就是演算法的程式碼實現。順便我要提醒一下,之前的向量我用的下標是0,所以我有θ0,θ1,θ2,但因為MATLAB的下標從1開始,在MATLAB 中θ0可能會用θ來表示,這些元素最後就會變成θ1,θ2,θ3表示,因為MATLAB中的下標從1開始,這就是為什麼這裡我的for迴圈,j從1取值到n+1,而不是從0取值到n。這是一個未向量化的程式碼實現方式,我們用一個for迴圈對n個元素進行加和。

    作為比較,接下來是向量化的程式碼實現:

    你把x和θ看作向量,而你只需要令變數prediction等於θTX,你就可以這樣計算。與其寫所有這些for迴圈的程式碼,你只需要一行程式碼,這行程式碼就是利用Octave 的高度優化的數值線性代數演算法來計算x和θ這兩個向量的內積,這樣會使程式碼更簡單,執行起來也將更加高效。這就是Octave 所做的而向量化的方法,在其他程式語言中同樣可以實現。

    讓我們來看一個C++ 的例子:

    這是未向量化的程式碼。同樣地,也是先初始化一個變數,然後再利用for迴圈。

    下面是向量化的程式碼實現:

    與此相反,使用較好的C++數值線性代數庫,你可以寫出像這樣的程式碼,因此取決於你的數值線性代數庫的內容。你或許有個C++物件:向量θ和一個C++物件:向量x。你只需要在C++中將兩個向量相乘。根據你所使用的數值和線性代數庫的使用細節的不同,你最終使用的程式碼表達方式可能會有些許不同,但是通過一個庫來計算內積,你可以得到一段更簡單、更有效的程式碼。
    現在,讓我們來看一個更為複雜的例子,這是線性迴歸演算法梯度下降的更新規則:     我只是用θ0,θ1,θ2來寫方程,假設我們有兩個特徵量,所以n=2,這些都是我們需要對θ0,θ1,θ2來進行更新,這些都應該是同步更新。    

    實現這三個方程的方法就是使用一個for迴圈,讓 j 等於0、1、2來更新物件θj

    但讓我們用向量化的方式來實現,看看我們是否能夠有一個更簡單的方法,看看能不能一次實現這三個方程。讓我們來看看怎樣能壓縮成一行向量化的程式碼來實現。思路如下:我打算把θ看做一個向量,然後我用θ-α 乘以某個別的向量δ 來更新θ。這裡的δ等於(1/m)Σ(hθ(xi)-yi)xi

    讓我解釋一下是怎麼回事:我要把θ看做一個n+1維向量,α是一個實數,δ是一個向量。

    所以這個減法運算是一個向量減法,因為αδ是一個向量,所以θ更新為θ-αδ。那麼向量δ是什麼呢?

    其實δ代表的就是紅框框起來的內容。具體地說,δ是一個n+1維向量。向量δ的第一個元素就等於綠框框起來的內容。

    認真看一下計算δ的正確方式。

    前面是一個實數,後面是一個n+1維向量。然後再求和。

    實際上,如果你要解下面這個方程,我們為了向量化這段程式碼,我們會令u = 2v +5w因此,我們說向量u等於2乘以向量v加上5乘以向量w。

    用這個例子說明,如何對不同的向量進行相加,這裡的求和是同樣的道理。在這個求和公式中,只是一個實數乘以一個向量x1,就像上面的2乘以向量v。然後再加上實數乘以一個向量x2,就像上面的5乘以向量w。以此類推,再加上許多項實數乘以向量。這就是為什麼這一整個是一個向量δ的原因。具體而言,如果n=2,那麼δ就由三項相加而組成。這就是為什麼根據θ-αδ更新θ的時候可以實現同步更新。

    這就是為什麼我們能夠向量化地實現線性迴歸。所以,保證你確實能理解上面的步驟。如果你實在不能理解它們數學上等價的原因,你就直接實現這個演算法,也是能得到正確答案的,你仍然能實現線性迴歸演算法。如果你能弄清楚為什麼這兩個步驟是等價的,那我希望你可以對向量化有一個更好的理解。   

    如果你在實現線性迴歸的時候,使用一個或兩個以上的特徵量。有時我們使用幾十或幾百個特徵量來計算線性迴歸,當你使用向量化地實現線性迴歸時,通常執行速度就會比你以前用你的for迴圈快的多。因此使用向量化實現方式,你應該是能夠得到一個高效得多的線性迴歸演算法。而當你向量化我們將在之後的課程裡面學到的演算法,這會是一個很好的技巧,無論是對於Octave 或者一些其他的語言,如C++、Java 來讓你的程式碼執行得更高效。

最後附上有中文字幕視訊的連結:https://www.bilibili.com/video/BV164411b7dx/?p=31

&n