從邏輯迴歸開始入門深度學習

從邏輯迴歸開始入門深度學習

本文主要來源於吳恩達《深度學習與神經網絡》。本文根據課程內容做一個串聯。

本文內容安排如下:

  • 符號定義
  • 邏輯迴歸LR:定義、實現、高效實現
  • 淺層神經網絡(2層):實現、優化
  • 深度神經網絡:實現、優化、應用

我們以一個分類問題作爲研究背景。研究問題爲判斷輸入圖片是否爲貓咪的二分類。

符號定義

在解決問題之前,我們先對使用的數學符號做一個定義:

  • (x, y): 輸入樣本; x ∈ RnxR^{n_x}, y ∈ {0, 1}
  • {(x(1),y(1)),(x(2),y(2))...(x(m),y(m))(x^{(1)}, y^{(1)}), (x^{(2)}, y^{(2)})... (x^{(m)}, y^{(m)})}: 訓練數據集,包含m個訓練樣本
  • [a,b,c,…,z].T: 向量,默認情況下,向量指的是列向量
  • m=mtrainm = m_{train}, mtestm_{test}=#test examples
  • $X \in R^{n_x * m} :XX.shape=(: 訓練集,訓練樣本以**列的方式**進行堆疊,換言之,X矩陣的每一列是一個樣本,而不是行; X.shape = (n_x$, m)
  • YR1mY \in R^{1*m}: 訓練標籤,標籤以列的方式進行堆疊, Y.shape=(1,m)Y.shape = (1,m)

邏輯迴歸

在介紹邏輯回顧處理圖片分類。我們處理的問題是二分類,輸入一張圖片判斷圖片中是否有貓。輸入圖片格式爲RGB三色圖,像素取值爲0~255。

img

原理介紹

邏輯迴歸用於處理二分類問題。邏輯迴歸中h^=P(y=1x)\hat{h} = P(y=1|x)用於計算輸入樣本爲1的概率。以單個樣本爲例,其計算公式爲
y^=sigmoid(wTx+b) \hat{y} = sigmoid(w^Tx+b)
其中,xRnxx \in R^{n_x}, wRnxw \in R^{n_x} ,bRb \in R。輸出結果的取值範圍爲[0, 1]。

邏輯迴歸其實是線性迴歸的進一步加工,線性迴歸計算結果的取值範圍爲(,+)(-\infty, +\infty),我們將線性迴歸的計算結果使用sigmoid將範圍壓縮到[0, 1].

Sigmoid是一種非線性的S型函數,取值範圍在[0, 1],這種輸出值可以別理解爲概率表示。Sigmoid函數的計算公式和曲線如下。
Sigmoid(z)=11+ez Sigmoid(z) = \frac{1}{1+e^{-z}}
Sigmoid

從上圖可以看出,sigmoid取值範圍爲[0, 1],當自變量z非常小時,sigmoid趨近於0;當z非常大時,sigmoid趨近於1(實際上當z=10時,輸出值爲0.9999,非常趨近於1)。

Loss function

我們現在知道了如何使用邏輯迴歸計算一個樣本爲正例的概率,那麼如何評估模型的好壞呢?這就依賴於損失函數。

給定一個樣本(x(i),y(i))(x^{(i)}, y^{(i)}),使用邏輯迴歸計算這個樣本爲正例的概率P(y=1|x),
y^(i)=σ(wTx(i)+b),where σ(z)=11+ez \hat{y}^{(i)} = \sigma(w^Tx^{(i)} + b), where \ \sigma(z)=\frac{1}{1+e^{-z}}
理想情況下,輸出結果y^\hat y應該和樣本標籤y儘可能相等,即y^(i)y(i)\hat y^{(i)} \approx y^{(i)}
L(y^,y)=(ylogy^+(1y)log(1y^)) L(\hat y, y) = -(ylog\hat y + (1-y)log(1-\hat y))
當y=1時,L(y^,y)=logy^L(\hat y, y)=-log\hat y;當y=0時,L(y^,y)=log(1y^)L(\hat y, y) = -log(1-\hat y).

在全部訓練樣本上,損失函數cost function爲
J(w,b)=1mi=1mL(y^,y)=1mi=1m[y(i)logy^(i)+(1y(i))log(1y^(i))] J(w, b) = \frac1{m}\sum_{i=1}^m L(\hat y, y) = -\frac1{m}\sum_{i=1}^m[y^{(i)}log\hat y^{(i)} + (1-y^{(i)})log(1-\hat y^{(i)})]
損失函數是參數w,b的函數,我們想要通過最小化損失函數找到最佳的參數w,b,最後用於樣本的預測[通過最小化損失函數,我們可以保證預測結果與真實樣本標籤之間差距儘可能小,進而保證預測結果的準確性]。

LR損失函數可以使用最大似然估計來進行推導。

Gradient Descent

知道了模型的損失函數,接下來就是通過最小化損失函數得到最終的參數w,b。常用的方法是使用梯度下降法,使用當前位置的偏導數對參數進行更新,反覆多次後,損失函數到達最低點,此時w,b即爲最終結果。

Gradient Descent

使用梯度下降算法,w,b的更新公式如下:
w=wαJ(w,b)wb=bαJ(w,b)b w = w - \alpha \frac{\partial J(w, b)}{\partial w} \\b = b - \alpha \frac{\partial J(w, b)}{\partial b}
其中,α\alpha爲學習率,含義是每次參數更新的步幅;如果α\alpha過大,導致參數更新幅度過大,可能會錯過模型的最優值;如果α\alpha過下,導致每次更新幅度很小,模型需要更多的迭代次數才能收斂。在程序代碼中,我們使用dw表示J(w,b)w\frac{\partial J(w, b)}{\partial w}, db表示J(w,b)b\frac{\partial J(w, b)}{\partial b}.

計算圖

神經網絡的計算過程一般分爲兩個階段:前向傳播和反向傳播。使用計算圖來描述計算過程更清晰:將整個計算過程分步驟進行計算。

假設J(a, b, c) = 3(a + bc),其中a=5, b=3, c=2.這個計算過程可以使用計算圖來描述,如:

設定u = bc, v = a + u, J=3v.

反向傳播過程,需要計算da, db, dc.此時,可以通過計算圖依據鏈式法則進行計算。
Ja=Jvva=31=3 \frac{\partial J}{\partial a} = \frac{\partial J}{\partial v} * \frac{\partial v}{\partial a} = 3 * 1 = 3

Jb=Jvvuub=31c=6 \frac{\partial J}{\partial b} = \frac{\partial J}{\partial v} * \frac{\partial v}{\partial u} * \frac{\partial u}{\partial b}= 3 * 1 * c= 6

Jc=Jvvuuc=31b=9 \frac{\partial J}{\partial c} = \frac{\partial J}{\partial v} * \frac{\partial v}{\partial u} * \frac{\partial u}{\partial c}= 3 * 1 * b= 9

在計算圖中,藍色線爲前向傳播計算過程,紅色線爲反向傳播計算過程。

LR的優化計算

通過上面的計算圖我們知道了神經網絡的計算流程。下面我們使用計算圖來描述單個樣本的邏輯迴歸的計算過程,然後擴展到m個樣本上;之後介紹LR的優化過程,即向量化。

單個樣本的計算

單個樣本的邏輯迴歸計算公式如下:
y^=σ(wTx+b),where σ(z)=11+ezL(y^,y)=[ylogy^+(1y)log(1y^)] \hat y = \sigma(w^Tx+b), where \ \sigma(z)=\frac1{1+e^{-z}} \\L(\hat y, y) = -[ylog\hat y + (1-y)log(1-\hat y)]
我們假設訓練樣本x的維度爲2(有兩個特徵x1、x2)。

描述邏輯迴歸的loss函數的計算圖將運算過程分爲3步, 分別爲計算z、y^\hat y,以及L(a,y)。

邏輯迴歸的參數更新法則如下:
w1=w1αLw1w2=w2αLw2b=bαLb w_1 = w_1 - \alpha * \frac{\partial L}{\partial w_1} \\w_2 = w_2 - \alpha * \frac{\partial L}{\partial w_2}\\b = b - \alpha * \frac{\partial L}{\partial b}
因此,接下來的計算過程主要集中在偏導數Lw1\frac{\partial L}{\partial w_1}, Lw2\frac{\partial L}{\partial w_2}以及Lb\frac{\partial L}{\partial b}的計算。

從計算圖來看:
Ja=[yloga+(1y)log(1a)]a=[ya1y1a] \frac{\partial J}{\partial a} = \frac{\partial -[yloga + (1-y)log(1-a)]}{\partial a} = -[\frac{y}{a} - \frac{1-y}{1-a}]

az=11+ezz=11+ezez1+ez=a(1a)zw1=(w1x1+w2x2+b)w1=x1zw2=(w1x1+w2x2+b)w2=x2zb=(w1x1+w2x2+b)b=1 \frac{\partial a}{\partial z} = \frac{\partial \frac{1}{1+e^{-z}}}{\partial z} = \frac{1}{1+e^{-z}} * \frac{e^{-z}}{1+e^{-z}} = a * (1 - a) \\\frac{\partial z}{\partial w_1} = \frac{\partial (w_1x_1+w_2x_2+b)}{\partial w_1} = x_1 \\\frac{\partial z}{\partial w_2} = \frac{\partial (w_1x_1+w_2x_2+b)}{\partial w_2} = x_2 \\\frac{\partial z}{\partial b} = \frac{\partial (w_1x_1+w_2x_2+b)}{\partial b} = 1

在反向傳播過程中根據鏈式法則,我們可以知道
Jw1=Jaazzw1=[ya1y1a]a(1a)x1=(ay)x1 \frac{\partial J}{\partial w_1} = \frac{\partial J}{\partial a} * \frac{\partial a}{\partial z} * \frac{\partial z}{\partial w_1} = -[\frac{y}{a} - \frac{1-y}{1-a}] * a * (1 - a) * x_1 \\= (a-y)*x_1

Jw2=Jaazzw2=[ya1y1a]a(1a)x2=(ay)x2 \frac{\partial J}{\partial w_2} = \frac{\partial J}{\partial a} * \frac{\partial a}{\partial z} * \frac{\partial z}{\partial w_2} = -[\frac{y}{a} - \frac{1-y}{1-a}] * a * (1 - a) * x_2 \\= (a-y)*x_2

Jb=Jaazzb=[ya1y1a]a(1a)1=ay \frac{\partial J}{\partial b} = \frac{\partial J}{\partial a} * \frac{\partial a}{\partial z} * \frac{\partial z}{\partial b} = -[\frac{y}{a} - \frac{1-y}{1-a}] * a * (1 - a) * 1 \\= a-y
知道了單個樣本的反向傳播過程,接下來我們將樣本數擴展到m個,看看計算有什麼變化。

m個樣本的計算

對於m個樣本,邏輯迴歸的cost function計算過程如下:
z(i)=wTx(i)+b z^{(i)} = w^Tx^{(i)} + b

y^(i)=a(i)=σ(z(i)) \hat y^{(i)} = a^{(i)} = \sigma(z^{(i)})

J(w,b)=1mi=1mL(y^,y)=1mi=1m[y(i)logy^(i)+(1y(i))log(1y^(i))] J(w, b) = \frac1{m}\sum_{i=1}^m L(\hat y, y) = -\frac1{m}\sum_{i=1}^m[y^{(i)}log\hat y^{(i)} + (1-y^{(i)})log(1-\hat y^{(i)})]

對應的偏導數爲:

Jw1=1mi=1m(a(i)y(i))x1(i)\frac{\partial J}{\partial w_1} = \frac1{m}*\sum_{i=1}^m(a^{(i)}-y^{(i)})*x_1^{(i)}

Jw2=1mi=1m(a(i)y(i))x2(i)\frac{\partial J}{\partial w_2} = \frac1{m}*\sum_{i=1}^m(a^{(i)}-y^{(i)})*x_2^{(i)}

Jb=1mi=1m(a(i)y(i))\frac{\partial J}{\partial b} = \frac1{m}*\sum_{i=1}^m(a^{(i)}-y^{(i)})

其實就是將m個樣本的偏導數求和,然後取平均。

使用僞代碼描述這個過程如下:

J=0; dw1=0; dw2=0; db=0
for i = 1 to m:
    # 前向傳播計算損失函數
    z(i) = w * x(i) + b
    a(i) = sigmoid(z(i))
    J += -[y(i)loga(i) + (1-y(i))log(1-a(i))]
    # 反向傳播計算導數
    dz(i) = a(i) - y(i)
    dw1 += dz(i)*x1(i) # x1(i):第i個樣本的第一個特徵
    dw2 += dz(i)*x2(i)
    db += dz(1)
# 遍歷完m個樣本,計算梯度均值
J /= m
dw1 /= m
dw2 /= m
db /= m

梯度計算完成後,對參數進行一次更新:

w1 -= alpha * dw1
w2 -= alpha * dw2
b -= alpha * db

這個過程是對樣本集的一次遍歷,梯度下降算法可以規定遍歷的次數,遍歷n次後整個梯度下降過程就完成了。

優化

整個計算過程中,使用的是顯示的for循環,我們可以使用矩陣運算來對整個計算過程進行優化。

Z計算: z=wTx+bz = w^Tx+b

對於單個樣本,z=wTx+bz = w^Tx + b; 其中, wRnxxRnx,bRw \in R^{n_x},x \in R^{n_x}, b \in R

for-loop形式

z = 0
for i in range(n_x):
    z += w[i]*x[i]
z += b

向量形式

import numpy as np
z = np.dot(w.T, x) + b

對於m個樣本,z的計算結果爲一個向量。$X \in R^{n_x * m},w \in R^{n_x} $

for-loop 方法

z = np.zeros((1, m))
for i in range(m):
    for j in range(n_x):
        z[i] += w[j]*X[j][i]

向量形式

z = np.dot(w.T, X)

使用矩陣運算後的LR計算過程如下:

# w: [n_x, 1]; x: [n_x, m], b: float
Z = np.dot(w.T, X) + b # [1, m]
A = sigmoid(Z)
# 反向傳播計算梯度dw, db
dZ = A -Y
dw = 1./m * X * dZ.T
db = 1./m * np.sum(dZ)
# 參數更新
w -= learning_rate * dw
b -= learning_rate * db

使用矩陣運算,減少了對樣本的for訓練遍歷以及對梯度計算過程中對參數的遍歷。

Whenever possible, avoid explicit for-loops.

值得注意的是,這裏關於非參數的矩陣表示,如訓練樣本矩陣X,標籤矩陣Y都是以列的方式進行堆疊而成的。矩陣運算將for循環集中在一次計算過程中完成。

淺層神經網絡(2層)

從某種角度上說,邏輯迴歸LR也可以看作一種神經網絡,示意圖如下。

中間的神經元完成兩種運算,分別爲z和a。

淺層神經網絡示意圖如下,其中每個“圓圈”的運算類似於LR,區別在於第二步a的計算中使用的激活函數不同。LR激活函數爲sigmoid,這裏可以爲relu、tanh、sigmoid等等。

這個神經網絡有輸入層、隱藏層和輸出層三層組成,但是一般情況下輸入層忽略不計,所以這個神經網絡有2層組成。

前向傳播

我們這裏設定wi[l]w_i^{[l]}表示神經網絡第l層的第i個神經元的權重參數。對於單個樣本而言,這個淺層神經網絡的計算過程如下:

在隱藏層:

z1[1]=w1[1]Tx+b1[1], a1[1]=σ(z1[1]);z_1^{[1]} = w_1^{[1]T}*x + b_1^{[1]},\ a_1^{[1]} = \sigma(z_1^{[1]});

z2[1]=w2[1]Tx+b2[1], a2[1]=σ(z2[1]);z_2^{[1]} = w_2^{[1]T}*x + b_2^{[1]},\ a_2^{[1]} = \sigma(z_2^{[1]});

z3[1]=w3[1]Tx+b3[1], a3[1]=σ(z3[1]);z_3^{[1]} = w_3^{[1]T}*x + b_3^{[1]},\ a_3^{[1]} = \sigma(z_3^{[1]});

z4[1]=w4[1]Tx+b4[1], a4[1]=σ(z4[1]);z_4^{[1]} = w_4^{[1]T}*x + b_4^{[1]},\ a_4^{[1]} = \sigma(z_4^{[1]});

輸出結果得到一個[4, 1]向量:[a1[1];a2[1];a3[1];a4[1]a_1^{[1]};a_2^{[1]};a_3^{[1]};a_4^{[1]}]. 我們使用a[1]a^{[1]}表示這個結果,同時作爲輸出層的輸入繼續計算。

輸出層計算結果:

z1[2]=w1[2]Ta[1]+b1[2],y^=a[2]=σ(z[2])z_1^{[2]} = w_1^{[2]T}*a^{[1]} + b_1^{[2]}, \hat y=a^{[2]} = \sigma(z^{[2]})

使用矩陣表示整個計算過程如下,隱藏層的參數用W[1]W^{[1]}表示,由隱藏層各個神經元對應權重參數以行的方式堆疊而成,這裏形狀爲[4, 3] (權重參數的第一維度爲本層神經元的數目,另一個維度爲上一層網絡的神經元數目)

單個樣本的矩陣表示計算過程如下:

z[1]=W[1]x+b[1]z^{[1]} = W^{[1]}x + b^{[1]}

a[1]=σ(z[1])a^{[1]} = \sigma(z^{[1]})

z[2]=W[2]a[1]+b[2]z^{[2]} = W^{[2]}a^{[1]} + b^{[2]}

a[2]=σ(z[2])a^{[2]}=\sigma(z^{[2]})

如果將樣本數擴展到m個,使用for循環的計算過程爲:

for i = 1 to m:
    z[1](i) = W[1]x(i) + b[1]
	a[1](i) = sigma(z[1](i))
	z[2](i) = W[2]a[1](i) + b[2]
	a[2](i) = sigma(z[2](i))

如果使用矩陣運算,我們設定m個訓練樣本以列的方式進行堆疊,用X表示,形狀爲[3, m]。使用矩陣運算過程如下,

Z[1] = W[1]X + b[1]
A[1] = sigma(Z[1])
Z[2] = W[2]A[1] + b[2]
A[2] = sigma(Z[2])

示意圖如下:

反向傳播

反向傳播主要用於計算梯度dw1, dw2, dw3, db.爲了方便理解,我們先用for循環進行介紹,之後再使用矩陣進行計算優化。

單個樣本

計算過程類似於邏輯迴歸的反向傳播過程。

dz[2]=a[2]ydz^{[2]} = a^{[2]} - y

dW[2]=dz[2]dz[2]W[2]=dz[2]a[1]TdW^{[2]} = dz^{[2]} * \frac{\partial dz^{[2]}}{\partial W^{[2]}} = dz^{[2]} * a^{[1]T}

$db^{[2]} = dz^{[2]} * \frac{\partial dz^{[2]}}{\partial b^{[2]}} = dz^{[2]} $

dz[1]=dz[2]dz[2]a[1]a[1]z[1]=W[2]Tdz[2]g[1](z[1])dz^{[1]} = dz^{[2]} * \frac{\partial dz^{[2]}}{\partial a^{[1]}} * \frac{\partial a^{[1]}}{\partial z^{[1]}} = W^{[2]T}*dz^{[2]} * g^{[1]^{'}}(z^{[1]})

dW[1]=dz[1]dz[1]W[1]=dz[1]xTdW^{[1]} = dz^{[1]} * \frac{\partial dz^{[1]}}{\partial W^{[1]}} = dz^{[1]} * x^T

db[1]=dz[1]dz[1]b[1]=dz[1]1=dz[1]db^{[1]} = dz^{[1]} * \frac{\partial dz^{[1]}}{\partial b^{[1]}} = dz^{[1]} * 1 = dz^{[1]}

對應的向量形式爲(將m個樣本堆疊在一起,一同計算):

深層神經網絡

深層神經網絡是指包括多個隱藏的神經網絡模型。如

深層神經網絡計算過程類似於淺層神經網絡,分爲前向傳播計算loss,反向傳播計算梯度,然後更新權重;反覆更新直到模型收斂。

模型的前向傳播郭恆比較簡單,我們接下來主要介紹模型的反向傳播。以神經網絡的某一層爲例:


Input: da[l]da^{[l]}

Output: da[l1],dW[l],db[l]da^{[l-1]}, dW^{[l]}, db^{[l]}


我們知道前向傳播過程中:

z[l]=W[l]a[l1]+b[l]z^{[l]} = W^{[l]}*a^{[l-1]} + b^{[l]}

a[l]=g(z[l])a^{[l]} = g(z^{[l]})

那麼,

dz[l]=da[l]g[l](z[l])dz^{[l]} = da^{[l]} * g^{[l]'}(z^{[l]})

da[l1]=W[l]Tdz[l]da^{[l-1]} = W^{[l]T} * dz^{[l]}

dW[l1]=dz[l]a[l1]dW^{[l-1]} = dz^{[l]} * a^{[l-1]}

db[l1]=dz[l]db^{[l-1]} = dz^{[l]}

得到da[l1]da^{[l-1]}之後,我們可以繼續往前傳播。


爲了方便運算,我們可以在前向傳播過程中保存計算結果g(z[l])g(z^{[l]})

深度神經網絡的計算圖可以描述如下。

神經網絡的前向傳播和反向傳播計算過程可以總結如下:

總結

本文自下而上的對神經網絡進行了介紹。首先,從邏輯迴歸開始介紹其計算過程、反向傳播、更新方法,在介紹過程中先以單個樣本的計算開始,然後擴展到m個樣本,之後爲了提高計算速度,採用向量化方法進行計算;我們瞭解了邏輯迴歸之後,介紹淺層神經網絡。淺層神經網絡是一個2層神經網絡,每層神經網絡的神經元可以看做是一個“邏輯迴歸”計算單元,區別在於使用的激活函數不同。淺層神經網絡的介紹也是先從單個樣本開始,通過單個樣本明白其計算過程,然後擴展到m個樣本,最終使用向量化方式完成計算。最後,介紹深層神經網絡,深層神經網絡只是增加了隱藏層的數目,其計算過程和淺層神經網絡十分相似。


歡迎關注我的公衆號,一同學習成長。
公衆號


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章