从0开始的机器学习(笔记系列)------导数 · 多元函数导数 · 梯度
笔者刚好最近打算从新开始搞一搞深度学习和机器学习出来,这里整理一点笔记。
1. 导数(一元函数)------直观与定义
- 直观:导数表示函数曲线上某点的切线斜率,或变量微小变化时函数值的变化率。
- 数学定义(极限):对于一元函数 (f(x)),在点 (x=a) 处的导数定义为
f′(a)=limh→0f(a+h)−f(a)h. f'(a)=\lim_{h\to 0}\frac{f(a+h)-f(a)}{h}. f′(a)=h→0limhf(a+h)−f(a).
- 常用求导规则 (便于记忆)
- 常数:((c)′=0)((c)'=0)((c)′=0)
- 幂函数:((xn)′=nxn−1)((x^n)'=n x^{n-1})((xn)′=nxn−1)
- 乘法:((uv)′=u′v+uv′)((uv)'=u'v+uv')((uv)′=u′v+uv′)
- 除法:((u/v)′=u′v−uv′v2)((u/v)'=\frac{u'v-uv'}{v^2})((u/v)′=v2u′v−uv′)
- 复合函数(链式法则):((f∘g)′(x)=f′(g(x))⋅g′(x))((f\circ g)'(x)=f'(g(x))\cdot g'(x))((f∘g)′(x)=f′(g(x))⋅g′(x))
示例:(f(x)=sin x)
解析导数:(f'(x)=\cos x)。
下面给出一个可运行的 Python 代码,绘制函数与解析导数,并用有限差分近似验证:
python
# 文件名: derivative_1d.py
import numpy as np
import matplotlib.pyplot as plt
# 函数定义
def f(x):
return np.sin(x)
def f_prime_analytic(x):
return np.cos(x)
# 数值导数(中心差分)
def numerical_derivative(f, x, h=1e-5):
return (f(x + h) - f(x - h)) / (2 * h)
# 网格
x = np.linspace(-2*np.pi, 2*np.pi, 400)
# 计算
y = f(x)
y_analytic = f_prime_analytic(x)
y_numeric = numerical_derivative(f, x)
# 绘图
plt.figure(figsize=(10,6))
plt.plot(x, y_analytic, label='解析导数 cos(x)')
plt.plot(x, y_numeric, '--', label='中心差分数值导数')
plt.title('一元函数导数:解析 vs 数值')
plt.legend()
plt.xlabel('x')
plt.grid(True)
plt.show()
运行后应能看到解析导数与数值导数高度重合的曲线,说明数值方法在合理步长下能很好地近似真实导数。
2. 多元函数的偏导数与梯度(Gradient)
偏导数(Partial derivative)
对于二元函数 (f(x,y)),在保持另一个变量不变的条件下对其中一个变量求导称为偏导数:
∂f∂x(x,y)=limh→0f(x+h,y)−f(x,y)h, \frac{\partial f}{\partial x}(x,y)=\lim_{h\to 0}\frac{f(x+h,y)-f(x,y)}{h}, ∂x∂f(x,y)=h→0limhf(x+h,y)−f(x,y),
同理可定义对 (y) 的偏导数 (\partial f/\partial y)。
梯度(Gradient)
梯度是偏导数按坐标轴排列成的向量,表示函数在各坐标方向的瞬时变化率:
∇f(x,y)=(∂f∂x,∂f∂y). \nabla f(x,y)=\begin{pmatrix} \frac{\partial f}{\partial x}, \frac{\partial f}{\partial y} \end{pmatrix}. ∇f(x,y)=(∂x∂f,∂y∂f).
梯度的方向是函数增长最快的方向,梯度的模长给出增长最快的斜率大小。
方向导数(Directional derivative)
沿单位向量 (\mathbf{u}) 的方向导数为:
Duf(x)=∇f(x)⋅u. D_{\mathbf{u}} f(\mathbf{x}) = \nabla f(\mathbf{x}) \cdot \mathbf{u}. Duf(x)=∇f(x)⋅u.
它说明函数在该方向上的瞬时变化率。
3. 例子:简单二元函数与可视化
函数:(f(x,y)=x2+y2)。
- 偏导数:(∂f∂x=2x),(∂f∂y=2y)(\frac{\partial f}{\partial x}=2x),(\frac{\partial f}{\partial y}=2y)(∂x∂f=2x),(∂y∂f=2y)。
- 梯度:(∇f=(2x,2y)T)(\nabla f=(2x,2y)^T)(∇f=(2x,2y)T)。
下面代码:绘制等高线(contour)并在网格点画出梯度向量场(用箭头表示)。
python
# 文件名: gradient_field.py
import numpy as np
import matplotlib.pyplot as plt
# 定义函数和梯度
def f(X, Y):
return X**2 + Y**2
def grad_f(X, Y):
return 2*X, 2*Y
# 网格
x = np.linspace(-2, 2, 25)
y = np.linspace(-2, 2, 25)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
# 梯度场
GX, GY = grad_f(X, Y)
plt.figure(figsize=(8,8))
# 等高线
cs = plt.contour(X, Y, Z, levels=12)
plt.clabel(cs, inline=True, fontsize=8)
# 画梯度(注意:梯度指向函数上升最快方向)
plt.quiver(X, Y, GX, GY)
plt.title('函数 f(x,y)=x^2+y^2 的等高线与梯度场')
plt.xlabel('x')
plt.ylabel('y')
plt.axis('equal')
plt.show()
你会看到在每个点上,箭头都指向远离原点的方向(因为函数在远离原点时变大),且箭头长度与距离成正比(梯度模长为 (2x2+y22\sqrt{x^2+y^2}2x2+y2 ))。
4. 解析梯度 vs 数值梯度(有限差分验证)
用一个稍复杂的函数:(f(x,y)=x2+xy+3y2f(x,y)=x^2 + x y + 3 y^2f(x,y)=x2+xy+3y2)。
- 解析梯度:(∇f=(2x+y,;x+6y)T\nabla f = (2x + y,; x + 6y)^T∇f=(2x+y,;x+6y)T)。
用中心差分计算数值梯度并与解析梯度比较------示例代码如下:
python
# 文件名: gradient_check.py
import numpy as np
# 函数
def f_xy(x, y):
return x**2 + x*y + 3*y**2
# 解析梯度
def grad_analytic(x, y):
return np.array([2*x + y, x + 6*y])
# 数值梯度(中心差分)
def grad_numeric(f, x, y, h=1e-6):
df_dx = (f(x + h, y) - f(x - h, y)) / (2*h)
df_dy = (f(x, y + h) - f(x, y - h)) / (2*h)
return np.array([df_dx, df_dy])
# 随机测试点
points = np.array([[0.0, 0.0], [1.0, 2.0], [-0.5, 0.7], [3.14, -2.72]])
for (x, y) in points:
a = grad_analytic(x, y)
n = grad_numeric(f_xy, x, y)
err = np.linalg.norm(a - n)
print(f"point=({x:.4f},{y:.4f}) analytic={a} numeric={n} error={err:.2e}")
# 你会看到误差通常在1e-9到1e-6量级,取决于h的选取和浮点误差。
5. 梯度在机器学习中的直观角色
- 在优化(如最小化损失函数)中,梯度给出了损失上升最快的方向;如果希望下降损失,应沿梯度的反方向更新参数(梯度下降法)。
- 简单的梯度下降更新公式(学习率 (\eta>0)):
θ←θ−η,∇θL(θ).\theta \leftarrow \theta - \eta,\nabla_{\theta} L(\theta).θ←θ−η,∇θL(θ). - 注意:实践中常用改进方法(动量、Adam、RMSprop 等)来加速收敛并稳固数值行为。
6. 小结速览
- 导数:刻画一维变化率。
- 偏导:固定其他变量时的单变量导数。
- 梯度:各偏导组成的向量,给出最快上升方向。
- 数值差分可用于验证解析导数/梯度,且是调试自动微分/手写反向传播时常用的检查手段(称为 gradient checking)。
7. 附:实用提示与常见陷阱
- 有限差分步长 h 选得太大会造成截断误差,选得太小会受浮点舍入误差影响。通常在
1e-6到1e-8之间试验。 - 对于高维参数(如神经网络),数值梯度开销极大,仅用于调试小模型或小批量参数。
- 梯度消失/爆炸是深度学习中的常见问题,与激活函数、初始化和学习率有关。