National Central University
Uedu Main Site
Explore Uedu
Student Console
Register as Member/Login
Research Informed Consent Center
Survey Center
Educational Big Data Challenge
Claim or create a course
Try an AI Scenario Task
Support & Messages
Uptime Data

UeduGPTs

--

Jupyters

3

Local AI

--

Uedu Code

--

中央大學 AQI 80 24°C PM2.5 21
AI Reply Desktop Notifications

Show a desktop notification when the AI TA finishes replying

Chat Message Notifications

Notify me when classmates post messages in the forum

Sound notification

Play an alert sound whenever there is a new notification

Unit 22

反向傳播

用 numpy 寫:連鎖律與梯度檢查
Interaction實作 30 minute(s)

Learning Objectives

  • 用連鎖律算出單一權重的梯度,並用數值微分驗證
  • 用 numpy 寫出 2-2-1 網路的反向傳播
  • 用梯度檢查找出反向傳播程式裡的錯誤
  • 說明反向傳播為什麼比逐一做數值微分省時間

每個權重該往哪裡調

上一課的權重都是亂數,輸出沒有意義。要訓練,就要知道:每個權重動一點點,損失會變大還是變小?這個斜率叫梯度(gradient),知道之後就可以用第 4 課的梯度下降,往損失變小的方向走。

最直接的做法是數值微分:把一個權重真的加一點點,重算一次損失,看變多少。但每個參數都要做兩次前向傳播;只要網路有幾千個參數,更新一步就要跑幾千次。

反向傳播(backpropagation)只要一次前向、一次反向,就能得到全部參數的梯度。Rumelhart、Hinton 與 Williams 在 1986 年發表於 Nature 的論文說明了這個方法,並示範隱藏層可以藉此學到有用的特徵。

它的數學只有一條:連鎖律(chain rule)。計算一路串下來時,整體的斜率等於每一段斜率相乘:

∂L/∂w = ∂L/∂p × ∂p/∂z × ∂z/∂w

如果 w 動一點點會讓 z 變 2 倍那麼多,z 動一點點會讓 p 變 0.2 倍,那 w 對 p 的影響就是 2 × 0.2。

逐步看:只有一個權重的連鎖律

先看最小的情況:一個輸入、一個權重、一個輸出,正確答案是 1,所以損失是 -log(p)。先由左到右算出每一段,再由右到左算斜率、相乘,最後用數值微分驗證。

多層時由右往左傳

多層網路的權重很多,但連鎖律的前面幾段是共用的。把共用的部分算好存起來,傳給左邊,就不必重算。這個共用的值這裡叫 delta:損失對某個節點的 z 的斜率。

以 tanh 隱藏層、sigmoid 輸出層、交叉熵損失為例:

算什麼 公式 說明
輸出節點的 delta delta2 = p − y sigmoid 配交叉熵時,斜率相乘後剛好這麼簡單
接到輸出的權重 delta2 × 隱藏層的值 這條線送進來多少,權重的影響就有多大
隱藏節點的 delta (W2 × delta2) × (1 − h²) 右邊的 delta × 這條權重 × tanh 的斜率
接到隱藏層的權重 delta1 × 輸入 一樣是 delta × 送進來的值

每個權重的梯度都是「這個節點的 delta × 這條線送進來的值」,偏差項的梯度就是 delta 本身(它送進來的值可以當成 1)。

逐步看:2-2-1 網路的前向與反向

權重是寫死的,方便和下面的小工具對照。注意前向傳播留下的 h 和 p,反向傳播時都會再用到。

互動練習:每個節點的值與每條權重的梯度

和上面的範例同一組權重。按「下一步」一個節點一個節點看;節點裡的數字是前向傳播算的,橘色的是反向傳播算的。表格可以對任何一個參數按「算」,做數值微分。

梯度檢查:抓反向傳播的錯

反向傳播的程式寫錯時,不會報錯,只是訓練不起來,很難查。梯度檢查(gradient checking)就是拿慢但可靠的數值微分,對照反向傳播的結果:

數值微分 ≈ (L(w + h) − L(w − h)) / (2h)

兩邊差距應該非常小;差很多,就是反向傳播寫錯了。數值微分太慢,不拿來訓練,只拿來驗證:通常在幾個參數、幾筆資料上檢查一次就好。下面故意漏掉 tanh 的斜率,看檢查抓不抓得到。

逐步看:梯度檢查抓到漏掉的斜率

四筆 XOR 資料,損失是四筆的平均。numeric 對 W1 的每一格做數值微分;backprop 分成正確與 bug=True(故意漏掉 tanh 的斜率)。

逐步看:用反向傳播訓練 XOR

把前面的計算放進迴圈:前向、算損失、反向、更新。這裡挑了一個 12 輪內學得起來的種子與較大的學習率,這樣才看得完每一步;一般訓練要跑幾百幾千輪,換一個種子也可能卡住。

實作:補上反向傳播

完成 backprop:回傳 W1、b1、W2、b2 的梯度(四筆資料的平均)。程式最後會用數值微分檢查,正確時最後一行印出「通過」。

提示:d2 是 (4, 1),W2.T 是 (1, 2);h 是 (4, 2)。

你的輸出
預期輸出

小測驗:反向傳播

1.

計算一路串成 w → z → p → L。∂z/∂w 是 3,∂p/∂z 是 0.2,∂L/∂p 是 −2,∂L/∂w 是多少?

2.

下面程式會印出什麼?

import numpy as np
x = np.array([0.0, 2.0])
delta = np.array([0.5])
print(np.outer(x, delta).ravel().tolist())
3.

網路有 1000 個參數。一次反向傳播和逐一做中央差分,分別要跑幾次前向傳播?

4.

梯度檢查時,數值微分和反向傳播的差距和梯度本身差不多大。最合理的判斷是?

5.

為什麼不把數值微分直接拿來訓練?

第 1 次作答

重點整理

  • 梯度告訴你每個權重動一點點時損失怎麼變;連鎖律說整體斜率等於每一段斜率相乘。
  • 反向傳播:先前向算出每個節點的值,再從輸出往左傳 delta。每個權重的梯度=這個節點的 delta × 這條線送進來的值,偏差項的梯度=delta。
  • 一次前向加一次反向就得到全部梯度;數值微分每個參數要跑兩次前向,太慢,只用來梯度檢查。
  • 反向傳播寫錯不會報錯,只是學不起來,所以先做梯度檢查。
  • 權重要用亂數初始化,全部相同時同一層的神經元永遠學成一樣。
  • 這一課每一輪都用全部資料更新一次。下一課看實際訓練要調的東西:批次、學習率、過擬合,以及怎麼用 MLPClassifier 和 PyTorch 寫。
這一課完成了!
Next lesson:訓練神經網路
你目前沒有登入,學習進度只存在這個瀏覽器。 Login 後,進度會跟著帳號,換電腦也看得到。