MODULE 01 — THE LANDSCAPE OF OPTIMIZATION

最佳化的地形:目標與可行域

前面十二關都在「算」——給你資料,算出一個數字。這一關開始「選」: 在一片有高有低的地形上,找最低的那個點;而且有人在地上畫了圍欄,你只能在圍欄裡面找。

① 這關在解什麼問題

上一關留下的洞

機率統計 05 關教你拿 C 當一把尺, 去一個點離中心有多遠。機率統計 01 到 05 關都在做同一件事:給你資料,算出一個數字

最佳化 03 關(有效邊界)做的是另一件事。它從第一句話就開始講 「可行域」「最優解」「兩條線相切的地方就是答案」,還直接寫下 min wTCw

問題是:整套教材從來沒教過「目標函數」是什麼、「凸」是什麼、 「為什麼最低點的梯度是 0」。這一關就是把這些字補齊。這一關完全不碰金融, 金融留給最佳化 03 關;這裡只用兩個旋鈕跟一片地形。

一個很具體的困擾

你負責一個線上服務,p99 延遲太高。你手上能動的旋鈕只有兩個:

所以「延遲」是這兩個旋鈕的函數,寫成 f(x, y)。 你要找的是讓 f 最小的那組 (x, y)

但機器的記憶體是固定的。假設每 1 GB 快取吃 1 單位記憶體、每 1 條執行緒吃 2 單位, 你總共只有 5 單位:

x + 2y ≤ 5 x —— 快取大小(GB)。y —— 執行緒數。5 —— 你機器上總共有多少單位記憶體。 這一行就是「圍欄」。

於是整件事變成一句話:

這一關的一句話

在圍欄裡面,找地形最低的那個點。

「地形」= 目標函數 f)。 「圍欄」= 可行域()。 「這片地形是碗還是蛋盤」= 凸性()。 「站在最低點時你腳下有什麼特徵」= 一階條件()。

四個字,四個小節,玩完你就能讀懂最佳化 03 關的每一句話。

② 目標函數 = 地形的高度

先從你已經會的東西開始:地圖上的等高線

國中地理課的地形圖:一圈一圈的細線,每一圈上面標一個數字(100 公尺、200 公尺…)。 規則只有兩條,你早就會了:

最佳化用的就是這張圖,一個字都不用改。唯一的差別是「高度」不是海拔,而是 你想要最小化的那個東西——延遲、誤差、成本、風險。

目標函數 f(x, y) = 「站在座標 (x, y) 這個位置時,你在意的那個數字」 f —— function 的 f,本關就叫它「地形高度」。
(x, y) —— 你手上兩個旋鈕的設定值,也就是地圖上的位置。
「最佳化」= 在這張地圖上找 f 最小的位置。要找最大就把 f 加負號,同一件事。
這張圖在幹嘛
你會看到什麼:一圈一圈的等高線(顏色就是高度:綠 = 低(好)紅 = 高(差),每三圈加粗一次,跟地形圖一樣)、 紫色的臨界點(這片地形的谷底)、 藍色可拖的點(你現在站的位置),右邊那根高度條就是你站的高度。
你可以動什麼:拖那顆藍點到任何地方;用下拉選單換三種地形。
要看出什麼:沿著同一圈拖,右邊高度條不會動(高度一樣); 往圈的內側拖,高度條就往下掉。這就是「最小化」在做的事。

藍點提示:試著沿著同一圈繞一圈, 看高度條會不會動。紫點是這片地形的臨界點(梯度為 0 的地方, 見 )。

你站的位置 (x, y) 臨界點 c = (1.20, 0.80) 低(f 小) 高(f 大)
(差)
f ≥
(好)
f =
你站的位置 (x, y)
高度 f(x, y)
你踩在哪兩圈之間
每一圈的高度差 Δ
臨界點 c 的高度0.00
你比臨界點高多少
現在這一格在說

三片地形分別是什麼

三個選項不是隨便挑的,每一片都在後面的關卡出現過:

地形式子等高線長相它在哪裡出現過
f = ½[(x−1.2)² + (y−0.8)²] 同心圓 最單純的最佳化:「離目標多遠」的平方,也就是最小平方法在做的事
拉長的碗 f = ½ (v−c)TC−1(v−c) 斜的同心橢圓 機率統計 05 關那顆橢圓C = [[4, 3.6], [3.6, 4]]。這片地形的高度就是 ½ ×(馬氏距離)²
馬鞍點 f = ½[(x−1.2)² − (y−0.8)²] 雙曲線,中間交叉成一個 × 本關 ⑧ 踩坑 的主角:梯度是 0,卻不是最低點

三片地形我故意讓它們的臨界點都在同一個地方 c = (1.20, 0.80), 這樣你切換地形時,紫點不會亂跑,你可以專心看「等高線的形狀」怎麼變。

選「拉長的碗」時順手看一件事

圖上會多出一條紫色虛線橢圓,標著 f = 0.5。 那一圈就是 機率統計 05 關的 1σ 橢圓—— 因為 f = ½ × 馬氏距離²,馬氏距離 = 1 的那一圈就是 f = 0.5

同一顆橢圓,兩種讀法:機率統計 05 關讀它是「等機率的一圈」,這關讀它是「等高度的一圈」。 這不是兩個概念,是同一個東西換一個問題問。

所以這一段的結論是:目標函數就是一張地形圖, f(x, y) 是海拔,等高線是「高度一樣的點連起來」, 而「最佳化」就是在這張圖上往低處走。

本頁符號對照表

下面這張表會跟著上面那張圖一起變。畫面上出現過的每一個符號都在這裡。

符號白話:它是什麼現在的值
f(x, y)目標函數,本關就是「地形高度」。你要讓它最小
(x, y)你手上兩個旋鈕的設定值 = 地圖上的位置
v把 (x, y) 寫成一個向量的寫法,v = (x, y)。跟 (x, y) 是同一個東西
c臨界點:梯度剛好 = 0 的位置。碗的臨界點就是谷底 (1.20, 0.80)
A地形的「形狀矩陣」(2×2 對稱)。它決定碗是圓的、斜的、還是馬鞍
L等高線的高度值。「L = 3 那一圈」= 所有 f = 3 的點
Δ相鄰兩圈的高度差。全圖固定,所以「線越密 = 坡越陡」
∇f梯度:站在這一點,往上最陡的方向(讀作 nabla f)。見
‖∇f‖梯度的長度=坡有多陡。谷底的特徵就是這個數 = 0
b, r, s圍欄的大小:直線的 b、圓盤的半徑 r、盒子的半邊長 s。見 見 ③
α學習率:梯度下降一步要跨多大(讀作 alpha)。見 見 ④
等高線在這一點的切線方向(單位向量,帽子就是「長度 1」)。見 見 ⑤
·內積。兩個方向垂直 ⟺ 內積 = 0 見 ⑤

③ 可行域 = 地上的圍欄

如果沒有圍欄,最佳化很無聊:往低處走,走到谷底,結束。 真實世界從來不是這樣——你的錢有限、記憶體有限、CPU 核心是整數、比例加起來要是 100%。 這些「你不能違反的規定」寫成數學就是約束,而所有滿足約束的點合起來叫可行域

可行域 = { 所有滿足全部約束的 (x, y) } 「可行」(feasible)= 合法、可以真的做出來。
約束有兩種寫法:等式=,必須剛好落在線上)與 不等式,落在區域裡面就好)。

下面三種圍欄,是實務上 90% 的情況:

圍欄式子形狀真實世界對應
直線等式x + 2y = b一條線(可行域是「線上」,不是「線的一邊」) 預算剛好花完;最佳化 03 關的 Σw = 1(錢全部投出去)
圓盤不等式x² + y² ≤ r²一個實心圓 「總量不要超過」;也是 L2 regularization 的可行域寫法
方形盒子|x| ≤ s 且 |y| ≤ s一個正方形(其實是 4 條不等式) 每個旋鈕各自有上下限:執行緒 1~8、快取 0~4 GB、最佳化 03 關的 w ≥ 0(不准做空)
這張圖在幹嘛
你會看到什麼:同一片地形(等高線同上),加上一道橘色圍欄圍欄外面被灰掉= 不合法。然後圖上有兩個答案並排: 紫點 = 無約束的最低點(地形真正的谷底), 桃紅點 = 有約束的最低點(圍欄裡最低的地方)。 還有一顆藍點是你自己選的位置。
你可以動什麼:換地形、換圍欄種類、拉「圍欄大小」滑桿、拖藍點試試哪裡合法。
要看出什麼:兩個答案幾乎永遠不一樣,而且桃紅點 幾乎永遠貼在圍欄邊界上——因為只要還能往谷底方向挪一點點,你就會挪。

灰掉的區域=不合法,不管那裡多低都不能選。 值得試:把圍欄慢慢放大,看兩個答案什麼時候會合成一個。

圍欄邊界 無約束最低點 有約束最低點 你選的點
① 無約束最低點
 它的高度 f
② 有約束最低點
 它的高度 f
被圍欄逼著多付的代價
② 到圍欄邊界的距離
你選的點
你選的點合法嗎
現在這一格在說

三個一定要試的設定

這一段的結論

有約束的最低點幾乎永遠在邊界上。道理很白話:如果你現在站的地方四周都還在圍欄裡, 那你一定還能往下坡方向再挪一小步——除非你已經站在谷底了。所以能停下來的地方只有兩種: 真正的谷底(圍欄沒咬到你),或被圍欄擋住的邊界

我這裡是怎麼算出答案的

老實說:暴力掃描邊界。沿著圍欄邊界取 720 個點,挑最低的那個, 再用黃金分割法在它左右微調 60 次。圓盤掃一圈、盒子掃四條邊加四個角、直線掃畫面內那一段。

能這樣幹是因為這裡只有兩個變數、邊界是一維的。換成 500 個變數就完蛋了最佳化 02 關會教你怎麼寫一條方程式直接解出來,不用掃。

④ 凸性:這片地形是「碗」還是「蛋盤」

假設你不知道地形長什麼樣(真實情況通常如此:你只能量某一點的高度跟坡度), 那你只能用最笨的辦法:站在原地量哪邊往下最陡,往那邊走一步,重複。 這就是梯度下降,一行式子:

v = v − α ∇f(v) v —— 你現在站的位置 (x, y)。
∇f —— 梯度,往上最陡的方向(會拆給你看)。前面加負號就是往下。
α —— 學習率:一步跨多大。太小走不完,太大會飛出去。
下標「新 / 舊」= 第 k 步跟第 k+1 步,就只是這樣。

問題來了:這樣走一定會走到最低點嗎?答案是「看地形」。而分界線就叫凸性

這兩張圖在幹嘛
你會看到什麼:兩片地形並排。左邊是凸的(一個碗,就是 ② 的「拉長的碗」), 右邊是非凸的(蛋盤,一格一格的凹坑)。每一張都從五個不同起點跑梯度下降, 五條軌跡各有顏色,空心方塊 = 起點實心點 = 60~300 步之後停下來的地方
你可以動什麼:學習率 α、步數,以及「換一組起點」(會換亂數 seed,seed 顯示在下面)。
要看出什麼:左邊五條都收在同一個點;右邊五條卡在不同的坑裡, 而且只有運氣好的那條找到最深的坑。

凸的:一個碗(f = ½ vTAv,A 正定)

非凸的:蛋盤(f = 0.1(x²+y²) − 0.8[cos 1.8x + cos 1.8y]

#起點左(凸碗)走到f右(蛋盤)走到f
左(凸碗):幾條收斂到同一點
右(蛋盤):落到幾個不同的谷
右:幾條找到最深的那個谷
現在這一組在說

「凸」到底在保證什麼

一句話

「凸」的意思不是「很好算」,是「往下走一定到得了終點;局部最低就是全域最低」。

換句話說:在凸地形上,你永遠不需要擔心起點選錯。 你在任何一點停下來(梯度 = 0、走不動了),那個點就是全世界最低的點,不用再找。 這是一個非常強的保證——非凸地形完全沒有這種東西。

白話的判斷法,跟國中畫圖一樣:

順手把最佳化 03 關的坑補掉

最佳化 03 關會直接寫下投資組合的風險 σp² = wTCw,然後說「這是個凸問題,所以有唯一解」。 為什麼可以這樣說?

因為 C共變異數矩陣,而共變異數矩陣永遠半正定—— 理由一句話就講完:wTCw 的意思是 「把資產按 w 混起來之後的變異數」, 而變異數是平方的平均,不可能是負的

半正定 ⟹ 那片地形一定是碗(最壞情況是有一條平底),不可能是蛋盤、不可能是馬鞍。 所以最佳化 03 關才敢直接解一條方程式就收工,不必擔心「卡在局部最低」。 這是整套教材裡「凸」這個字唯一真正付錢的地方。

所以這一段的結論是:凸地形上梯度下降是「保證會到」的; 非凸地形上它只保證「會停」,停在哪要看你從哪裡出發、一步跨多大。

⑤ 一階條件:梯度是什麼,為什麼谷底的梯度是 0

偏導數與梯度的完整版( 為什麼是「其他變數當常數」、 ∇f(v) = A(v − c) 怎麼算出來)在 微積分 · 多變量關 ②; 更前面的一維基礎(差商怎麼變成切線)在 導數關 ②不讀也能玩這一節,卡住再去。

「梯度」聽起來很兇,它其實只是兩個偏微分擺成一個向量

∇f(x, y) = ( ∂f/∂x , ∂f/∂y ) ∂f/∂x —— 「只動 x、y 不動」時 f 變多快。就是把 y 當常數的斜率。
∂f/∂y —— 反過來,只動 y。
∇ —— 讀作 nabla(或 del)。∇f 讀作「f 的梯度」,它是一個向量,不是一個數字。

兩個必須記住的性質,其中第二個是本節的重點:

  1. ∇f 指向往上最陡的方向。所以下坡方向是 −∇f
  2. ∇f 一定垂直於等高線

第二點為什麼?一句話:沿著等高線走,高度不變;不變就代表「往那個方向的斜率是 0」; 而斜率 = 梯度跟走的方向做內積。內積是 0,就是垂直。 下面那張圖就是在現場驗這件事

這張圖在幹嘛
你會看到什麼:等高線(同 ②)、你拖的藍點、 從藍點射出的橘色箭頭 = ∇f(往上最陡)、 反向的綠色虛線箭頭 = −∇f(下坡,梯度下降要走的方向)、 以及一條穿過藍點的桃紅色直線 = 等高線在這一點的切線, 兩者之間畫了一個直角記號
你可以動什麼:藍點;換地形。 右下小圖會跟著畫「離臨界點多遠 → 梯度多長」。
要看出什麼:讀數盤裡的 ∇f · t̂ 永遠是 0.0000、夾角永遠是 90°; 而藍點拖向紫點時,橘箭頭會縮短到消失

橘箭頭已按 0.5 倍畫(不然會衝出畫面),但長度仍與 ‖∇f‖ 成正比。 桃紅切線是我沿著同一個高度量出來的完全沒有用到梯度——所以「內積 = 0」是真的在驗證,不是套套邏輯。

你站的位置 ∇f(上坡最陡) −∇f(下坡) 等高線切線 t̂
位置 (x, y)
高度 f
∇f = (∂f/∂x, ∂f/∂y)
‖∇f‖(坡有多陡)
等高線切線 t̂
∇f · t̂(現場算的內積)
兩者夾角
離臨界點 c 多遠

小圖:沿著「紫點藍點」這條射線走, 橫軸是走了多遠,縱軸是那裡的 ‖∇f‖射線起點(也就是臨界點)上,梯度長度掉到 0。

現在這一格在說

把「谷底」翻譯成一條方程式

現在可以下定義了。如果 v*無約束問題的最低點,那麼:

∇f(v*) = 0 v* —— 星號慣例上代表「答案」、最優解。
這一行叫一階條件(first-order condition),因為它只用到一次微分。
白話:站在谷底,四面八方都不往下。哪個方向都沒有下坡,坡度就只能是 0。

∇f = 0 只是候選人、還要看二階才知道是谷底或山頂」的一維代數版, 在微積分 · 多變量關 ③(那裡有一條兩個谷底夾一個山頂的曲線可以拖); 多維版的判別法(Hessian 的行列式與跡)在同關 ④

這條式子很好用,因為它把「找最低點」變成「解方程式」。以本關的二次地形為例, 整個推導只有兩行:

f(v) = ½ (v − c)TA(v − c)  ⟹  ∇f(v) = A(v − c)
∇f = 0  ⟹  A(v − c) = 0  ⟹  v = c (A 是對稱矩陣時才這麼乾淨,本關三片地形的 A 都對稱。) 所以「臨界點就在 c」不是我硬塞的,是解出來的。
但是(這就是下一關的入口)

∇f = 0 只對無約束問題成立

回去看 :只要圍欄咬到你,答案就在邊界上,而邊界上的點 梯度根本不是 0——你明明還感覺到下坡(往谷底那邊),只是那個方向被圍欄擋住了,走不過去。

拿 ③ 的預設值:碗 + 直線 b = 5,有約束最低點是 (1.64, 1.68), 在那裡 ∇f = (0.44, 0.88),長度 0.98,離 0 差得遠。

但仔細看那個梯度:(0.44, 0.88) 剛好是 (1, 2) 的 0.44 倍,而 (1, 2) 正是圍欄 x + 2y = 5 的法向量。梯度不是 0,但它剛好完全垂直於圍欄。

那個「0.44」就是 最佳化 02 關的 Lagrange 乘子 λ。 下一關整關都在講這一件事。

⑥ 數學長怎樣(可以照著寫成程式的版本)

先給能跑的程式碼,五十行內把這一關全部裝完:

// 地形:f(v) = ½ (v − c)ᵀ A (v − c),A 對稱
const A = [[1, 0], [0, 1]], c = { x: 1.2, y: 0.8 };

function f(x, y) {
  const dx = x - c.x, dy = y - c.y;
  return 0.5 * (A[0][0]*dx*dx + 2*A[0][1]*dx*dy + A[1][1]*dy*dy);
}
// 梯度:對稱 A 的時候剛好就是 A(v − c)
function grad(x, y) {
  const dx = x - c.x, dy = y - c.y;
  return { x: A[0][0]*dx + A[0][1]*dy, y: A[1][0]*dx + A[1][1]*dy };
}

// 梯度下降:往 −∇f 走 α 步,重複
function descend(start, alpha, steps) {
  let v = { ...start };
  for (let i = 0; i < steps; i++) {
    const g = grad(v.x, v.y);
    v = { x: v.x - alpha * g.x, y: v.y - alpha * g.y };
  }
  return v;                       // 凸地形:不管 start 是什麼,都會回到 c
}

// 有約束:這一關用暴力法 —— 沿著圍欄邊界掃,挑最低的
function minOnCircle(r, n = 720) {
  let best = null;
  for (let i = 0; i < n; i++) {
    const a = 2 * Math.PI * i / n;
    const p = { x: r * Math.cos(a), y: r * Math.sin(a) };
    const v = f(p.x, p.y);
    if (!best || v < best.v) best = { ...p, v };
  }
  return best;                    // 最佳化 02 關會教你怎麼「解」而不是「掃」
}

符號版,每個字母都翻譯:

最小化  f(v)  使得  v ∈ F v —— 決策變數(你能動的旋鈕),本關是 (x, y)。
f —— 目標函數(你想壓低的數字)。
F —— 可行域(feasible set),所有合法的 v 合起來的集合。
整行讀作:「在 F 裡面挑一個 v,讓 f(v) 最小」。這就是最佳化問題的標準寫法。
f(v) = ½ (v − c)TA(v − c)  ·  ∇f(v) = A(v − c)  ·  ∇²f = A A —— 形狀矩陣,也是這片地形的 Hessian(二次微分矩陣)。
A 的特徵值全 > 0 → 正定 → 凸(碗);有正有負 → 馬鞍;全 ≥ 0 → 半正定(碗,可能有平底)。
½ 是慣例:放了它,梯度才乾淨地等於 A(v − c),不會多一個 2。
無約束最低點:∇f(v*) = 0  ⟹  v* = c v* —— 最優解。這一行就是「一階條件」。
注意它是必要條件不是充分條件:馬鞍點也滿足 ∇f = 0,卻不是最低點。
梯度下降:vk+1 = vk − α ∇f(vk) 下標 k —— 第幾步(k = 0 是起點)。α —— 學習率。
二次地形上收斂的條件是 α < 2 / λmax(A);本關「拉長的碗」的 λmax = 2.5, 所以 α 超過 0.8 就會震盪發散 —— 上面的滑桿可以拉到 1.1,自己去把它弄爆。

⑦ 工程師的「原來如此」

神經網路訓練=在非凸地形上跑梯度下降

訓練一個模型就是:目標函數= loss(預測錯多少),決策變數= 幾億個權重, 方法= 梯度下降(SGD / Adam 都是它的變種)。地形維度是幾億,而且非凸

「非凸」這一件事直接解釋了三個你天天在做卻覺得很玄的動作:

  • 為什麼要在意初始化(Xavier、He initialization)—— 起點決定你滾進哪個坑, 就是 右邊那張圖,只是換成幾億維。
  • 為什麼學習率要調、還要 warmup + decay —— α 太大在山谷裡彈來彈去(甚至 loss 變 NaN), 太小跑三天還沒到。④ 的 α 滑桿拉到 1.1 就是 NaN 的那個現場。
  • 為什麼同一份 code 跑兩次結果不一樣 —— 不同的隨機起點 / 不同的 batch 順序 = 不同的坑。 凸問題不會有這種事,換十個起點都給你同一個答案。
資源配額與容量規劃=標準的約束最佳化

Kubernetes 的 request / limit、雲端帳單優化、CDN 節點放哪、DB 連線池開多大—— 全部是同一個模板:

最小化 (延遲 或 成本)  使得  Σ 資源 ≤ 預算,每項 ≥ 0,某些是整數 「Σ 資源 ≤ 預算」= ③ 的直線 / 圓盤;「每項 ≥ 0」= ③ 的盒子。

那個結論——最優解幾乎永遠貼在邊界上——就是為什麼 容量規劃的答案總是「剛好把預算花完」而不是留一半。這也是為什麼調參老是感覺 「多給一點就好一點,直到某條線被撞到」:你正在沿著可行域的邊界爬。

(「某些是整數」是這片地形上最惡毒的約束:可行域從一片連續區域變成一堆孤立的點, 梯度完全失效。那是整數規劃的領域,本教材不碰。)

⑧ 踩坑

坑 1:局部最低 ≠ 全域最低

「梯度下降跑完、loss 不動了」只代表你走不動了,不代表那是最低點 右邊五條軌跡,落點的 f 分別是 −1.60、−0.47、−0.47、+0.66、+0.66—— 五個都是合法的「梯度 = 0、走不動」的點,但只有一個是真正的最低。

唯一能讓你安心說「停下來就是答案」的情況,是你證明了地形是凸的

坑 2:∇f = 0 只是必要條件,馬鞍點也滿足

在 ② / ⑤ 選「馬鞍點」,把藍點拖到 c = (1.20, 0.80)梯度長度真的是 0,但那裡不是最低點——沿著 y 方向走,f 一路往下沒有底。

所以「解 ∇f = 0」找到的是候選人名單(最低點、最高點、馬鞍點都在裡面), 要分辨是哪一種,得看二次微分 A 的特徵值正負。 順帶說:高維空間裡馬鞍點遠比局部最低點多,這是深度學習訓練卡住的主要原因之一。

坑 3:答案對「目標函數怎麼寫」極度敏感

最刺眼的一組對照:圍欄一模一樣(x + 2y = 5), 地形從「碗」換成「拉長的碗」,答案就從 (1.64, 1.68) 跳到 (1.92, 1.54)

換句話說:你把目標寫成什麼,就會得到什麼。 把「延遲」寫成平均延遲、p99、還是 p99.9,最優配置會落在完全不同的地方; loss 從 MSE 換成 MAE,模型學到的東西就不一樣。最佳化只會忠實地執行你寫下的那句話, 不會執行你心裡想的那句

坑 4:實務上「約束寫錯」比「目標寫錯」更常見,也更難抓

目標寫錯,你通常看得出來(答案很怪)。約束寫錯的症狀比較陰險,通常是這三種:

  • 可行域是空的——約束互相矛盾,solver 回 infeasible,而你以為是 bug。
  • 可行域太大——忘了寫某個限制(例:忘了 x ≥ 0), 答案跑到「快取大小 −3 GB」這種物理上不存在的地方,數學上卻完美。
  • 可行域太小——多寫了一個沒必要的約束,你拿到一個「合法但明顯不夠好」的答案, 而且完全看不出哪裡不對,因為 solver 不會抱怨。

檢查法:解完之後看哪些約束是「被咬到的」(active,答案貼在它的邊界上)。 如果一個你隨手加的約束居然是 active,那它正在替你決定答案,你最好回去確認它是真的。 這件事在 最佳化 02 關會變成一個可以直接讀的數字。

⑨ 這關回答了什麼

目標函數是什麼?

就是「你想要壓到最小的那個數字」,寫成 f(x, y): 把你能動的旋鈕餵給它,它吐出一個數。

本關把它想成地形的高度——旋鈕的設定值是地圖上的座標,f 是那個點的海拔。 延遲、成本、預測誤差、投資組合的風險,全都可以當 f。

兩件事值得記住:① 要「最大化」就把 f 加負號,完全一樣的問題; ② f 寫成什麼,你就會得到什麼坑 3)。

等高線怎麼讀?

跟地理課的地形圖一模一樣,兩條規則:

同一圈上的點高度完全一樣。沿著等高線走,f 不變( 那張圖可以直接驗:沿一圈拖,右邊高度條不動)。

線越密 = 坡越陡。因為相鄰兩圈的高度差 Δ 是固定的, 水平距離越短卻掉同樣的高度,當然更陡。

再加一條這關新學的:梯度一定垂直穿過等高線,指向線變密的那一邊 ()。

可行域為什麼重要?

因為它會直接改掉答案,而且改得很多。

沒有圍欄時答案就是谷底,一個。加上圍欄之後, 谷底可能根本不在圍欄裡,這時真正的答案是「圍欄上最低的那個點」, 而它幾乎永遠貼在邊界上)。

理由很白話:如果你四周都還在圍欄裡,你一定還能往下坡挪一步; 會被迫停下來,就是因為想走的那個方向被牆擋住了。

這也是為什麼容量規劃 / 預算配置的答案總是「剛好把資源用完」。

凸到底在保證什麼?

保證兩件事,而且都很強:

局部最低就是全域最低。你隨便停在一個「走不動」的點,那就是答案,不用再找。

往下走一定到得了。起點怎麼選都不影響最後的落點 (左邊五條軌跡收在同一點)。

注意它不是在保證「很好算」或「算得快」—— 左邊那個碗很扁(A 的特徵值 2.5 與 0.13,差 19 倍), 梯度下降在裡面會 zigzag 走很久。凸只保證「到得了」,不保證「很快到」。

怎麼確認地形是凸的?二次地形就看 A 的特徵值是不是都 ≥ 0 (半正定)。共變異數矩陣 C 永遠滿足這條, 所以 最佳化 03 關的 wTCw 一定是碗。

梯度是什麼方向?

∇f 指向往上最陡的方向(不是往下!下坡是 −∇f, 所以梯度下降的式子裡有個減號)。

它的長度 ‖∇f‖ 就是那個方向有多陡; 它一定垂直於等高線

垂直這件事在 是現場驗的:我沿著同一個高度量出等高線的切線 (過程完全沒用到梯度),再跟 ∇f內積,結果永遠是 0.0000、夾角 90°。

直覺版:沿著等高線走,高度不變 ⟹ 那個方向的斜率是 0 ⟹ 梯度在那個方向上沒有分量 ⟹ 垂直。

為什麼有約束時「梯度 = 0」失效?

因為「梯度 = 0」的意思是「四面八方都不往下」,而有圍欄時你不需要四面八方都不往下—— 你只需要「所有還走得過去的方向都不往下」。

具體看 的預設值:碗 + 直線 x + 2y = 5, 答案在 (1.64, 1.68),那裡 ∇f = (0.44, 0.88),長度 0.98, 完全不是 0。你在那裡確實感覺到下坡(往谷底 (1.20, 0.80) 那個方向), 但那個方向會讓你穿牆,所以不能走。

那新的停止條件是什麼?答案已經藏在數字裡了: (0.44, 0.88) = 0.44 × (1, 2),而 (1, 2) 正是那道圍欄的法向量。梯度不是 0,但它完全垂直於圍欄—— 意思是「剩下的下坡力氣全部被牆頂住了,沒有一絲一毫沿著牆的方向」。

把這句話寫成方程式,就是 最佳化 02 關的 Lagrange 乘子; 那個 0.44 就是 λ。

那我到底該用梯度下降,還是解方程式?

看你有什麼。

解方程式∇f = 0)需要你「寫得出 f 的式子並且解得開」。 二次地形可以,最佳化 03 關的投資組合也可以—— 所以那一關直接給你封閉解。

梯度下降只需要你「在任一點量得出坡度」,f 長什麼樣不用知道。 代價是:非凸地形上它只保證「會停」,不保證「停在最低點」(坑 1), 而且要調 α。幾億個參數的神經網路只剩這條路。

兩者共用的都是同一個一階條件。差別只在「解它」還是「逼近它」。

這關留下什麼洞 → 下一關補

本關的答案有一半是掃出來的:沿著圍欄邊界取 720 個點,挑最低的。 兩個變數可以這樣幹,兩百個變數不行。

而且 最後那個觀察太漂亮了不能放著: 有約束的最低點上,梯度不是 0,但它完全垂直於圍欄;換句話說, 等高線跟圍欄在那一點剛好相切

最佳化 02 關:Lagrange 乘子與 KKT會把這句幾何觀察變成一條可以解的方程式, 並回答「不等式約束怎麼辦」( 到底有沒有被咬到?)。 那一關做完,最佳化 03 關的每一個式子都會變成理所當然。