09.1 多變數微積分#
本節目標#
- 理解偏導數的數學意義,並用
diff(f, x)對多變數函數求偏導 - 學會求梯度、解聯立 \(f_x = f_y = 0\) 找出臨界點
- 用 Hessian 矩陣判別極大值、極小值與鞍點
- 以符號方式推導 Lagrange 乘數法,處理約束極值問題
- 用嵌套
integrate計算雙重積分 - 動手實驗:畫出 3D 曲面與等高線圖
偏導數的概念#
對多變數函數 \(f(x, y)\) 而言,偏導數 \(\dfrac{\partial f}{\partial x}\) 是「把其他變數當常數,只對 \(x\) 微分」的結果。例如:
在 SymPy 中,diff 的第二個之後的參數指定「對哪個變數」微分:
from sympy import symbols, diff, sin
x, y = symbols('x y')
f = x**2*y + sin(x*y)
print(diff(f, x)) # 2*x*y + y*cos(x*y)
print(diff(f, y)) # x**2 + x*cos(x*y)
print(diff(f, x, 2)) # 對 x 的二階偏導:2*y - y**2*sin(x*y)
print(diff(f, x, y)) # 混合偏導:2*x - x*y*sin(x*y) + cos(x*y)
梯度與極值:solve 聯立 f_x = f_y = 0#
梯度定義為所有偏導數組成的向量:
極值候補點(臨界點)就是梯度為零的地方。用 solve 解聯立方程 \(f_x = 0\) 且 \(f_y = 0\) :
from sympy import symbols, diff, solve
x, y = symbols('x y')
f = x**3 - 3*x + y**2 # 經典例子:有明顯的極值結構
fx = diff(f, x) # 3*x**2 - 3
fy = diff(f, y) # 2*y
crit = solve([fx, fy], [x, y])
print(crit) # [(-1, 0), (1, 0)]
Hessian 判別#
在臨界點 \(P\) 處,二階行為由 Hessian 矩陣決定:
判別規則(以兩變數為例):
- \(D > 0\) 且 \(f_{xx} > 0\) :局部極小值
- \(D > 0\) 且 \(f_{xx} < 0\) :局部極大值
- \(D < 0\) :鞍點
- \(D = 0\) :無法判斷
from sympy import symbols, diff, solve
x, y = symbols('x y')
f = x**3 - 3*x + y**2
fxx = diff(f, x, 2)
fyy = diff(f, y, 2)
fxy = diff(f, x, y)
crit = solve([diff(f, x), diff(f, y)], [x, y])
for px, py in crit:
D = fxx*fyy - fxy**2
Dv = D.subs({x: px, y: py})
fv = fxx.subs({x: px, y: py})
if Dv > 0:
kind = "極小值" if fv > 0 else "極大值"
elif Dv < 0:
kind = "鞍點"
else:
kind = "無法判斷"
print(f"({px}, {py}): D = {Dv}, f_xx = {fv} -> {kind}")
# (-1, 0): D = 12, f_xx = -6 -> 極大值
# (1, 0): D = 12, f_xx = 6 -> 極小值
也可以用矩陣形式直接建 Hessian 並求行列式:
from sympy import hessian
H = hessian(f, (x, y))
print(H.det()) # 與 fxx*fyy - fxy**2 相同
Lagrange 乘數法#
要在約束 \(g(x, y) = 0\) 下求 \(f(x, y)\) 的極值,引入乘數 \(\lambda\) ,解:
例子:在 \(x + y = 1\) 之下最大化 \(xy\) 。 這在幾何上是「周長固定的矩形,面積最大時是正方形」,我們用符號推導驗證:
from sympy import symbols, diff, solve, Rational
x, y, lam = symbols('x y lambda', real=True)
f = x*y
g = x + y - 1
# 聯立:f_x = lam*g_x, f_y = lam*g_y, g = 0
eqs = [
diff(f, x) - lam*diff(g, x), # y - lam
diff(f, y) - lam*diff(g, y), # x - lam
g,
]
sol = solve(eqs, [x, y, lam], dict=True)
print(sol) # [{x: 1/2, y: 1/2, lambda: 1/2}]
for s in sol:
print("最大值 f =", f.subs(s)) # 1/4
結果: \(x = y = \dfrac{1}{2}\) , \(xy = \dfrac{1}{4}\) ,正好是正方形。SymPy 完全用符號運算得出這個結論,沒有任何數值近似。
雙重積分#
計算
在 SymPy 中就是嵌套呼叫 integrate,先對內層變數積分:
from sympy import symbols, integrate
x, y = symbols('x y')
inner = integrate(x**2 + y**2, (x, 0, 2)) # 先對 x:2*y**2 + 8/3
result = integrate(inner, (y, 0, 1))
print(result) # 10/3
# 也可以一次寫完
print(integrate(x**2 + y**2, (x, 0, 2), (y, 0, 1))) # 10/3
注意順序:(x, 0, 2), (y, 0, 1) 表示先對 \(x\) 積到 2、再對 \(y\) 積到 1(內層在前)。
# 驗證:用極座標算圓盤上的積分
from sympy import pi
r, t = symbols('r theta', positive=True)
expr = (r**2) # x**2 + y**2 = r**2,面積元素為 r dr dt
print(integrate(expr*r, (r, 0, 1), (t, 0, 2*pi))) # pi/2
動手實驗:3D 曲面與等高線#
把 \(f(x, y) = x^3 - 3x + y^2\) 的曲面與等高線畫出來,觀察極大、極小與鞍點的位置:
import numpy as np
import matplotlib.pyplot as plt
X, Y = np.meshgrid(np.linspace(-2.5, 2.5, 200),
np.linspace(-2.5, 2.5, 200))
F = X**3 - 3*X + Y**2
fig = plt.figure(figsize=(12, 5))
# 3D 曲面
ax1 = fig.add_subplot(1, 2, 1, projection='3d')
ax1.plot_surface(X, Y, F, cmap='viridis', alpha=0.9)
ax1.set_title('$f(x,y) = x^3 - 3x + y^2$')
# 等高線(標出臨界點)
ax2 = fig.add_subplot(1, 2, 2)
cs = ax2.contour(X, Y, F, levels=20)
ax2.clabel(cs, fontsize=8)
ax2.plot(-1, 0, 'r*', markersize=14, label='極大值')
ax2.plot(1, 0, 'g*', markersize=14, label='極小值')
ax2.legend()
ax2.set_title('等高線圖')
plt.tight_layout()
plt.show()
等高線圖中,局部極大值周圍的等高線呈「封閉圈且內圈數值較大」,鞍點處等高線則呈交叉狀。你也可以把本節的 Lagrange 例子畫出來: \(xy = c\) 的等高線與直線 \(x + y = 1\) 相切之處就是極值點。
# Lagrange 幾何直覺:xy = 1/4 與 x + y = 1 相切於 (1/2, 1/2)
xv = np.linspace(0, 1, 200)
Xv, Yv = np.meshgrid(xv, xv)
plt.contour(Xv, Yv, Xv*Yv, levels=[0.1, 0.2, 0.25, 0.3])
plt.plot(xv, 1 - xv, 'r-', label='$x + y = 1$')
plt.plot(0.5, 0.5, 'ko')
plt.legend()
plt.gca().set_aspect('equal')
plt.show()
小結與練習#
本節重點
diff(f, x)求偏導數,diff(f, x, y)求混合偏導- 極值候補點由 \(\nabla f = 0\) 求得,用
solve解聯立方程 - Hessian 行列式 \(D\) 配合 \(f_{xx}\) 判別極值類型;
hessian(f, (x, y))可直接建矩陣 - Lagrange 乘數法:解 \(\nabla f = \lambda \nabla g\) 與 \(g = 0\)
- 雙重積分用嵌套
integrate,內層變數寫在前
練習
- 求 \(f(x, y) = x^2 + xy + y^2 - 3x\) 的所有臨界點並判別類型。
- 用 Lagrange 乘數法求:在 \(x^2 + y^2 = 1\) 之下, \(x + y\) 的最大值與最小值。
- 計算 \(\displaystyle\int_0^{\pi} \int_0^x \sin(x+y)\, dy\, dx\) ,並用數值積分(
integral.as_sum()或mpmath)驗證。 - 實驗:把 3D 圖中的函數換成 \(f(x, y) = x^2 - y^2\) ,確認原點是鞍點。