1 向量化( Vectorization )python
在邏輯迴歸中,以計算z爲例,$ z = w^{T}+b $,你能夠用for循環來實現。數組
可是在python中z能夠調用numpy的方法,直接一句$z = np.dot(w,x) + b$用向量化完成,並且你會發現這個很是快。網絡
ng作了個實驗,求兩個100萬長的一維向量的內積,用向量化花了1.5毫秒,而用for循環計算花了400多毫秒。函數
因此日常記得用向量化,必定要避免使用for循環,你的代碼會快不少。3d
CPU和GPU都有並行化的指令,有時候叫SIMD( single instruction multiple data )。調試
若是你使用了這樣的內置函數,好比np.function,python的numpy能充分利用並行化去更快的計算。blog
2 更多向量化的例子( More Vectorization Examples )ip
平時要避免使用for循環,善用python的numpy庫中的內置函數。文檔
好比矩陣A和向量v的內積,能夠用np.dot。對一列向量v實施指數運算,能夠用np.exp,還有各類np.log,np.abs,np.maxmum( v, 0)等等。io
對於 v**2, 1/v這樣的操做也要考慮用np裏的函數。
3 向量化邏輯迴歸( Vectorizing Logistic Regression )
對於邏輯迴歸的導數計算也應該使用向量化,徹底不用for循環。圖中給出了向量化的過程。
Z的計算的向量化形式是$z = np.dot(w.T,x) + b$,其中b在這裏是一個實數,python在向量和實數相加時,會自動把實數變成一個相同維度的向量再相加。
其中w是n * 1的列向量,w.T是1 * n的列向量,X是n * m的矩陣,結果就是1 * m的向量,最後加上1 * m的b向量,獲得1 * m的Z。最後經過sigmoid獲得預測值A。
同時還能夠利用向量化計算m個數據的梯度,注意是同時計算。下圖左邊是for循環的實現,右邊是向量化的實現。
這裏dz是代價函數對z變量的導數,以前推導過等於預測值減去實際值a - y。
dw是代價函數對w的導數,db是代價函數對b的導數,若是不記得了能夠翻看上一節課,邏輯迴歸的內容。
雖然要儘可能使用向量化,可是在進行屢次梯度降低的迭代仍是要用到for循環,這個不可避免。
4 python中的廣播( python broadcasting)
當你用一個向量加上一個數的時候,python會自動把這個數變成向量再一一相加。
當你用一個m*n的矩陣加(減乘除)上1*n的向量時,python會自動把1*n的向量豎直複製變成m*n再相加。
當你用一個m*n的矩陣加上m*1的向量時,python會自動把m*1的向量水平復制變成m*n再相加。
這是實現神經網絡時主要用到的廣播,更詳細的能夠查看numpy文檔搜索broadcasting。
對於numpy中的一些用法須要瞭解,能夠幫助你更高效地用矩陣運算來提高程序效率,ng在本節還舉了求百分比的例子。
$A.sum(axis=0)$表明豎直求和,若是axis = 1就是水平求和。
5 python / numpy中的向量說明( A note on python/numpy vectors )
numpy和廣播使咱們能夠用一行代碼完成不少運算。
但有時可能會引入很是細微的錯誤,很是奇怪的bug,若是你不熟悉全部的複雜的廣播運做方式。
好比你以爲一個行向量和列向量相加應該會報錯,可是並不會,並且也不是簡單的一一相加。
python這些奇怪的效果有其內在邏輯,若是不熟悉python,你可能會寫出奇怪的難以調試的bug。
ng的建議,在實現神經網絡的時候不要使用shape爲(n,)這樣的變量,要用(n,1)。
好比a 的 shape是(5, ) ,當你計算$np.dot(a, a.T)$的時候獲得的是一個實數,a和a的轉置,它們的shape都是(5, )。
若是a 的 shape是(5, 1),你計算$np.dot(a, a.T)$的時候獲得的就是一個5*5的矩陣。a的shape是( 5, 1),而a.T的shape是( 1, 5 )。
a.shape = (5, )這是一個秩爲1的數組,不是行向量也不是列向量。不少學生出現難以調試的bug都來自秩爲1數組。
另外你在代碼中作了不少事情後可能不記得或者不肯定a是怎樣的時候,用$assert( a.shape == (5,1) )$來檢查你的矩陣的維度。
若是你獲得了(5,) 你能夠把它reshape成(5, 1)或(1, 5),reshape是很快的O(1)複雜度,因此放心大膽的用它,不用擔憂。