Appearance
從零理解神經網路(三):梯度下降——順著山坡找谷底
本文是「從零理解神經網路」系列的第三篇。前兩篇我們認識了神經元和激活函數,這篇要回答一個核心問題:神經網路是怎麼「學習」的?
學習的本質是什麼?
讓我們先思考一個問題:當我們說神經網路在「學習」時,它到底在做什麼?
答案很簡單:調整權重,讓預測更準確。
一個神經網路有成千上萬個權重(w)和偏置(b),這些參數的值決定了網路的行為。「學習」就是找到一組最佳的參數值。
但問題是:怎麼找?
損失函數:衡量「錯得有多離譜」
在找最佳參數之前,我們需要一個方法來衡量「目前的參數有多糟糕」。這就是**損失函數(Loss Function)**的作用。
最常見的損失函數是均方誤差(MSE):
Loss = (1/n) × Σ(預測值 - 真實值)²舉個例子:
| 真實值 | 預測值 | 誤差 | 誤差² |
|---|---|---|---|
| 1.0 | 0.8 | 0.2 | 0.04 |
| 0.0 | 0.3 | -0.3 | 0.09 |
| 1.0 | 0.9 | 0.1 | 0.01 |
Loss = (0.04 + 0.09 + 0.01) / 3 = 0.047
損失越小,模型越準確。我們的目標是最小化損失。
損失地形:把優化想像成爬山
現在,想像損失函數是一個「地形」:
- 橫軸和縱軸:代表兩個權重 w₁ 和 w₂
- 高度:代表損失值
這樣,損失函數就變成了一個 3D 的「山」:
損失(高度)
↑
/\
/ \
/ \
/ 谷 \
/ 底 \
/ \
────────────→ 權重訓練神經網路 = 在這個地形上找到最低點(谷底)。
但問題是:這個地形可能有數百萬個維度(每個權重一個維度),我們不可能「看到」它。我們只能感受到「腳下的斜率」。
梯度:告訴你該往哪走
**梯度(Gradient)**就是「腳下的斜率」,更準確地說,是損失對每個權重的偏導數。
梯度 = [∂L/∂w₁, ∂L/∂w₂, ∂L/∂w₃, ...]梯度有兩個重要資訊:
- 方向:指向損失增加最快的方向
- 大小:斜率有多陡
既然梯度指向「上坡」方向,那我們反方向走就是「下坡」方向!
梯度下降算法
梯度下降的核心思想就是:反覆朝著梯度的反方向走一小步。
重複以下步驟:
1. 計算當前位置的梯度
2. 朝梯度的反方向移動一小步
3. 直到到達谷底(或足夠接近)用數學表示:
w_new = w_old - η × ∂L/∂w其中 η(eta) 是學習率(Learning Rate),控制每一步走多遠。
學習率的影響
學習率是最重要的超參數之一:
學習率太大:
- 步伐太大,可能「跨過」谷底
- 損失可能震盪或發散
- 就像下山時跳太遠,反而跳到對面山上
學習率太小:
- 步伐太小,下降太慢
- 訓練時間大幅增加
- 可能卡在局部最小值
學習率剛好:
- 穩定下降,最終收斂到谷底
學習率太大: 學習率太小: 學習率適中:
↗↙ ↘ ↘
↗ ↙ ↘ ↘
↗ ↙ ↘ ↘
震盪發散 太慢 穩定收斂梯度下降的變種
1. 批次梯度下降(Batch Gradient Descent)
用所有資料計算梯度,然後更新一次。
- ✅ 穩定,方向準確
- ❌ 慢,尤其資料量大時
2. 隨機梯度下降(Stochastic Gradient Descent, SGD)
每次只用一筆資料計算梯度。
- ✅ 快,能跳出局部最小值
- ❌ 震盪大,不穩定
3. 小批次梯度下降(Mini-batch Gradient Descent)
每次用一小批資料(如 32 筆)計算梯度。
- ✅ 兼顧速度和穩定性
- ✅ 實務上最常用
4. 進階優化器
現代深度學習使用更聰明的優化器:
Momentum(動量):
- 累積之前的梯度方向
- 像球滾下山,有慣性
- 能更快通過平坦區域
Adam:
- 結合動量和自適應學習率
- 為每個參數調整學習率
- 目前最受歡迎的優化器
常見的損失地形
1. 碗狀(凸函數)
\ /
\ /
\ /
V ← 全局最小值- 只有一個最低點
- 梯度下降一定能找到
- 理想情況,但神經網路通常不是這樣
2. 有局部最小值
\ /\ /
\/ \/
局部 全局
最小 最小- 可能卡在局部最小值
- SGD 的隨機性有助於跳出
3. 鞍點
/
/
X ← 鞍點(某方向是最小,另一方向是最大)
\
\- 梯度為 0,但不是最小值
- 高維空間中很常見
- Momentum 等方法有助於通過
4. 懸崖
│
│
│____- 梯度突然變得很大
- 可能導致參數「爆炸」
- 需要梯度裁剪(Gradient Clipping)
實際訓練的流程
python
# 偽代碼
for epoch in range(num_epochs):
for batch in dataset:
# 1. 前向傳播:計算預測值
predictions = model(batch.inputs)
# 2. 計算損失
loss = loss_function(predictions, batch.labels)
# 3. 反向傳播:計算梯度
gradients = compute_gradients(loss)
# 4. 更新權重
for param in model.parameters:
param = param - learning_rate * param.gradient這個流程會重複很多次(epochs),直到損失足夠小。
互動視覺化
我製作了一個 3D 互動工具,讓你可以:
- 在不同形狀的損失地形上嘗試梯度下降
- 調整學習率,觀察收斂行為
- 選擇不同的起始點,看會收斂到哪裡
建議你試試:
- 在「碗狀」地形上,學習率 0.1 vs 0.5 的差異
- 在「鞍點」地形上,從鞍點附近開始
- 在「多峰」地形上,不同起始點會收斂到不同位置
小結
今天我們學到了:
- 學習 = 找最佳權重,使損失最小化
- 損失函數衡量模型有多糟糕(MSE 是常見選擇)
- 梯度告訴我們損失增加最快的方向
- 梯度下降:反覆朝梯度反方向走一小步
- 學習率控制步伐大小,太大會震盪,太小會太慢
- 現代優化器(如 Adam)比基本 SGD 更聰明
下一篇預告
梯度下降需要知道「梯度」——也就是損失對每個權重的偏導數。
但神經網路有數百萬個權重,怎麼有效率地計算這麼多偏導數?
下一篇我們會介紹反向傳播(Backpropagation)——深度學習最核心的算法。我們會用「傳話遊戲」來解釋,為什麼每一層都要「負責」一部分錯誤。
本文是「從零理解神經網路」系列的第三篇。如果你覺得有幫助,歡迎分享給也在學習 ML 的朋友。