微分方程入門:只學過微積分,從頭開始
這一頁假設你學過微積分,但完全沒學過微分方程。我們從「微分方程到底是什麼」開始,手算第一個解,再一路走到相圖、特徵值、數值解法,最後看懂 DDIM 為什麼能用很少的步數。每一步都會寫出來,不會跳過。
讀完這頁你應該能夠
- 說明微分方程在問什麼,並用「代回去」驗算一個解是不是對的。
- 用分離變數一步一步解出 \(\frac{dx}{dt} = -kx\),解釋積分常數如何變成初始值。
- 看懂斜率場、向量場和相圖,並從圖上想像解的樣子。
- 說明為什麼軌跡不會交叉,以及為什麼這讓 ODE 可以倒著走。
- 推導為什麼從特徵向量 \(\mathbf v\) 出發的解是 \(e^{\lambda t}\mathbf v\),以及為什麼兩個特徵值就決定了整張相圖。
- 寫出 Euler、Heun、RK4 的更新式,並用面積的圖解釋它們為什麼一個比一個準。
- 解釋 Euler 為什麼在 \(h\lambda > 2\) 時會爆掉,並一步一步推導指數積分器,看懂它和 DDIM 的關係。
00怎麼讀這一頁
只需要這三樣微積分工具:導數是變化率;積分是導數的反運算;連鎖律 \(\frac{d}{dt}f(g(t)) = f'(g(t))\,g'(t)\)。另外會反覆用到 \(\frac{d}{dt}e^{at} = ae^{at}\) 和 \(\frac{d}{dx}\ln x = \frac1x\)。
第 1–4 節只有一個變數,一定要慢慢讀。第 5–7 節進入多個變數,需要矩陣和特徵值;如果還不熟,先讀補充課 A 第 3–4 節。第 8–11 節是電腦怎麼解 ODE。綠色線標示的「手算」區塊,建議拿紙筆跟著算。
01微分方程是什麼:未知的是一個函數
國中解的方程式,未知的是一個數字。例如 \(2x + 1 = 7\),答案是 \(x = 3\)。
微分方程未知的是一個函數,而且方程式描述的是這個函數的變化率。例如:
$$\frac{dx}{dt} = 2$$意思是「有一個隨時間變化的量 \(x(t)\),它每單位時間固定增加 2」。答案不是一個數字,而是一個函數,例如 \(x(t) = 2t\)。
三個一定要知道的詞
- 解:一個函數,代入方程式後等號在所有時間都成立。
- 初始條件:起點的值,例如 \(x(0) = 5\)。\(x = 2t\) 和 \(x = 2t + 5\) 都滿足 \(\frac{dx}{dt} = 2\),只知道規則無法決定是哪一條,還要知道從哪裡出發。
- ODE(ordinary differential equation,常微分方程):只對一個變數(這裡是時間 \(t\))微分的方程。對多個變數微分的叫 PDE,補充課 C 才會遇到。
這一頁的 ODE 都長這樣:
把它讀成一條速度規則:如果現在時間是 \(t\)、位置是 \(x\),那麼速度就是 \(v(x, t)\)。解 ODE 就是「照著這條規則,從起點一直走,看會走出什麼路線」。常見的另一種記法是在變數上加一點:\(\dot x\) 就是 \(\frac{dx}{dt}\)。
怎麼驗算一個解
解方程式很難,但驗算很簡單:把函數代回去,看左右兩邊是否相等。這個技巧整頁都會用。
\(x(t) = 3e^{-2t}\) 是不是 \(\frac{dx}{dt} = -2x\) 的解?
- 左邊:\(\frac{d}{dt}3e^{-2t} = -6e^{-2t}\)
- 右邊:\(-2\cdot3e^{-2t} = -6e^{-2t}\)
兩邊相等,所以是解,而且 \(x(0) = 3\)。反過來,\(x(t) = t^2\) 代入後左邊是 \(2t\)、右邊是 \(-2t^2\),不相等,所以不是解。
小練習:\(x(t) = \sin t\) 是 \(\frac{dx}{dt} = \cos t\) 的解嗎?\(x(t) = \sin t + 7\) 呢?
02最簡單的情況:右邊只有 t,就是積分
如果速度只和時間有關,\(\frac{dx}{dt} = f(t)\),這其實就是微積分:已知速度求位置,兩邊對 \(t\) 積分就好。
\(\frac{dx}{dt} = 2t\),\(x(0) = 1\)。
- 兩邊積分:\(x(t) = t^2 + C\)。\(C\) 是積分常數,因為常數微分後是 0,積分無法確定它。
- 用初始條件決定 \(C\):代入 \(t = 0\),得到 \(1 = 0 + C\),所以 \(C = 1\)。
- 答案:\(x(t) = t^2 + 1\)。
- 驗算:\(\frac{dx}{dt} = 2t\) ✓,\(x(0) = 1\) ✓。
這裡已經出現了微分方程的基本結構:規則給出一整族解,初始條件選出其中一條。
03第一個真正的 ODE:剩越多、掉越快
為什麼這題不能直接積分
放射性物質每單位時間衰變掉固定的比例,所以剩越多、衰變越快:
$$\frac{dx}{dt} = -k\,x\qquad(k > 0)$$右邊是 \(x\),不是 \(t\)。想直接積分會變成 \(x = -k\int x\,dt\),但要積的正是我們還不知道的 \(x(t)\),繞了一圈。這就是微分方程和普通積分真正不同的地方:速度取決於現在的位置,而位置又取決於過去的速度。
先不解,直接照規則走
就算不會解,也可以一步一步算。設 \(k = 0.1\)、\(x(0) = 100\),每次走 \(h = 1\) 的時間。假設這一小段內速度不變,新值 = 舊值 + 速度 × 時間:
| \(t\) | \(x\) | 速度 \(-0.1x\) | 下一個 \(x\) |
|---|---|---|---|
| 0 | 100 | −10 | 90 |
| 1 | 90 | −9 | 81 |
| 2 | 81 | −8.1 | 72.9 |
| 3 | 72.9 | −7.29 | 65.61 |
每一步都是乘上 \(0.9\),所以 \(t = 10\) 時是 \(100\times0.9^{10} = 34.87\)。
但「這段時間內速度不變」並不準確,因為 \(x\) 一直在變小,速度也一直在變小。步長越小,這個假設越準:
| 步長 \(h\) | 每步乘上 | \(t = 10\) 時的 \(x\) |
|---|---|---|
| 2 | 0.8 | 32.77 |
| 1 | 0.9 | 34.87 |
| 0.5 | 0.95 | 35.85 |
| 0.1 | 0.99 | 36.60 |
| 極限 \(h\to0\) | 36.79 |
數字收斂到某個值。微積分學過 \((1 - kh)^{t/h}\to e^{-kt}\)(\(h\to0\)),所以極限是 \(100e^{-1} = 36.79\)。指數函數就是這樣出現的:每一小步都乘上一個接近 1 的數,乘無限多次就是指數。
Demo B1 · 照著速度規則一步一步走
精確解法:分離變數
現在正式解出來。想法是:把和 \(x\) 有關的都搬到左邊,和 \(t\) 有關的都搬到右邊,兩邊就都能積分了。
- 兩邊除以 \(x\)(先假設 \(x\neq0\)): $$\frac{1}{x}\frac{dx}{dt} = -k$$
- 左邊正是某個函數的導數。由連鎖律,\(\frac{d}{dt}\ln x(t) = \frac{1}{x}\frac{dx}{dt}\)。所以方程式變成: $$\frac{d}{dt}\ln x(t) = -k$$ 這就是 \(\ln x\) 版本的第 2 節!右邊只是常數。
- 兩邊對 \(t\) 積分: $$\ln x(t) = -kt + C$$
- 兩邊取指數,把 \(\ln\) 去掉: $$x(t) = e^{-kt + C} = e^{C}\,e^{-kt}$$
- \(e^C\) 只是一個還沒決定的常數,記成 \(A\)。代入 \(t = 0\):\(x(0) = A\cdot e^0 = A\)。所以積分常數就是初始值。
驗算:\(\frac{d}{dt}x(0)e^{-kt} = -k\,x(0)e^{-kt} = -k\,x(t)\) ✓。
你在其他書上可能會看到更簡短的寫法:把 \(dx\) 和 \(dt\) 當成分數拆開,得到 \(\frac{dx}{x} = -k\,dt\),再兩邊分別積分。它和上面是同一件事,只是省略了連鎖律那一步。
\(k\) 的正負決定一切:\(\dot x = ax\) 的解是 \(x(0)e^{at}\)。\(a \lt 0\) 衰減到 0,\(a > 0\) 爆炸,\(a = 0\) 不動。第 7 節會反覆用到這個結果。
\(\frac{dx}{dt} = x^2\),\(x(0) = 1\)。除以 \(x^2\):\(x^{-2}\frac{dx}{dt} = 1\)。左邊是 \(\frac{d}{dt}(-x^{-1})\),積分得 \(-\frac1x = t + C\)。代入 \(t = 0, x = 1\),得 \(C = -1\),所以 \(x(t) = \frac{1}{1-t}\)。
驗算:\(\frac{dx}{dt} = \frac{1}{(1-t)^2} = x^2\) ✓。注意它在 \(t = 1\) 衝到無窮大:ODE 的解不一定對所有時間都存在。
大多數 ODE 無法這樣分離,例如 \(\frac{dx}{dt} = \sin(2t) - x\)(第 11 節會解);速度場是神經網路時,更不可能有公式解。所以後面才需要圖形和數值方法。
小練習:\(\frac{dx}{dt} = 0.5x\),\(x(0) = 2\)。\(x(t)\) 是什麼?驗算一次。
04斜率場:不解方程也能看出解的樣子
公式解很少見,但有一個辦法永遠可用:把規則畫出來。在 \((t, x)\) 平面的每一點,規則都告訴我們解在那裡的斜率 \(\frac{dx}{dt}\)。畫一小段那個斜率的線段,就是斜率場。
例如 \(\frac{dx}{dt} = -x\)。在 \(x = 2\) 的地方斜率是 \(-2\)(陡陡地往下);\(x = 0\) 的地方斜率是 0(水平);\(x = -1\) 的地方斜率是 \(+1\)(往上)。
平衡點
讓速度為 0 的位置叫平衡點:粒子放在那裡就不會動。平衡點分兩種,看附近的粒子是被吸回來還是被推開:
族群成長 \(\frac{dx}{dt} = x(1-x)\)。令右邊等於 0,得到平衡點 \(x = 0\) 和 \(x = 1\)。
- \(x = 0.1\):速度 \(0.09 > 0\),往上走,離開 0。所以 \(x = 0\) 是不穩定的。
- \(x = 0.9\):速度 \(0.09 > 0\),往上走,靠近 1。\(x = 1.2\):速度 \(-0.24\),往下走,也靠近 1。所以 \(x = 1\) 是穩定的。
Demo B2 · 斜率場與解曲線(點一下畫布加一條解)
- 衰減:所有解都往 0 靠近,越來越貼近,但不會碰在一起。
- 族群成長:解被 \(x = 1\) 吸過去,被 \(x = 0\) 推開。
- 被推動的衰減:不論從哪裡出發,過一段時間都被拉到同一條擺動的曲線上,起點被「忘掉」了。第 16 講說「雜訊夠多時,從哪裡出發都一樣」,是同一種現象。
- 爆炸:\(x(0) = 1\) 的解在 \(t = 1\) 衝到無窮大。
小練習:\(\frac{dx}{dt} = x - x^3\) 的平衡點有哪些?哪些是穩定的?
05二維:向量場與相圖
為什麼需要多個變數
一張圖片有上百萬個像素,是一個上百萬維的點。Diffusion model 就是在這個空間裡推動粒子。維度太高畫不出來,但道理在二維時就看得到。
從一條方程變成一組方程
粒子的位置現在有兩個座標 \((x, y)\),規則也變成兩條:
$$\frac{dx}{dt} = v_1(x, y),\qquad\frac{dy}{dt} = v_2(x, y)$$寫成向量就是 \(\frac{d\mathbf x}{dt} = \mathbf v(\mathbf x)\),和一維長得一模一樣。平面上每一點都有一支速度箭頭 \(\mathbf v(\mathbf x)\),合起來叫向量場。把粒子放進去,它就順著箭頭走,走出來的路線叫軌跡。
\(\frac{dx}{dt} = -y,\ \frac{dy}{dt} = x\),從 \((1, 0)\) 出發。在 \((1, 0)\) 的速度是 \((0, 1)\),朝上;在 \((0, 1)\) 的速度是 \((-1, 0)\),朝左。看起來在繞圈。
猜 \(x = \cos t,\ y = \sin t\) 並驗算:\(\frac{dx}{dt} = -\sin t = -y\) ✓,\(\frac{dy}{dt} = \cos t = x\) ✓。解確實是單位圓。
相圖是什麼
同一個解有兩種畫法。第一種是分別畫出 \(x, y\) 對 \(t\) 的曲線。第二種是不畫時間,只在 \((x, y)\) 平面上畫出粒子走過的路線。第二種就叫相圖(phase portrait)。它通常會畫很多條軌跡,每條從不同的起點出發,讓你一眼看到所有可能的未來。
Demo B3 · 向量場與流動的粒子
這就是 CS236 裡 probability flow ODE 和 flow matching 的畫面:學一個向量場,把一團雜訊粒子推成資料的形狀。
06軌跡不交叉,所以可以倒著走
解是唯一的
只要速度場夠平滑,從每個起點出發的解都存在而且唯一。「夠平滑」的嚴格說法是 Lipschitz 連續:存在常數 \(L\),對任意兩點都有
$$\Vert\mathbf v(\mathbf x) - \mathbf v(\mathbf y)\Vert\le L\Vert\mathbf x - \mathbf y\Vert$$白話就是:兩點靠近時,它們的速度也要靠近,速度場不能有無限陡的斜率。
不交叉
唯一性直接帶來一個看得見的結果:兩條軌跡不可能交叉。
精確地說:速度場隨時間改變時,是「同一時刻不會有兩顆粒子在同一位置」。相圖上的路線,有可能在不同時刻經過同一點,但粒子不會同時在那裡相遇。
可以倒著走
如果把時間倒過來,令 \(\mathbf y(s) = \mathbf x(T - s)\),由連鎖律:
$$\frac{d\mathbf y}{ds} = -\frac{d\mathbf x}{dt}\Big|_{t = T - s} = -\mathbf v(\mathbf y(s))$$所以把速度反過來走,就會原路回去。把 ODE 從 0 解到 \(T\) 是一個可逆的映射:不同的起點一定走到不同的終點(否則就交叉了),而且可以用 \(-\mathbf v\) 走回來。第 14、17 講說「ODE 的解唯一,所以 diffusion model 可以變成 normalizing flow」,指的就是這件事。
Demo B4 · 往前流,再倒著流回來
反例:速度場不平滑時,解可以不唯一
\(\frac{dx}{dt} = \sqrt{|x|}\),\(x(0) = 0\)。
- \(x(t) = 0\) 是一個解:左邊 0,右邊 0。
- \(x(t) = t^2/4\)(\(t\ge0\))也是:左邊 \(t/2\),右邊 \(\sqrt{t^2/4} = t/2\)。
粒子可以在原點停任意久再出發,未來不唯一。問題出在 \(\sqrt{|x|}\) 在 0 的斜率是無窮大,不是 Lipschitz 連續。神經網路用平滑的激活函數、權重有限,所以 diffusion 的速度場通常沒有這個問題。
出處:Lai et al. (2026) 附錄 A.1.2,局部與全域的存在唯一性定理,以及「Uniqueness Implies Non-Intersection of Solutions」一段。
07線性系統:為什麼特徵值決定了一切
為什麼需要它
一般的 ODE 沒有公式解,但有一大類可以完全解出來:線性系統,也就是速度是位置的矩陣乘法。
$$\frac{d\mathbf x}{dt} = A\mathbf x$$它在 CS236 很重要:diffusion 的前向過程、第 18 講的離散 diffusion 都是線性的。而且任何平滑的 ODE,放大到一點附近看,都近似線性(Jacobian 就是那個矩陣),所以這裡學到的東西到處都用得上。
這一節會用到特徵值和特徵向量。如果忘了,先看補充課 A 第 4 節:\(A\mathbf v = \lambda\mathbf v\) 的 \(\mathbf v\) 是不會轉彎的方向,\(\lambda\) 是沿那個方向拉長的倍數。
第一步:沒有互相影響的情況
如果 \(A\) 是對角矩陣,兩個變數互不影響,就是兩個獨立的第 3 節:
$$\frac{d}{dt}\begin{bmatrix}x\\y\end{bmatrix} = \begin{bmatrix}-1&0\\0&-3\end{bmatrix}\begin{bmatrix}x\\y\end{bmatrix}$$也就是 \(\dot x = -x,\ \dot y = -3y\),解是 \(x(t) = x(0)e^{-t},\ y(t) = y(0)e^{-3t}\)。很容易。
第二步:互相影響時,找不會互相影響的方向
現在考慮
$$A = \begin{bmatrix}-2&1\\1&-2\end{bmatrix}$$也就是 \(\dot x = -2x + y,\ \dot y = x - 2y\)。\(x\) 的速度取決於 \(y\),\(y\) 的速度取決於 \(x\),兩條方程綁在一起,不能分開解。
換個問法:有沒有哪個方向,粒子從那裡出發後會一直留在同一條直線上?如果有,沿那條線就只剩一維的問題了。
設粒子一直留在方向 \(\mathbf v\) 上,也就是 \(\mathbf x(t) = f(t)\,\mathbf v\),其中 \(f(t)\) 是一個純量函數,表示它在線上的位置。代入 ODE:
- 左邊:\(\frac{d}{dt}\big(f(t)\mathbf v\big) = f'(t)\,\mathbf v\)(\(\mathbf v\) 是固定的向量)
- 右邊:\(A\big(f(t)\mathbf v\big) = f(t)\,A\mathbf v\)
要讓 \(f'(t)\,\mathbf v = f(t)\,A\mathbf v\) 成立,\(A\mathbf v\) 必須和 \(\mathbf v\) 同方向,也就是 \(A\mathbf v = \lambda\mathbf v\):\(\mathbf v\) 必須是特徵向量。代入後兩邊的 \(\mathbf v\) 消掉,只剩:
$$f'(t) = \lambda f(t)$$這正是第 3 節解過的方程,答案是 \(f(t) = f(0)e^{\lambda t}\)。所以:
如果 \(A\mathbf v = \lambda\mathbf v\),從 \(\mathbf v\) 出發的解就是
$$\mathbf x(t) = e^{\lambda t}\mathbf v$$也可以直接驗算:左邊 \(\frac{d}{dt}e^{\lambda t}\mathbf v = \lambda e^{\lambda t}\mathbf v\),右邊 \(A(e^{\lambda t}\mathbf v) = e^{\lambda t}A\mathbf v = e^{\lambda t}\lambda\mathbf v\) ✓。
上面的 \(A\):特徵方程 \(\lambda^2 + 4\lambda + 3 = (\lambda+1)(\lambda+3) = 0\),所以 \(\lambda_1 = -1\)、\(\lambda_2 = -3\)。
\(\lambda_1 = -1\):\(A + I = \begin{bmatrix}-1&1\\1&-1\end{bmatrix}\),要求 \(v_1 = v_2\),取 \(\mathbf v_1 = (1, 1)\)。
\(\lambda_2 = -3\):\(A + 3I = \begin{bmatrix}1&1\\1&1\end{bmatrix}\),要求 \(v_1 = -v_2\),取 \(\mathbf v_2 = (1, -1)\)。
沿 \((1,1)\) 方向,\(\dot x = -2x + x = -x\),確實以 \(e^{-t}\) 衰減;沿 \((1,-1)\) 方向(\(y = -x\)),\(\dot x = -2x - x = -3x\),以 \(e^{-3t}\) 衰減。
第三步:其他起點怎麼辦?拆開再加起來
起點不一定在特徵方向上,但線性系統有一個關鍵性質:兩個解相加還是解。如果 \(\dot{\mathbf a} = A\mathbf a\)、\(\dot{\mathbf b} = A\mathbf b\),則
$$\frac{d}{dt}(\mathbf a + \mathbf b) = A\mathbf a + A\mathbf b = A(\mathbf a + \mathbf b)$$所以做法是:
- 把起點拆成兩個特徵向量的組合:\(\mathbf x(0) = c_1\mathbf v_1 + c_2\mathbf v_2\)。
- 每一部分各自依第二步演化。
- 加起來:
同一個 \(A\),起點 \((1, 0)\)。拆解:\((1, 0) = \tfrac12(1, 1) + \tfrac12(1, -1)\),所以 \(c_1 = c_2 = \tfrac12\)。
$$\mathbf x(t) = \tfrac12e^{-t}\begin{bmatrix}1\\1\end{bmatrix} + \tfrac12e^{-3t}\begin{bmatrix}1\\-1\end{bmatrix}$$也就是 \(x(t) = \tfrac12(e^{-t} + e^{-3t})\)、\(y(t) = \tfrac12(e^{-t} - e^{-3t})\)。
驗算 \(\dot x = -2x + y\)。左邊:\(\tfrac12(-e^{-t} - 3e^{-3t})\)。右邊:\(-(e^{-t} + e^{-3t}) + \tfrac12(e^{-t} - e^{-3t})\),合併後是 \(-\tfrac12e^{-t} - \tfrac32e^{-3t}\),和左邊相等 ✓。
Demo B5 · 把起點拆成兩個特徵方向
為什麼只要看兩個特徵值,就知道整張相圖
現在可以回答這個問題了。一般解告訴我們,任何一條軌跡都只是 \(e^{\lambda_1t}\) 和 \(e^{\lambda_2t}\) 這兩個數字的組合,不同的起點只是改變 \(c_1, c_2\)。所以兩個特徵值的正負就決定了所有軌跡的共同命運:
| 特徵值 | 相圖 | 為什麼 | 例子 |
|---|---|---|---|
| 兩個負實數 | 穩定節點 | \(e^{\lambda t}\) 都衰減,所有軌跡進入原點 | DDPM 前向 SDE 的 drift \(-\tfrac12\beta\mathbf x\) |
| 兩個正實數 | 不穩定節點 | 都放大,所有軌跡離開原點 | Demo B5 第三個矩陣 |
| 一正一負 | 鞍點 | 一個方向縮小、一個方向放大 | Demo B3 的鞍點 |
| 複數,實部負 | 螺旋收斂 | 邊轉邊衰減(見下) | 阻尼振盪 |
| 複數,實部正 | 螺旋發散 | 邊轉邊放大 | |
| 純虛數 | 中心 | 只轉不縮 | 無阻尼振盪 |
這也解釋了長期行為:時間久了,\(e^{\lambda t}\) 中 \(\lambda\) 最大的那一項會壓過其他項,粒子的方向會貼近對應的特徵向量。
特徵值是複數時:為什麼是旋轉
第 5 節的旋轉 \(A = \begin{bmatrix}0&-1\\1&0\end{bmatrix}\) 特徵方程是 \(\lambda^2 + 1 = 0\),特徵值 \(\pm i\),也沒有實數的特徵方向,符合「每個方向都會轉彎」。更一般地看:
$$A = \begin{bmatrix}\sigma&-\omega\\\omega&\sigma\end{bmatrix},\qquad\lambda = \sigma\pm i\omega$$它的解是(可以代回去驗算):
$$\begin{aligned}x(t) &= e^{\sigma t}(x_0\cos\omega t - y_0\sin\omega t)\\y(t) &= e^{\sigma t}(x_0\sin\omega t + y_0\cos\omega t)\end{aligned}$$實部 \(\sigma\) 決定半徑怎麼變,虛部 \(\omega\) 決定旋轉速度。這和指數函數一致:由 Euler 公式 \(e^{i\omega t} = \cos\omega t + i\sin\omega t\),所以 \(e^{(\sigma + i\omega)t} = e^{\sigma t}(\cos\omega t + i\sin\omega t)\),複數指數本來就同時包含了放大和旋轉。
Demo B6 · 線性系統的相圖
- 由 \(\lambda = \frac12(\operatorname{tr}\pm\sqrt{\operatorname{tr}^2 - 4\det})\),拋物線 \(\det = \operatorname{tr}^2/4\) 以上根號裡是負的,特徵值是複數(旋轉);以下是實數。
- \(\det \lt 0\) 時兩個特徵值一正一負(鞍點),因為行列式是特徵值的積。
- \(\det > 0\) 時,\(\operatorname{tr} \lt 0\) 穩定、\(\operatorname{tr} > 0\) 不穩定,因為 trace 是特徵值的和。
矩陣指數:把解寫成一個式子
一維的解是 \(x(t) = e^{at}x(0)\)。多維能不能也寫成 \(\mathbf x(t) = e^{tA}\mathbf x(0)\)?可以,只要定義「矩陣的指數」。普通指數的級數是 \(e^{y} = 1 + y + \frac{y^2}{2!} + \cdots\),把 \(y\) 換成 \(tA\),1 換成單位矩陣:
$$e^{tA} = I + tA + \frac{(tA)^2}{2!} + \frac{(tA)^3}{3!} + \cdots$$逐項對 \(t\) 微分,會得到 \(\frac{d}{dt}e^{tA} = A\,e^{tA}\),和一維完全一樣,所以 \(e^{tA}\mathbf x(0)\) 確實是解。
它和上面的一般解是同一件事。如果 \(\mathbf v\) 是特徵向量,\(A^k\mathbf v = \lambda^k\mathbf v\),代入級數:
$$\begin{aligned}e^{tA}\mathbf v &= \Big(1 + t\lambda + \frac{(t\lambda)^2}{2!} + \cdots\Big)\mathbf v\\&= e^{\lambda t}\mathbf v\end{aligned}$$實際上,矩陣指數最常用的算法就是先拆成特徵方向,每個方向乘上自己的 \(e^{\lambda t}\),再加回來。
小練習:\(A = \begin{bmatrix}1&0\\0&-2\end{bmatrix}\),起點 \((1, 1)\)。寫出解。這是哪一種相圖?
08Euler 法:讓電腦解 ODE
為什麼需要它
速度場是神經網路時沒有公式解,只能用電腦一步一步走。CS236 的取樣,本質上就是在數值解一個 ODE 或 SDE。
方法
第 3 節的表格其實已經用了這個方法:把時間切成長度 \(h\) 的小段,每段都假設速度不變。
它就是一階 Taylor 展開(補充課 A 第 1 節):\(\mathbf x(t + h)\approx\mathbf x(t) + h\,\dot{\mathbf x}(t)\),丟掉了 \(O(h^2)\) 的項。
誤差有多大
- 每一步丟掉 \(O(h^2)\) 的誤差,這叫局部誤差。
- 走到固定時間 \(T\) 要 \(T/h\) 步。誤差大致累積起來:\(\frac{T}{h}\times O(h^2) = O(h)\),這叫全域誤差。
所以步數加倍(\(h\) 減半),最後的誤差大約只減半。全域誤差是 \(O(h)\) 的方法叫一階方法。第 3 節的表格可以驗證:\(t = 10\) 的誤差在 \(h = 1\) 時是 \(36.79 - 34.87 = 1.92\),\(h = 0.5\) 時是 \(0.94\),大約減半。
一個看得到誤差的例子:繞圈
第 5 節的 \(\dot x = -y,\ \dot y = x\),精確解是單位圓,半徑永遠是 1。Euler 的一步是:
$$\begin{aligned}x_{n+1} &= x_n - hy_n\\y_{n+1} &= y_n + hx_n\end{aligned}$$算新的半徑平方,交叉項會互相抵銷:
$$\begin{aligned}&x_{n+1}^2 + y_{n+1}^2\\={}&(x_n - hy_n)^2 + (y_n + hx_n)^2\\={}&(1 + h^2)(x_n^2 + y_n^2)\end{aligned}$$半徑每步乘上 \(\sqrt{1 + h^2} > 1\)。切線永遠指向圓外,所以每一步都走到圓外一點,誤差只會累積,不會抵銷。繞一圈用 \(N = 12\) 步時,\(h = 2\pi/12\),半徑變成 \((1 + h^2)^{6}\approx4.28\) 倍。
Demo B7 · 繞圈的 ODE:Euler 會越繞越外面
小練習:\(\dot x = -2x\),\(x(0) = 3\),步長 \(0.25\)。用 Euler 算到 \(t = 0.5\),和精確值比較。
09Heun 與 RK4:多看幾眼速度場
換個角度看:解 ODE 就是估計面積
把 ODE 兩邊從 \(t\) 積分到 \(t + h\),就得到完全精確的式子:
$$\mathbf x(t + h) = \mathbf x(t) + \int_t^{t+h}\mathbf v(\mathbf x(s), s)\,ds$$積分就是速度曲線下的面積,所以每種解法的差別,只在於怎麼估計這塊面積。這和微積分裡的數值積分是同一回事:
但有一個困難:要知道終點的速度,得先知道終點的位置,而那正是我們要算的東西。解決的辦法是:先用便宜的方法試走一步,用試走的位置去看速度。
Heun 法(改良的 Euler,二階)
梯形的面積是兩端速度的平均乘上 \(h\):
$$\begin{aligned}\mathbf k_1 &= \mathbf v(\mathbf x_n, t_n)\\\mathbf k_2 &= \mathbf v(\mathbf x_n + h\mathbf k_1,\ t_n + h)\\\mathbf x_{n+1} &= \mathbf x_n + \frac h2(\mathbf k_1 + \mathbf k_2)\end{aligned}$$\(\mathbf k_1\) 是起點的速度。\(\mathbf k_2\) 是用 Euler 試走一步之後,在那裡看到的速度。最後用兩者的平均,從起點重新走一步。
為什麼 Heun 的全域誤差是 \(O(h^2)\)
只看 \(\dot x = v(x)\) 的一維情況。精確解的二階 Taylor 展開是 \(x(t+h) = x + hv + \tfrac12h^2\ddot x + O(h^3)\),而由連鎖律 \(\ddot x = \frac{d}{dt}v(x(t)) = v'v\)。
Heun 的 \(k_2 = v(x + hv)\approx v + hv'v\),所以一步是 \(x + \frac h2(2v + hv'v) = x + hv + \tfrac12h^2v'v\)。和精確解相同,一直到 \(h^2\) 項都對,局部誤差是 \(O(h^3)\),累積後全域誤差是 \(O(h^2)\)。
RK4(四階 Runge–Kutta)
多試幾個位置,在頭、中、中、尾各看一次速度,再加權平均:
$$\begin{aligned}\mathbf k_1 &= \mathbf v(\mathbf x_n,\ t_n)\\\mathbf k_2 &= \mathbf v(\mathbf x_n + \tfrac h2\mathbf k_1,\ t_n + \tfrac h2)\\\mathbf k_3 &= \mathbf v(\mathbf x_n + \tfrac h2\mathbf k_2,\ t_n + \tfrac h2)\\\mathbf k_4 &= \mathbf v(\mathbf x_n + h\mathbf k_3,\ t_n + h)\\\mathbf x_{n+1} &= \mathbf x_n + \frac h6(\mathbf k_1 + 2\mathbf k_2 + 2\mathbf k_3 + \mathbf k_4)\end{aligned}$$權重 \(1, 2, 2, 1\) 從哪裡來?如果速度只和時間有關,\(\mathbf k_2 = \mathbf k_3\),公式就變成 \(\frac h6(\mathbf k_1 + 4\mathbf k_2 + \mathbf k_4)\),這正是微積分學過的 Simpson 法則(用拋物線估計面積)。一般情況下全域誤差是 \(O(h^4)\),證明要展開很多項,這裡不推導,下面的 demo 會直接量出來。
\(\dot x = -x\),\(x_0 = 1\),\(h = 0.5\)。精確值 \(e^{-0.5} = 0.60653\)。
Euler:\(1 + 0.5(-1) = 0.5\),誤差 \(0.107\)。
Heun:\(k_1 = -1\)。試走到 \(1 + 0.5(-1) = 0.5\),所以 \(k_2 = -0.5\)。\(x_1 = 1 + \frac{0.5}{2}(-1.5) = 0.625\),誤差 \(0.018\)。
RK4:
- \(k_1 = -1\)
- \(k_2 = -(1 - 0.25\cdot1) = -0.75\)
- \(k_3 = -(1 - 0.25\cdot0.75) = -0.8125\)
- \(k_4 = -(1 - 0.5\cdot0.8125) = -0.59375\)
括號裡是 \(-1 - 1.5 - 1.625 - 0.59375 = -4.71875\),所以 \(x_1 = 1 - \frac{0.5}{6}\times4.71875 = 0.60677\),誤差 \(0.00024\)。
比較時要看 NFE
Heun 每步算 2 次速度場,RK4 算 4 次。在 diffusion model 裡,算一次速度場就是跑一次神經網路,這是最花時間的部分,叫做一次 NFE(number of function evaluations)。所以比較解法時要看「同樣的 NFE 下誰比較準」,而不是同樣的步數。
| 方法 | 每步 NFE | 全域誤差 | 步數加倍,誤差變成 |
|---|---|---|---|
| Euler | 1 | \(O(h)\) | \(1/2\) |
| Heun | 2 | \(O(h^2)\) | \(1/4\) |
| RK4 | 4 | \(O(h^4)\) | \(1/16\) |
Demo B8 · 誤差隨步數下降的速度(log–log 圖)
- Karras et al. (2022) 的 EDM 用 Heun 解 diffusion 的 ODE,在 35 次左右的 NFE 達到很好的品質(出處見延伸閱讀)。
- 實務上還會自動調整步長:在速度場變化快的地方走小步、平緩的地方走大步(例如 RK45 / dopri5)。第 14 講用 ODE 算 likelihood,Song et al. 用的就是這種求解器。
Picard 迭代:同時猜整段軌跡再修正
本節開頭的積分式還能這樣用:先猜整段軌跡(例如全部等於起點),代入右邊的積分,得到一條新的軌跡,再代入,反覆做。這叫 Picard 迭代。因為每次都可以同時算所有時間點的速度,所以能平行計算。第 17 講的 ParaDiGMS 就是這個想法。
小練習:\(\dot x = x\),\(x_0 = 1\),\(h = 0.1\)。用 Heun 走一步,和 \(e^{0.1}\) 比較。
10Stiffness:為什麼 Euler 步長太大會爆掉
測試方程
回到最簡單的 \(\dot x = -\lambda x\)(\(\lambda > 0\))。精確解 \(e^{-\lambda t}\) 永遠平穩地衰減到 0,這個方程本身非常穩定。但 Euler 的一步是:
$$x_{n+1} = x_n + h(-\lambda x_n) = (1 - h\lambda)\,x_n$$每步乘上 \(1 - h\lambda\),所以 \(x_n = (1 - h\lambda)^nx_0\)。會發生什麼,完全看這個係數:
| \(h\lambda\) | 係數 \(1 - h\lambda\) | \(x_0, x_1, x_2, x_3, \dots\) | 行為 |
|---|---|---|---|
| 0.5 | 0.5 | 1, 0.5, 0.25, 0.125 | 平順衰減 |
| 1 | 0 | 1, 0, 0, 0 | 一步到 0 |
| 1.5 | −0.5 | 1, −0.5, 0.25, −0.125 | 上下振盪,但會衰減 |
| 2.5 | −1.5 | 1, −1.5, 2.25, −3.375 | 越振越大,爆掉 |
為什麼會這樣?速度正比於 \(x\) 且 \(\lambda\) 很大時,一步會走太遠,直接越過 0 衝到另一邊,而且衝得比原來還遠。精確解是一路減速地靠近 0,但 Euler 假設速度不變,所以煞車不及。
什麼是 stiff
上面的例子解本身也變化很快,用小步長好像理所當然。真正麻煩的是下面這種情況:
$$\frac{dx}{dt} = -\lambda\,(x - \cos t),\qquad\lambda\text{ 很大}$$規則是「不論現在在哪裡,都被很快地拉向 \(\cos t\)」。解很快就貼上 \(\cos t\),之後變化非常平順,看起來用大步長就夠了。但 Euler 的一步是:
$$x_{n+1} = (1 - h\lambda)x_n + h\lambda\cos t_n$$係數還是 \(1 - h\lambda\)。只要 \(h\lambda > 2\),和 \(\cos t\) 的誤差就會每步放大。解明明很平順,步長卻被一個早就結束的快速過程綁住,這種情況就叫 stiff。多維系統也一樣:特徵值中最大的 \(|\lambda|\) 決定 Euler 能用多大的步長,就算那個方向的分量早就衰減完了。
第 3 節的 Demo B1 已經看過一半的現象:\(kh > 1\) 時一步衝過 0,變成負的。補充課 F 的 Langevin 取樣也有同樣的步長限制。
小練習:\(\dot x = -100x\)。Euler 最大能用多大的步長?
11指數積分器:把好解的部分精確解掉,以及 DDIM
想法
Stiff 的麻煩來自 \(-\lambda x\) 這一項,但它正好是我們會精確解的(第 3 節)。那能不能把這部分精確解掉,只對剩下的部分做近似?這類方程叫半線性(semilinear):
$$\frac{dx}{dt} = -\lambda x + g(t)$$一個線性項,加上一個其他的東西 \(g\)。上一節的例子就是 \(g(t) = \lambda\cos t\)。
積分因子:一步一步解
直接分離變數行不通,因為右邊有兩項。關鍵的技巧是換一個變數,讓線性項消失。定義
$$u(t) = e^{\lambda t}x(t)$$也就是用「精確解的衰減速度」把 \(x\) 放大回來。對 \(u\) 微分,用乘積法則:
$$\frac{du}{dt} = \lambda e^{\lambda t}x + e^{\lambda t}\frac{dx}{dt}$$把 ODE 代入 \(\frac{dx}{dt}\):
$$\frac{du}{dt} = \lambda e^{\lambda t}x + e^{\lambda t}\big(-\lambda x + g(t)\big)$$前後兩個 \(\lambda e^{\lambda t}x\) 剛好抵銷:
$$\frac{du}{dt} = e^{\lambda t}g(t)$$\(x\) 不見了!右邊只有 \(t\),所以這是第 2 節的情況,直接積分就好。\(e^{\lambda t}\) 叫積分因子。從 \(t_n\) 積到 \(t_n + h\):
$$\begin{aligned}&e^{\lambda(t_n + h)}x(t_n + h) - e^{\lambda t_n}x(t_n)\\={}&\int_{t_n}^{t_n + h}e^{\lambda s}g(s)\,ds\end{aligned}$$兩邊除以 \(e^{\lambda(t_n + h)}\):
第一項是線性部分的精確解,第二項是 \(g\) 累積的影響,而且越早的貢獻衰減得越多。
唯一的近似
\(g\) 一般沒辦法積分(它可能是神經網路),所以假設它在這一小段內是常數 \(g(t_n)\)。積分就能算了:
$$\int_{t_n}^{t_n + h}e^{-\lambda(t_n + h - s)}\,ds = \frac{1 - e^{-\lambda h}}{\lambda}$$這個式子有很好的解讀。\(g\) 固定時,\(x\) 的平衡點(速度為 0 的位置)是 \(g/\lambda\),也就是「目標」。令 \(w = e^{-\lambda h}\),更新式就是
$$x_{n+1} = w\,x_n + (1 - w)\,\frac{g}{\lambda}$$\(w\) 永遠在 0 和 1 之間,所以 \(x_{n+1}\) 永遠是現在位置和目標的加權平均,一定落在兩者之間,不可能衝過頭。不論 \(h\) 多大都不會爆。把 \(g(t) = \lambda\cos t\) 代入,就是 \(x_{n+1} = e^{-\lambda h}x_n + (1 - e^{-\lambda h})\cos t_n\)。
\(\dot x = -10x + 10\),\(x_0 = 0\),步長 \(h = 0.25\)(\(h\lambda = 2.5\))。目標是 \(g/\lambda = 1\),精確解是 \(1 - e^{-10t}\)。
| 步 | 精確 | Euler | 指數積分器 |
|---|---|---|---|
| 1 | 0.918 | 2.5 | 0.918 |
| 2 | 0.993 | −1.25 | 0.993 |
| 3 | 0.999 | 4.375 | 0.999 |
| 4 | 1.000 | −4.0625 | 1.000 |
Euler 每步:\(x_1 = 0 + 0.25(10) = 2.5\),接著 \(x_2 = 2.5 + 0.25(-25 + 10) = -1.25\)。指數積分器每步:\(w = e^{-2.5} = 0.0821\),\(x_1 = 0.0821\cdot0 + 0.9179\cdot1 = 0.918\)。這裡 \(g\) 真的是常數,所以它和精確解完全相同。
Demo B9 · 同一個 stiff ODE:Euler vs. 指數積分器
把 \(g\) 用更高次的多項式近似(不只是常數),就得到高階的指數積分器。
和 DDIM 的關係
現在可以看懂第 17 講投影片 33「exponential integrator (semi-linear ODE)」的意思了。VP diffusion 的 probability flow ODE 正好是半線性的:
$$\frac{d\mathbf x}{dt} = -\tfrac12\beta(t)\mathbf x + (\text{含神經網路的部分})$$| 本節 | diffusion |
|---|---|
| 線性項 \(-\lambda x\) | \(-\tfrac12\beta(t)\mathbf x\),可以精確解 |
| 其他部分 \(g(t)\) | 含神經網路的部分,只能近似 |
| 積分因子 \(e^{\lambda t}\) | 因為 \(\beta\) 隨時間改變,換成 \(\exp\big(\tfrac12\int\beta\,dt\big)\),步驟相同 |
在 \(t\) 接近 0 時 \(\beta\) 變化很劇烈,直接用 Euler 需要很小的步長。DDIM 等於把線性部分精確解掉、只對神經網路的部分做近似;後來的 DPM-Solver、DEIS 把它推廣成高階的指數積分器。這是 DDIM 只要 10–50 步的主要原因之一。另外,第 17 講 Demo A 把步數集中在雜訊小的尾段(二次間隔),也是在處理同一件事:在變化快的地方多走幾步。
出處:Lai et al. (2026) 附錄 A.1.3「Semilinear ODEs and Exponential Integration Factors」;第 17 講頁面 §3「DDIM 為什麼是一個好的 ODE 解法」。
小練習:第 3 節提到 \(\frac{dx}{dt} = \sin(2t) - x\) 無法分離變數。用積分因子解它的第一步:\(u = ?\),\(\frac{du}{dt} = ?\)
12在 CS236 哪裡用到
| 概念 | 出現的地方 |
|---|---|
| 速度場推動粒子 | 第 14 講的 probability flow ODE、第 16 講「ODE 把 VAE 變成 flow」、flow matching |
| 解唯一、軌跡不交叉 → 可逆 | 第 14、17 講:diffusion 的 ODE 是一個 normalizing flow,可以精確算 likelihood(補充課 C) |
| 線性 ODE、矩陣指數 | 第 18 講的 \(e^{tQ}\);VP / VE SDE 的閉式 \(q(\mathbf x_t\mid\mathbf x_0)\) |
| Euler、Heun、RK、NFE | 第 16–17 講:DDPM 是反向 SDE 的 Euler–Maruyama、DDIM、Heun(EDM)、自適應步長的 likelihood 計算 |
| 指數積分器、stiffness | 第 17 講的 DDIM、DPM-Solver、二次時間間隔 |
| Picard 迭代 | 第 17 講的平行求解 ParaDiGMS |
常見誤解
自我測驗
1. \(\dot x = -2x\),\(x(0) = 3\)。\(x(1)\) 是多少?用 Euler、步長 0.5 算兩步得到多少?
2. 為什麼兩條 ODE 軌跡不能交叉?這對 diffusion model 有什麼用?
3. \(\dot{\mathbf x} = A\mathbf x\),\(A = \begin{bmatrix}1&2\\0&-1\end{bmatrix}\)。特徵值是什麼?相圖是哪一種?
4. 上一題從 \(\mathbf v = (1, 0)\) 出發的解是什麼?
5. 某解法把步數加倍後誤差變成 1/4。它是幾階?RK4 呢?
6. 為什麼 DDIM 這類方法可以用很大的步長?
延伸閱讀
- Lai et al. (2026) 附錄 A.1:ODE 的直覺、存在唯一性與「解不交叉」、半線性 ODE 的指數積分因子、數值解法(Euler、Runge–Kutta、Heun、Adams–Bashforth、Picard 迭代)。
- Karras et al. (2022), Elucidating the Design Space of Diffusion-Based Generative Models(EDM):用 Heun 解 diffusion 的 ODE。
- Lu et al. (2022), DPM-Solver:diffusion ODE 的高階指數積分器。
- Holderrieth & Erives (2026) 第 2 章:flow model 就是用神經網路當速度場的 ODE。