這篇文章主要介紹如何使用 Vectorization 來加速 Python 的數值運算,以及如何將 Logistic Regression 的 for-loops 轉換成 vectorization,以及如何將 gradient (backpropogation) 也進行向量化。Vectorization 可以大大提高數值運算的速度,甚至可以提高數百倍的速度。因此在編寫程式時,建議在可以使用 vectorization 時就應盡量避免使用 for loop 。
以下用一個 Python 例子來解釋 vectorization 的好處:假設我們要求 wTx,而 w,x 都是 1000000 * 1 的矩陣。
- 這是一個 for loop 方法:
w = np.random.rand(1000000)
x = np.random.rand(1000000)
c = 0
for i in range(1000000):
c += w[i] * x[i]
- 這是一個 vectorization 的方法:
import numpy as np
c = np.dot(w, x)
這些向量化的方法是利用 CPU 或 GPU 的 SIMD 平行指令,可以看到 vectorization 比 for loop 快上了三百多倍,因此以後在編寫程式時應盡量避免使用 for loop,而盡可能使用 vectorization。
"Whenever possible, avoid explicit for-loops"
Vectorizing Logistic Regression
我們將 forward propogation 的 for-loops 試著轉成 vectorization,利用 for-loops 我們必須要這樣做:
z(1)=wTx(1)+ba(1)=σ(z(1))z(2)=wTx(2)+ba(2)=σ(z(2))z(3)=wTx(3)+ba(3)=σ(z(3))...... 我們知道 X 是一個 nx * m 的矩陣
X=⎣⎡∣x(1)∣∣x(2)∣⋯∣x(m)∣⎦⎤ 我們可以將整個矩陣直接跟 wT 相乘,得到一個 1 * m 的 Z 矩陣
Z=[z(1)z(2)⋯z(m)]=wTX+b=[wTx(1)+bwTx(2)+b⋯wTx(m)+b] 然後再計算出 1 * m 的 A 矩陣
A=[a(1)a(2)⋯a(m)]=σ(Z) 在 python 中,Z 的運算如下
現在我們來將 gradient (backpropogation) 的 dZ,dw,db 也進行向量化,dZ 其實就是矩陣 A 和矩陣 y 相減。
dZ=[dz(1)dz(2)⋯dz(m)]=A−Y=[a(1)−y(1)a(2)−y(2)⋯a(m)−y(m)] 我們將 dw1, dw2, ... 組合成為一個 nx * 1 的 dw 矩陣
dw=m1XdZT=m1⎣⎡∣x(1)∣∣x(2)∣⋯∣x(m)∣⎦⎤⎣⎡dZ(1)⋮dZ(m)⎦⎤ 而 db 則是用 sum 的方法乘起來平均
db=m1i=1∑mdZ(i)=m1np.sum(dZ) 現在我們就能用一個 vectorization 的方法一次計算一個 gradient descent 的情形
Z = np.dot(w.T, X) + b
A = sigmoid(Z)
dZ = A - y
dw = 1/m * X * dZ.T
db = 1/m * np.sum(dZ)
w = w - a * dw
b = b - a * db