在這節中,咱們將學習有關向量化的內容。不管你是用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 來表示,這些元素最後就會變成θ1,θ2,θ3表示,由於MATLAB中的下標從1開始,這就是爲何這裏個人for循環,j從1取值到n+1,而不是從0取值到n。這是一個未向量化的代碼實現方式,咱們用一個for循環對n個元素進行加和。編程語言
做爲比較,接下來是向量化的代碼實現:ide
你把x和θ看做向量,而你只須要令變量prediction等於θTX,你就能夠這樣計算。與其寫全部這些for循環的代碼,你只須要一行代碼,這行代碼就是利用Octave 的高度優化的數值線性代數算法來計算x和θ這兩個向量的內積,這樣會使代碼更簡單,運行起來也將更加高效。這就是Octave 所作的而向量化的方法,在其餘編程語言中一樣能夠實現。函數
讓咱們來看一個C++ 的例子:學習
這是未向量化的代碼。一樣地,也是先初始化一個變量,而後再利用for循環。優化
下面是向量化的代碼實現:spa
與此相反,使用較好的C++數值線性代數庫,你能夠寫出像這樣的代碼,所以取決於你的數值線性代數庫的內容。你或許有個C++對象:向量θ和一個C++對象:向量x。你只須要在C++中將兩個向量相乘。根據你所使用的數值和線性代數庫的使用細節的不一樣,你最終使用的代碼表達方式可能會有些許不一樣,可是經過一個庫來計算內積,你能夠獲得一段更簡單、更有效的代碼。
如今,讓咱們來看一個更爲複雜的例子,這是線性迴歸算法梯度降低的更新規則: 我只是用θ0,θ1,θ2來寫方程,假設咱們有兩個特徵量,因此n=2,這些都是咱們須要對θ0,θ1,θ2來進行更新,這些都應該是同步更新。 3d
實現這三個方程的方法就是使用一個for循環,讓 j 等於0、一、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