1.視頻網站:mooc慕課https://mooc.study.163.com/university/deeplearning_ai#/c
2.詳細筆記網站(中文):http://www.ai-start.com/dl2017/
3.github課件+作業+答案:https://github.com/stormstone/deeplearning.ai
2.11 向量化 Vectorization-加速計算
向量化是非常基礎的去除代碼中for循環的藝術。在深度學習領域,運行向量化是一個關鍵的技巧。
在邏輯迴歸中你需要去計算,在第一節中已經介紹過,這裏的w,x都是列向量。如果你有很多的特徵那麼就會有一個非常大的向量,,。
如果你想使用非向量化方法去計算,代碼如下
z=0
for i in range(n_x)
z+=w[i]*x[i]
z+=b
如果改用向量化方式,代碼如下
z=np.dot(w,x)+b
你將會發現這個方法非常快。
讓我們用下面這個小例子說明一下。
import numpy as np #導入numpy庫
a = np.array([1,2,3,4]) #創建一個數組a
print(a)
# [1 2 3 4]
import time #導入時間庫
a = np.random.rand(1000000)
b = np.random.rand(1000000) #通過round隨機得到兩個一百萬維度的數組
tic = time.time() #現在測量一下當前時間
#向量化的版本
c = np.dot(a,b)
toc = time.time()
print("c=",c)
print("Vectorized version:" + str(10000*(toc-tic)) +"ms") #打印一下向量化的版本的時間
#繼續增加非向量化的版本
c = 0
tic = time.time()
for i in range(1000000):
c += a[i]*b[i]
toc = time.time()
print("c=",c)
print("For loop:" + str(10000*(toc-tic)) + "ms")#打印for循環的版本的時間
在python中運行結果如下
[1 2 3 4]
c= 249939.826271
Vectorized version:99.10821914672852ms
c= 249939.826271
For loop:8998.942375183105ms
在兩個方法中,向量化和非向量化計算了相同的c值,如你所見,非向量化版本多花費了90倍時間。
所以說,向量化後運行速度會大幅提升。
CPU和GPU都有並行化指令,有時候會叫SIMD指令,意思是單指令多維數據。SIMD指令的意義是,如果你使用了內置函數,例如:np.function或者其他能讓你去掉顯示for循環的函數,此時python的numpy能夠充分利用並行化,去更快的計算。這一點,在CPU和GPU上計算都是成立的。
GPU更加擅長SIMD計算,事實上CPU也不是太差,可能沒有GPU那麼擅長吧。
2.12 向量化的更多例子 More vectorization examples
上一節我們瞭解了通過numpy內置函數和避開顯式的for循環的方式進行向量化,從而有效提高代碼速度。
經驗法則:當我們在寫神經網絡程序時,或者在寫邏輯迴歸,或者其他神經網絡模型時,應該避免寫循環語句。
再來看一些例子。
例1
如果你想計算向量,根據矩陣乘法的定義,。
如果用非向量化計算
u=np.zeros((n,1)) #初始化
for i...
for j...
u[i]+=A[i][j]*v[j]
這是一個雙重循環。
改用向量化計算
u=np.dot(A,v)
這裏消除了2個循環,速度會更加快。
例2
假設有向量,現在要對向量v的每個元素做指數操作,
先使用非向量化方式
u=np.zeros((n,1)) #初始化向量u
for i in range(n): #通過循環依次計算每個元素
u[i]=math.exp(v[i]) #一次計算一個元素
向量化方式,利用內置函數替換了上面的顯示for循環。
import numpy as np
u=np.exp(v)
向量化代碼執行的效率會快很多。
numpy有很多內置函數,例如:np.log()計算log,np.abs()計算絕對值,np.maximum()計算最大值。
所以當你想寫循環時候,先檢查numpy是否存在類似的內置函數,從而避免使用循環方式。
在第10節中,我們實現邏輯迴歸中的梯度下降算法中曾經說過會有2個for循環。
其中第二個for循環是因爲如果樣本的特徵值非常多,需要對每個特徵值進行循環遍歷。
這裏我們可以用向量化方法來替換
step1.替換初始化過程
不用初始化 dw1,dw2…dwn 都等於0。改用dw=np.zeros((n,1)),定義了n*1維向量。
step2.替換dw1,dw2…dwn循環計算
dw1 += x1(i)dz(i);#導數,參數w1變化對J的影響。注意:這裏沒有上標i,是累加整個訓練集合上的和。
dw2 += x2(i)dz(i);#導數,參數w2變化對J的影響。注意:這裏沒有上標i,是累加整個訓練集合上的和。
...
dwn += xn(i)dz(i);
替換爲dw+=x(i)dz(i)
step3.替換最後的求平均值dw=dw/m
上面的圖詳細說明了第二個for循環被替換過程。
在下一節,我們將進一步的講解邏輯迴歸,你將會看到更好的監督學習結果。在訓練中將不需要使用任何 for 循環,你也可以寫出代碼去運行整個訓練集。