神經網路基礎知識
二分類任務(Binary Classification)
-
在二分類問題中,目標是將輸入(如圖片、文字或其他資料)分為兩類之一,通常使用標籤0和1來表示不同的類別。以影像識別為例,假設我們需要判斷一張圖片中是否包含貓。我們可以將包含貓的圖片標記為標籤1,不包含貓的圖片標記為標籤0。模型的任務是學習圖片的特徵,以便根據這些特徵準確地預測圖片的類別,即是“貓”還是“非貓”。二分類模型經過訓練後,可以對未見過的圖片進行推斷,輸出0或1來表示是否檢測到貓。
-
在視覺任務中,影像通常表示為矩陣,其中每個畫素點包含顏色資訊。如果圖片大小為 \(64 \times 64\) 畫素,並且是 RGB 彩色影像,那麼這張圖片可以表示為三個 \(64 \times 64\) 的矩陣,分別對應紅、綠、藍三個通道中每個畫素的強度值。為了將這張圖片轉換為一個特徵向量,可以將這三個矩陣中的所有畫素值按順序展開為一個列向量,即將所有紅、綠、藍通道的畫素強度值依次排成一個長向量。這樣得到的特徵向量維度為 \([1, 64 \times 64 \times 3]\) ,也就是 \([1, 12288]\) ,可以記作 \(n_x = 12288\) 。在二分類問題中,目標是透過學習一個分類器,將特徵向量作為輸入,從而預測輸出 \(y\) 的類別,即圖片是否為“貓”( \(y=1\) )或“非貓”( \(y=0\) )。
-
符號定義
\(n_x\):表示每個樣本的特徵數
\(x\):表示一個 \(n_x\)維的輸入特徵向量,維度為 \((n_x,1)\)
\(y\):表示輸出結果,在二分類問題中取值為 \((0,1)\)
\(m\):表示訓練樣本總數
\(M_{train}\):表示訓練集樣本總數
\(M_{test}\):表示測試集樣本總數
\((x,y)\):表示一個單獨的樣本,包含輸入與輸出
\((x^{(i)},y^{(i)})\):表示第 \(i\) 組訓練樣本,包含輸入與輸出
\(X=[x^{(1)},x^{(2)},...,x^{(m)}]\):表示訓練集所有樣本的輸入,維度為 \((n_x,m)\),每個樣本自成一列
\(Y=[y^{(1)},y^{(2)},...,y^{(n)}]\):表示訓練集所有樣本的輸出,維度為 \((1,m)\),每個樣本自成一列
邏輯迴歸(Logistic Regression)
-
在二分類任務中,目標是訓練一個分類器,使其能夠輸出預測值 \(\hat{y}\),其中 \(\hat{y}\)表示 \(y=1\) 的機率,即 \(\hat{y}=P(y=1|x)\)。在邏輯迴歸模型中,有一個權重向量 \(\omega\) 和一個偏置引數 \(b\)。這裡,\(\omega\) 是一個與輸入特徵向量 \(x\) 維度相同的列向量,大小為 \((n_x,1)\),用於表示特徵的權重。偏置引數 \(b\) 則是一個標量(實數),表示模型的偏移量。
-
在邏輯迴歸中,我們透過計算特徵向量 \(x\) 和權重向量 \(\omega\) 的內積並加上偏置 \(b\),然後將結果傳入 Sigmoid 函式,以得到預測值 \(\hat{y}\)。該假設函式(Hypothesis Function)定義如下:
\[z=\omega^Tx+b \\ \hat{y}=\sigma(z)=\frac{1}{1+e^{-z}} \]其中, \(\sigma(z)\) 是 Sigmoid 函式,它將 \(z\) 的值域對映到 \([0,1]\) 的範圍,從而使 \(\hat{y}\) 表示預測為類別 \(y=1\) 的機率。邏輯迴歸模型的目標是透過訓練學習引數 \(\omega\) 和 \(b\),使得 \(\hat{y}\) 能夠很好地估計 \(y=1\) 的機率。
在實際訓練過程中,透過最小化損失函式,邏輯迴歸不斷調整引數 \(\omega\) 和 \(b\),以最大化模型在訓練資料上的預測準確性。
-
在機器學習中,損失函式 \(L(\hat{y},y)\) 用於衡量模型預測值與實際值之間的差距。通常情況下,我們可能會使用預測值與實際值的平方差作為損失函式,但在邏輯迴歸中,使用平方差損失會導致最佳化目標不是凸函式,因此可能會出現多個區域性最優值,從而難以找到全域性最優解。為了解決這一問題,邏輯迴歸採用了交叉熵損失函式,定義如下:
\[L(\hat{y},y)=-y\text{log}(\hat{y})-(1-y)\text{log}(1-\hat{y}) \]該損失函式有如下性質:
- 當 \(y=1\)時,損失函式變為 \(L=-log(\hat{y})\)。在這種情況下,為了使損失函式儘可能小, \(\hat{y}\) 需要儘可能大。而由於 Sigmoid 函式的輸出範圍是 \([0,1]\), \(\hat{y}\) 會盡可能接近於 1。
- 當 \(y=0\)時,損失函式變為 \(L=-log(1-\hat{y})\)。在這種情況下,為了使損失函式儘可能小, \(\hat{y}\) 需要儘可能小。同樣由於 Sigmoid 函式的限制, \(\hat{y}\) 會盡可能接近於0。
交叉熵損失在邏輯迴歸中有重要作用,因為它是一個凸函式,這意味著損失函式在引數空間中有唯一的全域性最優解,因此可以透過梯度下降等最佳化方法有效地找到最佳引數 \(\omega\) 和 \(b\),從而提高模型的預測效能。
-
在邏輯迴歸中,損失函式 \(L(\hat{y},y)\) 定義在單個訓練樣本上,用於衡量模型在該樣本上的預測誤差,反映了模型對該樣本預測的準確性。然而,為了衡量模型在整個訓練集上的表現,我們定義代價函式 \(J(\omega,b)\),它是所有訓練樣本的平均損失。代價函式的定義如下:
\[J(\omega,b)=\frac{1}{m}\sum_{i=1}^{m}L(\hat{y}^{(i)},y^{(i)}) \]其中, \(m\) 是訓練樣本的總數,\(L(\hat{y},y)\) 表示第 \(i\) 個樣本的損失。
損失函式和代價函式之間的區別在於,損失函式只適用於單個訓練樣本,而代價函式是所有樣本損失的平均值,衡量模型在整個訓練集上的總體表現。訓練邏輯迴歸模型的目標是找到合適的引數 \(\omega\) 和 \(b\),使得代價函式 \(J(\omega,b)\) 達到最小值,從而讓模型的整體預測誤差降到最低。
-
在邏輯迴歸模型中,我們的目標是預測二分類變數 \(y \in \{0, 1\}\) 的機率。預測結果可以表示為:
\[\hat{y} = \sigma(\omega^T x + b) \]因此,模型輸出 \(\hat{y}\) 表示 \(y = 1\) 的機率, \(1 - \hat{y}\) 表示 \(y = 0\) 的機率。可以用如下條件機率表示式描述模型預測:
\[p(y | x) = \begin{cases} \hat{y}, & \text{if } y = 1 \\ 1 - \hat{y}, & \text{if } y = 0 \end{cases} \]上述公式可以進一步合併為一個統一的表示式:
\[p(y|x)={\hat{y}}^{y}{(1-\hat{y})}^{(1-y)} \]此公式可以解釋為:當 \(y = 1\) 時, \(p(y | x) = \hat{y}\) ;當 \(y = 0\) 時, \(p(y | x) = 1 - \hat{y}\) 。
為了訓練模型,我們希望最大化所有樣本的聯合機率,即對數似然函式。因為對數函式是單調遞增的,最大化 \(p(y | x)\) 等價於最大化其對數:
\[log(p(y|x))=y\text{log}(\hat{y})+(1-y)\text{log}(1-\hat{y}) \]這樣,我們就得到了邏輯迴歸的對數似然函式。
在邏輯迴歸中,我們透過最小化負對數似然損失(即交叉熵損失)來訓練模型。負對數似然損失函式 \(L(\hat{y}, y)\) 可以定義為:
\[L(\hat{y},y)=-\text{log}(p(y|x)) \]代入合併的機率公式後,可以得到具體的損失函式形式:
\[L(\hat{y}, y) = -\left( y \log(\hat{y}) + (1 - y) \log(1 - \hat{y}) \right) \] -
在邏輯迴歸中,我們的目標是找到一組模型引數 \(\omega\) 和 \(b\) ,使得給定訓練樣本的觀測結果機率最大。由於假設所有訓練樣本是獨立同分布的,因此所有樣本的聯合機率可以表示為每個樣本條件機率的乘積。
假設訓練集中共有 \(m\) 個樣本 \((x^{(i)}, y^{(i)})\),每個樣本的觀測標籤條件機率為 \(P(y^{(i)} | x^{(i)})\)。對於所有樣本,聯合機率可以表示為:
\[P(\text{labels in training set}) = \prod_{i =1}^{m}{P(y^{(i)}|x^{(i)})} \]最大似然估計的目標是找到一組引數 \(\omega\) 和 \(b\) ,使得這個聯合機率最大。
為了簡化計算,我們通常取聯合機率的對數,因為對數函式是單調遞增的,因此最大化聯合機率與最大化其對數是等價的。將聯合機率的對數表示為:
\[\log P(\text{labels in training set}) = \log \prod_{i=1}^{m} P(y^{(i)} | x^{(i)}) \]根據對數乘法法則,轉化為求和形式:
\[\log P(\text{labels in training set}) = \sum_{i=1}^{m} \log P(y^{(i)} | x^{(i)}) \]我們已知每個樣本的機率可以寫成:
\[P(y^{(i)} | x^{(i)}) = \hat{y}^{(i) y^{(i)}} (1 - \hat{y}^{(i)})^{(1 - y^{(i)})} \]於是,對數似然函式就可以表示為:
\[\log P(\text{labels in training set}) = \sum_{i=1}^{m} ( y^{(i)} \log(\hat{y}^{(i)}) + (1 - y^{(i)}) \log(1 - \hat{y}^{(i)}) ) \]在邏輯迴歸中,我們通常希望最小化一個損失函式而不是直接最大化似然。因此,定義損失函式為對數似然的負值(因為最大化對數似然等價於最小化負對數似然):
\[\text{負對數似然} = -\sum_{i=1}^{m} ( y^{(i)} \log(\hat{y}^{(i)}) + (1 - y^{(i)}) \log(1 - \hat{y}^{(i)}) ) \]進一步定義平均損失函式,這樣可以在樣本量 \(m\) 變化時保證損失函式的穩定性。我們在前面加上一個因子 \(\frac{1}{m}\):
\[J(\omega, b) = \frac{1}{m} \sum_{i=1}^{m} L(\hat{y}^{(i)}, y^{(i)}) \]其中,單個樣本的損失函式(即交叉熵損失)為:
\[L(\hat{y}^{(i)}, y^{(i)}) = -( y^{(i)} \log(\hat{y}^{(i)}) + (1 - y^{(i)}) \log(1 - \hat{y}^{(i)}) ) \]這樣一來,我們得到了邏輯迴歸的代價函式。模型訓練的目標是透過最佳化演算法(如梯度下降)最小化這個代價函式 ,使得模型對所有訓練樣本的預測誤差儘量小。
最終,邏輯迴歸的代價函式形式為:
\[J(\omega, b) = -\frac{1}{m} \sum_{i=1}^{m} ( y^{(i)} \log(\hat{y}^{(i)}) + (1 - y^{(i)}) \log(1 - \hat{y}^{(i)}) ) \]其中, \(\hat{y}^{(i)} = \sigma(\omega^T x^{(i)} + b)\) 是第 \(i\) 個樣本的預測機率。這個函式度量了模型在所有訓練樣本上的預測誤差。
梯度下降(Gradient Descent)
-
在測試集上尋找最佳引數 \(\omega\) 和 \(b\),目標是最小化代價函式 \(J(\omega,b)\)。由於代價函式 \(J(\omega,b)\) 是凸函式,因此可以使用梯度下降演算法來找到其全域性最小值。
梯度下降的過程如下:
-
隨機初始化:首先,隨機初始化引數 \(\omega\) 和 \(b\)。由於凸函式只有一個全域性最小值,所以無論初始位置如何,梯度下降都可以收斂到全域性最優解或其附近。
-
計算梯度:在每次迭代中,計算代價函式 \(J(\omega,b)\) 對引數 \(\omega\) 和 \(b\) 的偏導數,即梯度。梯度指示了代價函式在當前引數位置上變化最快的方向。
-
更新引數:沿著代價函式下降最快的方向(即負梯度方向)更新引數。更新公式如下:
\[ \omega := \omega - \alpha \frac{\partial J(\omega, b)}{\partial \omega} \\ b := b - \alpha \frac{\partial J(\omega, b)}{\partial b} \]其中, \(\alpha\) 是學習率,決定了每一步更新的幅度。
-
迭代:重複計算梯度和更新引數的步驟,直到代價函式的值不再顯著下降,即達到收斂條件,此時 \(\omega\) 和 \(b\) 接近全域性最優解。
透過梯度下降演算法,我們可以使代價函式 收斂到其最小值,從而找到最佳引數 \(\omega\) 和 \(b\),使得模型在測試集上表現良好。
-
-
在處理複雜的計算表示式時,計算圖是一種有效的工具,它將函式分解為一系列簡單的操作,從而簡化求導過程。計算圖的前向計算用於得到代價函式的值,而反向傳播用於根據鏈式法則計算每個變數的梯度,便於最佳化模型引數。
以以下計算過程為例:
\[J=3(a+bc) \]我們可以將其分解為多個簡單的計算步驟:
- 定義中間變數:
\[u = bc ,\; v = a + u, \; J = 3v \]-
前向計算:按照計算圖,從輸入開始一步步計算出代價函式 \(J\) 的值。
-
反向傳播與鏈式法則:透過鏈式法則,從輸出向輸入逐步求導,以計算出 \(J\) 對每個中間變數的偏導數。鏈式法則如下:
\[\frac{dJ}{du}=\frac{dJ}{dv}\frac{dv}{du} \]在計算圖中,通常用符號
dvar
表示最終輸出 \(J\) 對某個中間變數var
的偏導數結果,例如 \(da\) 表示 \(\frac{dJ}{da}\)。這種分步驟的計算圖方法使複雜函式的導數計算更為系統化和簡潔,尤其適用於反向傳播演算法。 -
在單樣本邏輯迴歸中,目標是透過梯度下降法來最小化損失函式,以更新模型引數 \(\omega\) 和 \(b\)。以下是整個梯度下降過程的詳細步驟:
前向計算
-
線性組合:計算輸入特徵的加權和,加上偏置項 \(b\)。
\[z = \omega^T x + b =\omega_1 x_1 + \omega_2x_2 + b \] -
啟用函式:將 \(z\) 輸入到 Sigmoid 函式中,得到模型的預測輸出 \(\hat{y}\)(即 \(a\)),表示預測為正類的機率。
\[\hat{y} = a = \sigma(z) = \frac{1}{1+e^{-x}} \] -
損失函式:使用交叉熵損失函式計算預測值 \(a\) 和真實標籤 \(y\) 之間的誤差。
\[L(a,y) = -y\text{log}(a) - (1-y)\text{log}(1-a) \]- 計算圖流向:前向計算的流向依次為
\[\omega,x \rightarrow z \rightarrow a \rightarrow L(a,y) \]反向傳播
在反向傳播中,透過鏈式法則依次計算損失 \(L\)對每個引數的梯度。
-
損失函式的導數:計算損失 \(L\) 對輸出 \(a\) 的偏導數。
\[da = \frac{dL(a,y)}{da}= -\frac{y}{a} + \frac{1-y}{1-a} \] -
Sigmoid 導數:計算 \(a\) 對 \(z\) 的導數。
\[ \frac{da}{dz} = \frac{e^{-x}}{(1+e^{-x})^2}=a^2 \times (\frac{1}{a}-1)=a-a^2 \] -
鏈式法則:將上述兩步結合,得到損失函式 \(L\) 對 \(z\) 的導數。
\[dz = \frac{dL(a,y)}{dz} = \frac{dL(a,y)}{da} \times \frac{da}{dz} = a-y \] -
引數梯度計算:根據鏈式法則計算 \(L\) 對 \(\omega_1\)、 \(\omega_2\) 和 \(b\) 的偏導數。
\[\frac{dz}{d\omega_1} = x_1,\; \frac{dz}{d\omega_x} = x_x,\; \frac{dz}{db} = 1 \\ d\omega_1=\frac{dL(a,y)}{d\omega1} = \frac{dL(a,y)}{dz} \times \frac{dz}{d\omega_1} = x_1(a-y) \\ d\omega_2=\frac{dL(a,y)}{d\omega2} = \frac{dL(a,y)}{dz} \times \frac{dz}{d\omega_2} = x_2(a-y) \\ db=\frac{dL(a,y)}{db} = \frac{dL(a,y)}{dz} \times \frac{dz}{db} = a-y \]引數更新
利用學習率 \(\alpha\) 更新引數 \(\omega_1\)、 \(\omega_2\) 和 \(b\):
\[\omega_1=\omega_1-\alpha d\omega_1 = \omega_1 -\alpha \cdot x_1(a-y) \\ \omega_2=\omega_2-\alpha d\omega_2 = \omega_2 -\alpha \cdot x_2(a-y) \\ b=b-\alpha db = b-\alpha \cdot (a-y) \]透過不斷迭代上述步驟,梯度下降會逐步調整引數,使得代價函式 \(J(\omega, b)\) 收斂到最小值,從而提高模型的預測準確性。
-
-
在多樣本邏輯迴歸中,為了最小化損失函式,我們使用梯度下降來更新模型引數 \(\omega\) 和 \(b\)。對於包含 \(m\) 個訓練樣本的資料集,邏輯迴歸的代價函式定義為所有樣本損失的平均值:
\[J(\omega,b)=\frac{1}{m}\sum_{i=1}^mL(a^{(i)},y^{(i)}) \]梯度下降的目的是最小化這個全域性代價函式 \(J(\omega, b)\)。因此,對於 \(\omega_1\) 的梯度,可以表示為:
\[ \frac{dJ(\omega,b)}{d\omega_1}=\frac{1}{m}\sum_{i=1}^m\frac{dL(a^{(i)},y^{(i)}}{d\omega_1}) \]這意味著全域性代價函式對 \(\omega_1\) 的導數等於每個樣本損失對 \(\omega_1\) 的導數的平均。因此,在計算全域性梯度時,可以透過對每個樣本的梯度累加,最後取平均值來求出最終的梯度,從而更新引數。
梯度計算步驟
- 初始化
\[J=0,\; d\omega_1=0,\; d\omega_2=0,\; db=0 \]- 遍歷每個樣本 \(i(i \in [1,m])\):
-
計算 \(z^{(i)}\):線性組合輸入特徵和引數:
\[z^{(i)}=\omega^Tx^{(i)}+b \] -
計算 \(a^{(i)}\):透過 Sigmoid 函式得到預測機率:
\[ a^{(i)} = \sigma(z^{(i)}) \] -
累加代價函式:
\[ J += -y^{(i)}\text{log}(a^{(i)})-(1-y^{(i)})\text{log}(1-a^{(i)}) \] -
累加梯度:
\[ d\omega_1+=x_1^{(i)}(a^{(i)}-y^{(i)}) \\ d\omega_2+=x_2^{(i)}(a^{(i)}-y^{(i)}) \\ db += a^{(i)}-y^{(i)} \]- 計算全域性平均
\[J /= m \\ d\omega_1/=m,\;d\omega_2/=m,\;db/=m \]- 引數更新
\[\omega_1:=\omega_1-\alpha d\omega_1 \\ \omega_2:=\omega_2-\alpha d\omega_2 \\ b:=b-\alpha db \]以上過程為對 \(m\) 個樣本的一次梯度下降,因此需要重複該過程多次(迭代),以便逐步逼近代價函式的最小值。
-
上述演算法存在一個主要的計算效率問題:多重for迴圈。這種顯式的 for 迴圈會使得演算法在處理大型資料集和高維特徵時非常低效。
- 第一個迴圈用於多次執行梯度下降。
- 第二個迴圈遍歷 \(m\) 個訓練樣本。
- 第三個迴圈遍歷所有特徵(在例子中為兩個特徵 \(\omega_1\)和 \(\omega_2\);若有更多特徵,則要計算從 \(\omega_1\)到 \(\omega_n\))。
向量化(vectorization)
-
向量化是一種將標量運算轉換為向量或矩陣運算的技術。對於深度學習和資料科學中的大量計算任務,向量化的使用能夠極大地提高計算效率。原因在於向量化可以讓計算直接在矩陣級別上操作,而不是透過迴圈逐一處理元素。
在邏輯迴歸中需要計算 \(z={{w}^{T}}x+b\) ,這裡的 \(\omega\) , \(x\)都是 \((n_x,1)\)維的列向量,如果用非向量化的方式計算 \({w}^{T}x\),程式碼如下
z = 0 for i in range(nx): z += w[i] * x[i] z += b
如果是向量化方法,程式碼如下
z = np.dot(w, x) + b
並且向量化方式執行速度會快很多,程式碼及其執行結果如下
import time import numpy as np # 隨機生成兩個陣列 a = np.random.rand(1000000) b = np.random.rand(1000000) # 向量化的版本 tic = time.time() c = np.dot(a, b) toc = time.time() print(c) print("Vectorized version: " + str(1000*(toc-tic)) + "ms") # 非向量化的版本 c = 0 tic = time.time() for i in range(1000000): c += a[i]*b[i] toc = time.time() print(c) print("For loop: " + str(1000*(toc-tic)) + "ms")
250325.66409073974 Vectorized version: 5.634069442749023ms 250325.66409074445 For loop: 419.6150302886963ms
使用向量化和內建函式(例如 NumPy 的
np.dot
)能夠讓 Python 程式碼在 CPU 和 GPU 上都高效執行,因為這些函式在底層已經最佳化為 SIMD 指令,充分利用並行化。相比之下,顯式的for
迴圈逐一操作每個元素,無法利用 SIMD 的效能優勢。CPU 和 GPU 均支援並行化,但方式有所不同:
- CPU 的並行化依賴 SIMD 指令(單指令多資料),適合執行多個簡單指令流。CPU 的並行化核心較少,但每個核心相對強大,因此非常適合處理任務量小但複雜的運算。
- GPU 是為了處理影像和影片渲染而設計的,具有大量核心(通常是 CPU 的數百倍),擅長在大規模資料上進行簡單的平行計算,因此在深度學習中的矩陣計算尤為高效。GPU 的大規模並行架構非常適合深度學習中的大規模矩陣運算。
-
在計算向量 \(u=Av\) 時,矩陣乘法的定義是 \(u_i=\sum_jA_{ij}v_j\),而非向量化的實現方式通常使用巢狀迴圈來遍歷矩陣的行和列:
for i in range(n): for j in range(m): u[i] = A[i][j] * v[j]
這種方式雖然直接,但巢狀迴圈的開銷較大,尤其是在矩陣規模較大時會影響效能。而向量化的實現方式可以透過
np.dot()
函式計算矩陣與向量的乘積,將迴圈交給底層的高效實現來處理,大大提高了程式碼執行速度:v = np.dot(A, v)
不難看出,向量化的實現方式消除了兩層迴圈,使得程式碼執行速度更快。這種向量化方式適用於大量的矩陣和向量操作,因此在資料處理和機器學習中被廣泛採用。
在 Numpy 中,還可以直接對向量 \(v\) 使用一些函式,操作 \(v\) 中的所有元素,避免寫顯式迴圈。例如:
u = np.exp(v)
計算\(e^x\);np.log(v)
計算 \(\text{log}(x)\);np.abs(v)
計算絕對值;np.maximum(v, 0)
計算 \(v\) 中每個元素和0比的最大值;v**2
計算 \(v\) 中每個元素的平方;1/v
計算 \(v\) 中每個元素的倒數。
這些操作都能自動應用於 \(v\) 的每一個元素,避免了顯式迴圈,使程式碼更加簡潔高效。
-
在邏輯迴歸梯度下降中,如果有多個特徵,需要分別計算每個特徵的梯度更新。傳統的非向量化方法需要為每個特徵分別計算梯度,例如:
\[ d\omega_1+=x_1^{(i)}(a^{(i)}-y^{(i)}) \\ d\omega_2+=x_2^{(i)}(a^{(i)}-y^{(i)}) \]其中 \(a^{(i)}\) 是預測值, \(y^{(i)}\) 是真實值。對於 \(n\) 個特徵,這種方法需要進行 \(n\) 次迴圈。
使用向量化方法,我們可以將這些特徵的梯度更新整合為一個向量,避免多次迴圈,透過一次計算完成所有梯度的更新:
\[d\omega=d\omega+x^{(i)}(a^{(i)}-y^{(i)}) \]這樣一來,向量化方法透過在矩陣或向量層面直接計算,實現了批次更新,提高了梯度下降的效率。這種最佳化方式不僅在邏輯迴歸中適用,在其他機器學習演算法的梯度計算中也同樣高效。
-
在邏輯迴歸的前向傳播中,我們需要對多個樣本進行預測。對於每個樣本 \(i\),計算如下:
\[z^{(i)}=\omega^Tx^{(i)}+b \\ a^{(i)} = \sigma(z^{(i)}) \]其中:
- \(x^{(i)} \in \mathbb{R}^{n_x}\) 是第 \(i\) 個樣本的輸入特徵向量。
- \(\omega \in \mathbb{R}^{n_x}\) 是模型的引數向量(權重)。
- \(b \in \mathbb{R}\) 是偏置項。
- \(a^{(i)}\) 是第 \(a^{(i)}\) 個樣本的預測輸出。
為了對 \(m\) 個樣本進行批次計算,我們可以將輸入資料和計算過程向量化。
令 \(X = [x^{(1)},x^{(2)},...,x^{(m)}] \in \mathbb{R}^{n_x \times m}\),每一列代表一個樣本的特徵向量。引數向量 \(\omega\) 保持為 \(\mathbb{R}^{n_x}\) 的列向量。
\[Z = [z^{(1)},z^{(2)}\;... \;z^{(m)}] \\ = \omega^TX+b \\ = [\omega^Tx^{(1)}+b,\omega^Tx^{(2)}+b\;... \;\omega^Tx^{(n)}+b] \]- \(\omega^T \in \mathbb{R}^{1 \times n_x}\),所以 \(\omega^T X \in \mathbb{R}^{1 \times m}\) 。
- \(b\) 是標量,透過廣播機制加到 \(Z\) 的每個元素上。
- 最終 \(Z \in \mathbb{R}^{1 \times m}\),每個元素對應一個樣本的線性組合結果。
對 \(Z\) 中的每個元素應用 Sigmoid 函式,得到預測值向量 \(A\):
Sigmoid啟用函式也可以進行向量化計算,在同一時間內可以完成一個所有 \(m\) 個訓練樣本的前向傳播向量化計算。
\[A=\sigma(Z)=[a^{(1)},a^{(2)}\;... \;a^{(m)}] \]- \(A \in \mathbb{R}^{1 \times m}\),每個元素是對應樣本的預測機率。
向量化的前向傳播過程可以用 Python 和 NumPy 實現:
import numpy as np def sigmoid(z): return 1 / (1 + np.exp(-z)) # 假設 W 是形狀為 (n_x, 1) 的列向量,X 是形狀為 (n_x, m) 的輸入矩陣 Z = np.dot(W.T, X) + b # Z 的形狀為 (1, m) A = sigmoid(Z) # A 的形狀為 (1, m)
-
在邏輯迴歸的梯度下降過程中,我們可以利用向量化計算批次訓練資料的梯度,以提高效率和簡化程式碼。在這種情況下,對於每個樣本 \(i\),模型的預測輸出 \(a^{(i)}\) 與真實標籤 \(y^{(i)}\) 的誤差可以表示為:
\[dZ=A-Y=[a^{(1)}-y^{(1)},a^{(2)}-y^{(2)}\;...\;a^{(m)}-y^{(m)}]\in \mathbb{R}^{1\times m} \]其中:
- \(A \in \mathbb{R}^{1 \times m}\) 是模型對 \(m\) 個樣本的預測結果。
- \(Y \in \mathbb{R}^{1 \times m}\) 是實際標籤的向量。
- \(dZ \in \mathbb{R}^{1 \times m}\) 表示每個樣本的誤差(損失的導數)。
偏置項 \(b\) 的梯度 \(db\) 是 \(dZ\) 的平均值,可以計算為:
\[db=\frac{1}{m}\sum_{i=1}^{m}dz^{(i)} \]在程式碼中,可以利用 Numpy 的
np.sum()
函式對 \(dZ\) 的所有元素求和,併除以 \(m\) 來計算 \(db\) 。dZ = A - Y db = np.sum(dZ) / m
權重向量 \(\omega\) 的梯度 \(d\omega\) 可以表示為:
\[d\omega = \frac{1}{m}\sum_{i=1}^mx^{(i)}dz^{(i)} \]將所有樣本的輸入資料 \(X \in \mathbb{R}^{n_x \times m}\) 和誤差 \(dZ \in \mathbb{R}^{1 \times m}\) 進行矩陣乘法,可以得到 \(d\omega\) 的向量化表示:
\[d\omega = \frac{1}{m}XdZ^T \]- \(X \in \mathbb{R}^{n_x \times m}\) 表示所有樣本的輸入資料,每列代表一個樣本的特徵向量。
- \(dZ^T \in \mathbb{R}^{m \times 1}\) 是誤差向量的轉置。
- \(X dZ^T \in \mathbb{R}^{n_x \times 1}\) 是每個特徵的梯度,表示為一個列向量。
在程式碼中,可以透過 Numpy 的矩陣乘法
np.dot()
來實現:dw = np.dot(X, dZ.T) / m
-
向量化邏輯迴歸總結
在邏輯迴歸的訓練中,我們可以利用向量化操作來簡化前向傳播和梯度計算過程。
- \(X \in \mathbb{R}^{n_x \times m}\):輸入矩陣,其中每列為一個樣本的特徵向量,總共 \(m\) 個樣本,每個樣本有 \(n_x\) 個特徵。
- \(\omega \in \mathbb{R}^{n_x}\):權重向量(列向量),用於模型的線性組合。
- \(Y \in \mathbb{R}^{1 \times m}\):實際標籤向量,其中每個元素為一個樣本的標籤。
前向傳播
\[Z = \omega^TX+b \in \mathbb{R}^{1\times m} \\ A = \sigma(Z) \in \mathbb{R}^{1\times m} \]反向傳播
\[dZ = A - Y \in \mathbb{R}^{1\times m} \\ d\omega = \frac{1}{m} XdZ^T \in \mathbb{R}^{n_x} \\ db =\frac{1}{m}\sum dZ \in \mathbb{R} \]引數更新
\[\omega = \omega - \alpha d\omega \in \mathbb{R}^{n_x} \\ b = b - \alpha db \in \mathbb{R} \]向量化後的邏輯迴歸梯度更新可以用以下程式碼實現:
import numpy as np # 前向傳播 Z = np.dot(W.T, X) + b A = sigmoid(Z) # 假設已定義 sigmoid 函式 # 反向傳播 dZ = A - Y dw = np.dot(X, dZ.T) / m db = np.sum(dZ) / m # 引數更新 W = W - alpha * dw b = b - alpha * db