03.1 向量場與梯度場#
本節目標#
多變數微積分的核心不再是「一個數對一個數」,而是「場對場」。本節要重建你對以下概念的直覺:
- 什麼是向量場(vector field):空間中每一點都掛上一個向量。
- 什麼是梯度 \(\nabla f\) :純量場爬坡最快的方向與坡度。
- 方向導數:沿任意方向量測變化率。
- 幾何黃金律:梯度必正交於等位面。
- 用 SymPy 做符號微分,用 matplotlib
streamplot視覺化向量場。
3.1.1 向量場:空間中的箭頭海洋#
純量場像「氣溫地圖」:每一點給一個數。 向量場像「風速地圖」:每一點給一個箭頭。數學上是映射
直覺例子:
- 重力場 \(\mathbf{g} = (0,0,-9.8)\) :處處指向地心,均勻場。
- 點電荷電場 \(\mathbf{E} \propto \dfrac{\mathbf{r}}{\|\mathbf{r}\|^3}\) :由中心向外放射,放射場。
- 旋轉流 \(\mathbf{F} = (-y, x)\) :繞原點打轉,渦旋場。
用 matplotlib 畫出來看,是建立直覺最快的方式:
import numpy as np
import matplotlib.pyplot as plt
x, y = np.meshgrid(np.linspace(-3, 3, 20), np.linspace(-3, 3, 20))
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
axes[0].quiver(x, y, x, y) # 放射場 F=(x,y)
axes[1].quiver(x, y, -y, x) # 渦旋場 F=(-y,x)
axes[2].quiver(x, y, 0, -2.0) # 均勻重力場
for ax, t in zip(axes, ["放射場", "渦旋場", "均勻場"]):
ax.set_title(t); ax.set_aspect("equal")
plt.show()
每個箭頭畫在「該點」上,箭頭方向就是該點的場向量。看圖時要訓練自己問:箭頭從哪裡湧出?在哪裡匯聚?有沒有打轉?——這正是下一節散度與旋度的伏筆。
3.1.2 梯度:最陡上升方向#
設純量場 \(f(x,y)\) 可微。在點 \((x_0,y_0)\) 附近,函數沿方向 \(\mathbf{u}\) (單位向量)的變化率是方向導數:
其中梯度向量定義為偏導數排成的向量:
由內積不等式 \(\nabla f \cdot \mathbf{u} \le \|\nabla f\|\,\|\mathbf{u}\| = \|\nabla f\|\) ,等號當且僅當 \(\mathbf{u}\) 與 \(\nabla f\) 同向。所以:
梯度 = 變化最快的方向,其長度 = 最大的方向導數值(最大坡度)。 沿 \(-\nabla f\) 則是下降最快(這是梯度下降法的根據)。
幾何驗證小實驗: \(f = x^2 + y^2\) 在點 \((1,1)\) 的梯度是 \((2,2)\) 。從該點走一步 \(\mathbf{u} = \frac{1}{\sqrt 2}(1,1)\) 得 \(f\) 增加約 \(2\sqrt2 \cdot h\) ;走 \((1,-1)/\sqrt2\) 幾乎不變(方向 \((-1,1)\) 恰是等位線 \(x^2+y^2=2\) 的切線方向)。這不是巧合,見下一小節。
3.1.3 等位面正交於梯度#
等位線(等位面)是 \(f = c\) 的集合。沿著等位線走, \(f\) 不變,所以方向導數為 \(0\) :
其中 \(\mathbf{t}\) 是等位線切向。梯度與切向內積為零 ⇒ 梯度是等位面的法向。
登山的比喻最傳神:等高線上走不費力(高度不變),垂直等高線走最耗力(坡度最大)。地形圖上一組一組的等高線,其間距越密坡度越陡——梯度大小就藏在「密度」裡。
3.1.4 SymPy 符號計算梯度#
SymPy 中最直接的方式是把偏導數排成矩陣(Jacobian),或用 derive_by_list / Matrix.diff:
import sympy as sp
x, y, z = sp.symbols("x y z")
f = x**2 + y**2
grad_f = [sp.diff(f, v) for v in (x, y)]
print(grad_f) # [2*x, 2*y]
# 用 Matrix.diff(Jacobian,一行列表一次算完)
g = x*y*sp.sin(z)
J = sp.Matrix([g]).diff(sp.Matrix([x, y, z])).T
print(J) # Matrix([[y*sin(z), x*sin(z), x*y*cos(z)]])
接著驗證「梯度 ⟂ 等位面」:取等位線上任一點,構造切向量,檢查內積為零:
f = x**2 + y**2
grad = sp.Matrix([2*x, 2*y])
# 等位面 f=c 上的切向是隱函數微分:df = 2x dx + 2y dy = 0
# 切向量 t 滿足 grad · t = 0,例如在 (x,y) 平面取 t = (-2y, 2x)
t = sp.Matrix([-2*y, 2*x])
print(sp.simplify(grad.dot(t))) # 0
3.1.5 動手實驗:梯度場與等位線疊圖#
把 \(f = x^2 + y^2\) 的梯度場(箭頭)畫在等位線(同心圓)上。你會看到箭頭處處垂直穿透圓圈:
import numpy as np
import matplotlib.pyplot as plt
x, y = np.meshgrid(np.linspace(-3, 3, 20), np.linspace(-3, 3, 20))
fval = x**2 + y**2
gx, gy = 2*x, 2*y
plt.figure(figsize=(6, 6))
plt.contour(x, y, fval, levels=[0.5, 1, 2, 3, 4, 6, 8], cmap="Blues")
plt.streamplot(x, y, gx, gy, color="crimson", density=0.8)
plt.title("f = x^2 + y^2 : 梯度場( strm ) 疊 等位線( contour )")
plt.gca().set_aspect("equal")
plt.show()
換一個更有趣的場試試: \(f = \sin(x)\cos(y)\) 的梯度場是 \((\cos x \cos y,\ -\sin x \sin y)\) 。把上面程式改成這組,觀察箭頭是否依然垂直穿越等位線,以及「山頂/盆地」(梯度為零的臨界點)會把流線分流或匯聚。
再進一步:用 streamplot 觀察與梯度反方向的流( \(-\nabla f\) ),它會像水往低處流一樣匯入局部極小點——這正是最陡下降法在連續世界裡的原本樣貌:
plt.streamplot(x, y, -gx, -gy, color="seagreen", density=0.8)
3.1.6 三維推廣#
三維時等位面變成曲面,梯度仍是法向量。對 \(f = x^2 + y^2 + z^2\) , \(\nabla f = (2x,2y,2z)\) 恰好由球心向外,正交於每一個球面——球面是等位面 \(r^2 = c\) ,法向就是徑向。
x, y, z = sp.symbols("x y z")
f = x**2 + y**2 + z**2
print([sp.diff(f, v) for v in (x, y, z)]) # [2*x, 2*y, 2*z]
小結與練習#
- 向量場是每點一個向量的映射;純量場是每點一個數。
- \(\nabla f\) 指向最陡上升, \(\|\nabla f\|\) 是最大方向導數, \(-\nabla f\) 下降最快。
- \(\nabla f \perp\) 等位面;等位線密 ⇒ 梯度大。
- SymPy:把偏導數排成列表
derive_by_list,或Matrix([...]).diff(...)。
練習:
- 求 \(f = x^3 - 3xy^2\) 的梯度,在點 \((1,1)\) 處沿方向 \(\mathbf{u} = \frac{1}{\sqrt3}(1,1,\sqrt{1})=(1,1)/\sqrt2\) 的方向導數為何?哪個方向變化率為零?
- 畫 \(f = x^2 - y^2\) 的等位線與梯度場疊圖。這是鞍點地形,描述流線在 \((0,0)\) 附近的行為。
- 證明:若 \(\|\nabla f\|\) 在某恆為常數 \(k>0\) ,且 \(f\) 可微,則沿著等高線走一段長 \(L\) 的弧線, \(f\) 值變化應該是 \(0\) ;沿垂直等高線走 \(L\) ,變化至多為 \(kL\) 。
- 用 streamplot 畫 \(-\nabla f\) ( \(f=xy(x+y)\) ),找出所有匯聚點並與 \(\nabla f = 0\) 的解對照。