第 11 章 多元函数与偏导数
学习目标
- 理解二元函数及其几何意义
- 掌握偏导数的定义与计算
- 理解全微分与近似计算
- 理解方向导数与梯度
- 掌握多元链式法则
- 会用 PyTorch 计算偏导与梯度
11.1 二元函数:输入变成一对
前面研究的函数,输入是一个数 。可现实里很多量取决于两个或更多输入。比如:
- 房间里的温度 取决于位置:左右 、前后 ,;
- 山坡的海拔 取决于经纬度:;
- 机器的成本取决于产量和原料价格。
二元函数:对每一对输入 ,按照确定规则给出唯一输出 ,记作 。、 叫自变量, 叫因变量。
几何上,二元函数是一张曲面:在 平面上取一点 ,向上(或向下)量出高度 ,所有这样的点组成一张曲面。

import matplotlib.pyplot as plt
from matplotlib import font_manager
for f in font_manager.findSystemFonts():
if any(k in f for k in ("NotoSansCJK", "NotoSansSC", "wqy", "SimHei", "msyh", "PingFang")):
font_manager.fontManager.addfont(f)
plt.rcParams["font.sans-serif"] = ["Noto Sans CJK SC", "WenQuanYi Zen Hei", "SimHei", "Microsoft YaHei", "PingFang SC"]
plt.rcParams["axes.unicode_minus"] = False
import numpy as np
fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111, projection="3d")
x = np.linspace(-2, 2, 60)
y = np.linspace(-2, 2, 60)
X, Y = np.meshgrid(x, y)
Z = X ** 2 + Y ** 2
ax.plot_surface(X, Y, Z, cmap="viridis", alpha=0.9)
ax.contour(X, Y, Z, zdir="z", offset=0, cmap="viridis", alpha=0.5)
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.set_zlabel("z = f(x, y)")
ax.set_title("z = x² + y²:一张碗形曲面")
fig.savefig("book/public/figs/fig11-surface.png", dpi=120, bbox_inches="tight")
plt.close(fig)曲面上的「高度」可以用等高线压缩到平面:同一条等高线上的点,函数值相等,就像地图上的海拔线。
11.2 偏导数:固定一个变量,只看另一个
二元函数在一点有多「陡」?方向太多了:沿 方向、沿 方向、沿任何斜方向……所以先把方向限定为坐标轴方向。
偏导数:把 当作常数、只对 求导,得到 对 的偏导数;把 当作常数、只对 求导,得到对 的偏导数:
记号:、,或 、(偏导数用圆体 ,区别于一元导数 )。
求 的偏导数:
求偏导和一元求导完全一样,只是每次只动一个变量。验证:
import numpy as np
def f(x, y):
return x ** 2 * y
h = 1e-6
x, y = 2.0, 3.0
fx = (f(x + h, y) - f(x - h, y)) / (2 * h)
fy = (f(x, y + h) - f(x, y - h)) / (2 * h)
print("fx(2,3) 数值 ≈", fx, " 公式 2xy =", 2 * x * y)
print("fy(2,3) 数值 ≈", fy, " 公式 x² =", x ** 2)fx(2,3) 数值 ≈ 12.000000000789157 公式 2xy = 12.0
fy(2,3) 数值 ≈ 4.000000000559112 公式 x² = 4.011.3 偏导数的几何意义
的几何意义:在点 处,沿 轴方向切曲面一刀,得到一条截线,这条截线在 处的切线斜率就是 。 同理,是沿 轴方向截线的斜率。
换句话说:偏导数回答「只往东走,坡度是多少」「只往北走,坡度是多少」,两个方向分开看。
11.4 全微分
两个方向同时动一点,函数值变化多少?设 、 都很小,由「各自贡献相加」:
写成微分形式:
这叫全微分。它是一元微分「」的推广:每个自变量贡献一项「偏导数 × 自变量的变化」。
例:,在 处, 增加 0.01、 减少 0.02:
实际变化 ,与全微分近似 0.04 只差约 0.0005。
def f(x, y):
return x ** 2 * y
x, y = 2.0, 3.0
dx, dy = 0.01, -0.02
dz_approx = 2 * x * y * dx + x ** 2 * dy
dz_exact = f(x + dx, y + dy) - f(x, y)
print("全微分近似:", dz_approx)
print("实际变化 :", dz_exact)全微分近似: 0.039999999999999994
实际变化 : 0.0394979999999964811.5 方向导数与梯度
只沿坐标轴不够。任意方向 (单位向量)上的变化率,叫方向导数。可以证明:
把偏导数排成向量,得到梯度:
方向导数可以写成梯度与方向向量的点积:
由点积公式 ( 是两个向量的夹角),方向导数最大当 ,即 与 同向。所以:
梯度的方向是函数上升最快的方向;梯度的大小是这个方向的变化率。
这解释了为什么爬山要「对着最陡的方向走」,也预告了第 13 章机器学习里梯度的核心地位。

import matplotlib.pyplot as plt
from matplotlib import font_manager
for f in font_manager.findSystemFonts():
if any(k in f for k in ("NotoSansCJK", "NotoSansSC", "wqy", "SimHei", "msyh", "PingFang")):
font_manager.fontManager.addfont(f)
plt.rcParams["font.sans-serif"] = ["Noto Sans CJK SC", "WenQuanYi Zen Hei", "SimHei", "Microsoft YaHei", "PingFang SC"]
plt.rcParams["axes.unicode_minus"] = False
import numpy as np
x = np.linspace(-2, 2, 300)
y = np.linspace(-2, 2, 300)
X, Y = np.meshgrid(x, y)
Z = X ** 2 + Y ** 2
fig, ax = plt.subplots(figsize=(6.5, 5.5))
cs = ax.contour(X, Y, Z, levels=[0.5, 1, 2, 4, 6, 8], colors="tab:blue")
ax.clabel(cs, inline=True, fontsize=9)
# 梯度向量:指向外,即上升最快的方向
for px, py in [(-1.2, -1.2), (0, 1.3), (1.2, 0.8), (-0.6, 1.6), (1.4, -0.4)]:
gx, gy = 2 * px, 2 * py
scale = 0.18
ax.arrow(px, py, gx * scale, gy * scale,
head_width=0.08, color="tab:red", length_includes_head=True)
ax.annotate("梯度方向 = 上升最快", (0.4, -1.5), color="tab:red")
ax.set_xlim(-2.2, 2.2)
ax.set_ylim(-2.2, 2.2)
ax.set_aspect("equal")
ax.grid(True, linestyle=":", alpha=0.5)
ax.set_title("z = x² + y²:等高线与梯度(红色箭头)")
fig.savefig("book/public/figs/fig11-gradient.png", dpi=120, bbox_inches="tight")
plt.close(fig)import numpy as np
x, y = 1.0, 2.0
grad = np.array([2 * x, 2 * y])
u = np.array([1 / np.sqrt(2), 1 / np.sqrt(2)])
Du = np.dot(grad, u)
print("梯度 ∇f =", grad)
print("方向导数(沿 45° 方向) =", Du)梯度 ∇f = [2. 4.]
方向导数(沿 45° 方向) = 4.242640687119285沿梯度方向 的方向导数最大,是 。
11.6 多元链式法则
若 ,而 、 都随 变化,则 对 的变化率是两条路径贡献之和:
直觉:沿每条路径,「对 的敏感度 × 自身的变化」,两条路径加起来。这正是神经网络反向传播的雏形:损失函数对参数的导数,要沿着计算路径逐层相乘再相加(第 14 章展开)。
例:,,,则
11.7 用 PyTorch 计算梯度
PyTorch 的 backward() 自动算梯度,和手算一致:
import torch
x = torch.tensor(1.0, requires_grad=True)
y = torch.tensor(2.0, requires_grad=True)
z = x ** 2 + y ** 2
z.backward()
print("z =", z.item())
print("∂z/∂x =", x.grad.item())
print("∂z/∂y =", y.grad.item())z = 5.0
∂z/∂x = 2.0
∂z/∂y = 4.0常见错误
| 错误写法/理解 | 原因 |
|---|---|
| 求 时把 也当变量一起求导 | 偏导数的定义就是固定 、只动 |
| 把 与 混用 | 偏导数用 ,一元导数用 |
| 梯度方向当成「下降最快」 | 梯度是上升最快的方向;下降最快是负梯度方向 |
| 全微分漏掉某一项 | 有几个自变量就有几项,每项是「对应偏导 × 变化量」 |
| 把方向导数 里的 忘掉归一化 | 方向向量必须是单位向量,否则结果随长度变化 |
章末练习
基础
- 求 的 、。
- 求 的偏导数。
- 求 在 处的梯度。
提高
- 用全微分近似计算:在 处, 增加 0.02、 减少 0.01, 变化多少?
- 求 、、 的 。
挑战
- 证明方向导数 中,当 与 同向时取得最大值 。
- 用 PyTorch 求 在 、 处的梯度,并与手算比较。
章末自测
每题选择一个最佳答案。本书不附答案:完成后交由老师或 AI 老师批改讲解。
- 二元函数 的图像是?
- A. 一条曲线
- B. 一张曲面
- C. 一个平面点集
- D. 一根数轴
- 求 时,正确的做法是?
- A. 当常数,只对 求导
- B. 当常数,只对 求导
- C. 对 、 同时求导
- D. 先对 积分
- ,则 是?
- A.
- B.
- C.
- D.
- ,则 是?
- A.
- B.
- C.
- D.
- 偏导数的几何意义是?
- A. 曲面某方向的截线斜率
- B. 曲面面积
- C. 等高线长度
- D. 函数的最大值
- 全微分 等于?
- A.
- B.
- C.
- D.
- 梯度的方向是?
- A. 函数下降最快的方向
- B. 函数上升最快的方向
- C. 等高线方向
- D. 轴方向
- 在 处的梯度是?
- A.
- B.
- C.
- D.
- 方向导数公式是?
- A.
- B.
- C.
- D.
- 多元链式法则 等于?
- A.
- B.
- C.
- D.
