神經網路基礎知識

钰见梵星發表於2024-11-08

神經網路基礎知識

二分類任務(Binary Classification)

  1. 在二分類問題中,目標是將輸入(如圖片、文字或其他資料)分為兩類之一,通常使用標籤0和1來表示不同的類別。以影像識別為例,假設我們需要判斷一張圖片中是否包含貓。我們可以將包含貓的圖片標記為標籤1,不包含貓的圖片標記為標籤0。模型的任務是學習圖片的特徵,以便根據這些特徵準確地預測圖片的類別,即是“貓”還是“非貓”。二分類模型經過訓練後,可以對未見過的圖片進行推斷,輸出0或1來表示是否檢測到貓。

  2. 在視覺任務中,影像通常表示為矩陣,其中每個畫素點包含顏色資訊。如果圖片大小為 \(64 \times 64\) 畫素,並且是 RGB 彩色影像,那麼這張圖片可以表示為三個 \(64 \times 64\) 的矩陣,分別對應紅、綠、藍三個通道中每個畫素的強度值。為了將這張圖片轉換為一個特徵向量,可以將這三個矩陣中的所有畫素值按順序展開為一個列向量,即將所有紅、綠、藍通道的畫素強度值依次排成一個長向量。這樣得到的特徵向量維度為 \([1, 64 \times 64 \times 3]\) ,也就是 \([1, 12288]\) ,可以記作 \(n_x = 12288\) 。在二分類問題中,目標是透過學習一個分類器,將特徵向量作為輸入,從而預測輸出 \(y\) 的類別,即圖片是否為“貓”( \(y=1\) )或“非貓”( \(y=0\) )。

  3. 符號定義

    \(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)

  1. 在二分類任務中,目標是訓練一個分類器,使其能夠輸出預測值 \(\hat{y}\),其中 \(\hat{y}\)表示 \(y=1\) 的機率,即 \(\hat{y}=P(y=1|x)\)。在邏輯迴歸模型中,有一個權重向量 \(\omega\) 和一個偏置引數 \(b\)。這裡,\(\omega\) 是一個與輸入特徵向量 \(x\) 維度相同的列向量,大小為 \((n_x,1)\),用於表示特徵的權重。偏置引數 \(b\) 則是一個標量(實數),表示模型的偏移量。

  2. 在邏輯迴歸中,我們透過計算特徵向量 \(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\),以最大化模型在訓練資料上的預測準確性。

  3. 在機器學習中,損失函式 \(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\),從而提高模型的預測效能。

  4. 在邏輯迴歸中,損失函式 \(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)\) 達到最小值,從而讓模型的整體預測誤差降到最低。

  5. 在邏輯迴歸模型中,我們的目標是預測二分類變數 \(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) \]

  6. 在邏輯迴歸中,我們的目標是找到一組模型引數 \(\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)

  1. 在測試集上尋找最佳引數 \(\omega\)\(b\),目標是最小化代價函式 \(J(\omega,b)\)。由於代價函式 \(J(\omega,b)\) 是凸函式,因此可以使用梯度下降演算法來找到其全域性最小值。

    梯度下降的過程如下:

    1. 隨機初始化:首先,隨機初始化引數 \(\omega\)\(b\)。由於凸函式只有一個全域性最小值,所以無論初始位置如何,梯度下降都可以收斂到全域性最優解或其附近。

    2. 計算梯度:在每次迭代中,計算代價函式 \(J(\omega,b)\) 對引數 \(\omega\)\(b\) 的偏導數,即梯度。梯度指示了代價函式在當前引數位置上變化最快的方向。

    3. 更新引數:沿著代價函式下降最快的方向(即負梯度方向)更新引數。更新公式如下:

      \[ \omega := \omega - \alpha \frac{\partial J(\omega, b)}{\partial \omega} \\ b := b - \alpha \frac{\partial J(\omega, b)}{\partial b} \]

      其中, \(\alpha\) 是學習率,決定了每一步更新的幅度。

    4. 迭代:重複計算梯度和更新引數的步驟,直到代價函式的值不再顯著下降,即達到收斂條件,此時 \(\omega\)\(b\) 接近全域性最優解。

    透過梯度下降演算法,我們可以使代價函式 收斂到其最小值,從而找到最佳引數 \(\omega\)\(b\),使得模型在測試集上表現良好。

  2. 在處理複雜的計算表示式時,計算圖是一種有效的工具,它將函式分解為一系列簡單的操作,從而簡化求導過程。計算圖的前向計算用於得到代價函式的值,而反向傳播用於根據鏈式法則計算每個變數的梯度,便於最佳化模型引數。

    以以下計算過程為例:

    \[J=3(a+bc) \]

    我們可以將其分解為多個簡單的計算步驟:

    1. 定義中間變數:

    \[u = bc ,\; v = a + u, \; J = 3v \]

    1. 前向計算:按照計算圖,從輸入開始一步步計算出代價函式 \(J\) 的值。

    2. 反向傳播與鏈式法則:透過鏈式法則,從輸出向輸入逐步求導,以計算出 \(J\) 對每個中間變數的偏導數。鏈式法則如下:

    \[\frac{dJ}{du}=\frac{dJ}{dv}\frac{dv}{du} \]

    在計算圖中,通常用符號 dvar 表示最終輸出 \(J\) 對某個中間變數 var 的偏導數結果,例如 \(da\) 表示 \(\frac{dJ}{da}\)。這種分步驟的計算圖方法使複雜函式的導數計算更為系統化和簡潔,尤其適用於反向傳播演算法。

  3. 在單樣本邏輯迴歸中,目標是透過梯度下降法來最小化損失函式,以更新模型引數 \(\omega\)\(b\)。以下是整個梯度下降過程的詳細步驟:

    前向計算

    1. 線性組合:計算輸入特徵的加權和,加上偏置項 \(b\)

      \[z = \omega^T x + b =\omega_1 x_1 + \omega_2x_2 + b \]

    2. 啟用函式:將 \(z\) 輸入到 Sigmoid 函式中,得到模型的預測輸出 \(\hat{y}\)(即 \(a\)),表示預測為正類的機率。

      \[\hat{y} = a = \sigma(z) = \frac{1}{1+e^{-x}} \]

    3. 損失函式:使用交叉熵損失函式計算預測值 \(a\) 和真實標籤 \(y\) 之間的誤差。

    \[L(a,y) = -y\text{log}(a) - (1-y)\text{log}(1-a) \]

    1. 計算圖流向:前向計算的流向依次為

    \[\omega,x \rightarrow z \rightarrow a \rightarrow L(a,y) \]

    反向傳播

    在反向傳播中,透過鏈式法則依次計算損失 \(L\)對每個引數的梯度。

    1. 損失函式的導數:計算損失 \(L\) 對輸出 \(a\) 的偏導數。

      \[da = \frac{dL(a,y)}{da}= -\frac{y}{a} + \frac{1-y}{1-a} \]

    2. Sigmoid 導數:計算 \(a\)\(z\) 的導數。

      \[ \frac{da}{dz} = \frac{e^{-x}}{(1+e^{-x})^2}=a^2 \times (\frac{1}{a}-1)=a-a^2 \]

    3. 鏈式法則:將上述兩步結合,得到損失函式 \(L\)\(z\) 的導數。

      \[dz = \frac{dL(a,y)}{dz} = \frac{dL(a,y)}{da} \times \frac{da}{dz} = a-y \]

    4. 引數梯度計算:根據鏈式法則計算 \(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)\) 收斂到最小值,從而提高模型的預測準確性。

  4. 在多樣本邏輯迴歸中,為了最小化損失函式,我們使用梯度下降來更新模型引數 \(\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\) 的導數的平均。因此,在計算全域性梯度時,可以透過對每個樣本的梯度累加,最後取平均值來求出最終的梯度,從而更新引數。

    梯度計算步驟

    1. 初始化

    \[J=0,\; d\omega_1=0,\; d\omega_2=0,\; db=0 \]

    1. 遍歷每個樣本 \(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)} \]

    1. 計算全域性平均

    \[J /= m \\ d\omega_1/=m,\;d\omega_2/=m,\;db/=m \]

    1. 引數更新

    \[\omega_1:=\omega_1-\alpha d\omega_1 \\ \omega_2:=\omega_2-\alpha d\omega_2 \\ b:=b-\alpha db \]

    以上過程為對 \(m\) 個樣本的一次梯度下降,因此需要重複該過程多次(迭代),以便逐步逼近代價函式的最小值。

  5. 上述演算法存在一個主要的計算效率問題:多重for迴圈。這種顯式的 for 迴圈會使得演算法在處理大型資料集和高維特徵時非常低效。

    • 第一個迴圈用於多次執行梯度下降。
    • 第二個迴圈遍歷 \(m\) 個訓練樣本。
    • 第三個迴圈遍歷所有特徵(在例子中為兩個特徵 \(\omega_1\)\(\omega_2\);若有更多特徵,則要計算從 \(\omega_1\)\(\omega_n\))。

向量化(vectorization)

  1. 向量化是一種將標量運算轉換為向量或矩陣運算的技術。對於深度學習和資料科學中的大量計算任務,向量化的使用能夠極大地提高計算效率。原因在於向量化可以讓計算直接在矩陣級別上操作,而不是透過迴圈逐一處理元素。

    在邏輯迴歸中需要計算 \(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 的大規模並行架構非常適合深度學習中的大規模矩陣運算。
  2. 在計算向量 \(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\) 的每一個元素,避免了顯式迴圈,使程式碼更加簡潔高效。

  3. 在邏輯迴歸梯度下降中,如果有多個特徵,需要分別計算每個特徵的梯度更新。傳統的非向量化方法需要為每個特徵分別計算梯度,例如:

    \[ 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)}) \]

    這樣一來,向量化方法透過在矩陣或向量層面直接計算,實現了批次更新,提高了梯度下降的效率。這種最佳化方式不僅在邏輯迴歸中適用,在其他機器學習演算法的梯度計算中也同樣高效。

  4. 在邏輯迴歸的前向傳播中,我們需要對多個樣本進行預測。對於每個樣本 \(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)
    
  5. 在邏輯迴歸的梯度下降過程中,我們可以利用向量化計算批次訓練資料的梯度,以提高效率和簡化程式碼。在這種情況下,對於每個樣本 \(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
    
  6. 向量化邏輯迴歸總結

    在邏輯迴歸的訓練中,我們可以利用向量化操作來簡化前向傳播和梯度計算過程。

    • \(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
    

相關文章