17·数学基础进阶

微积分要点:导数与梯度

mathcalculus

第17课:微积分要点:导数与梯度

学习目标

完成本课学习后,你将能够:

  1. 理解导数作为函数变化率的核心概念。
  2. 掌握基本函数的求导规则,并能手动计算简单函数的导数。
  3. 计算多变量函数的偏导数,并理解梯度向量的含义。
  4. 解释梯度在机器学习优化问题(如寻找损失函数极小值)中的作用。

核心概念

1. 导数:变化的“速度”

想象你在开车,导数描述的就是你速度瞬时变化率。在数学上,函数 ( f(x) ) 在一点 ( x ) 的导数 ( f'(x) ) 或 ( \frac{df}{dx} ),表示当 ( x ) 有微小变化时,函数值 ( f(x) ) 的变化有多快。

  • 几何意义:导数是函数曲线在某一点的切线斜率。斜率越大,函数在该点上升(或下降)得越快。
  • 机器学习关联:在机器学习中,我们常常优化一个“损失函数” ( L(w) ),其中 ( w ) 是模型的参数(比如权重)。我们想知道,当参数 ( w ) 改变一点点时,损失 ( L ) 是如何变化的?答案就是损失函数对参数的导数 ( \frac{dL}{dw} )。这个信息告诉我们调整参数的方向和幅度

2. 偏导数:多变量的“单独影响”

当函数有多个输入变量时,例如 ( f(x, y) ),我们想知道只改变其中一个变量(比如 ( x )),而其他变量保持不变时,函数值的变化率。这就是偏导数,记为 ( \frac{\partial f}{\partial x} )。

  • 计算方式:将其他所有变量都看作常数,然后对目标变量求导。

3. 梯度:最速上升方向

对于一个多变量函数 ( f(x_1, x_2, ..., x_n) ),它的梯度是一个由所有偏导数组成的向量: [ \nabla f = \left( \frac{\partial f}{\partial x_1}, \frac{\partial f}{\partial x_2}, ..., \frac{\partial f}{\partial x_n} \right) ]

  • 核心性质:梯度指向函数在该点增长最快的方向。相反,负梯度 ( -\nabla f ) 指向函数下降最快的方向。
  • 机器学习核心梯度下降算法就是利用这个性质。我们从一个初始点出发,沿着损失函数的负梯度方向一步步“下山”,希望最终能找到一个损失很小的参数点。梯度 ( \nabla L(w) ) 告诉我们每一步该怎么走。

代码示例

以下示例将使用 Python 和 numpy 库来演示导数的计算和梯度的概念。

import numpy as np
import matplotlib.pyplot as plt

# === 1. 导数:单变量函数示例 ===
# 定义一个函数: f(x) = x^2 - 4x + 5 (一个简单的二次函数)
def f(x):
    return x**2 - 4*x + 5

# 解析求导: f'(x) = 2x - 4
def df_dx(x):
    return 2*x - 4

# 绘制函数和其导数
x_vals = np.linspace(-2, 6, 100)
y_vals = f(x_vals)
dy_vals = df_dx(x_vals)

plt.figure(figsize=(10, 4))
plt.subplot(1, 2, 1)
plt.plot(x_vals, y_vals, label='f(x) = x²-4x+5')
plt.xlabel('x')
plt.ylabel('f(x)')
plt.title('函数图像')
plt.grid(True)

# 选取一个点,展示切线斜率(导数值)
x_point = 1
slope = df_dx(x_point)
tangent_line = f(x_point) + slope * (x_vals - x_point) # 切线方程: y = f(a) + f'(a)*(x-a)
plt.plot(x_vals, tangent_line, 'r--', label=f'在x={x_point}的切线 (斜率={slope})')
plt.legend()

plt.subplot(1, 2, 2)
plt.plot(x_vals, dy_vals, label="f'(x) = 2x-4", color='orange')
plt.axhline(y=0, color='gray', linestyle='-', linewidth=0.5) # 水平参考线
plt.axvline(x=0, color='gray', linestyle='-', linewidth=0.5) # 垂直参考线
plt.xlabel('x')
plt.ylabel("f'(x)")
plt.title('导数图像')
plt.grid(True)
plt.legend()
plt.tight_layout()
plt.show()

print(f"在 x=1 处,函数值 f(1)={f(1)}")
print(f"在 x=1 处,导数 f'(1)={df_dx(1)},表示函数在此点瞬时变化率为 -2,正在下降。")

# === 2. 梯度:多变量函数示例 ===
# 定义一个二维函数: g(x, y) = (x-1)^2 + (y-2)^2 + 5
# 这是一个碗状函数,在 (1, 2) 处有最小值 5
def g(x, y):
    return (x - 1)**2 + (y - 2)**2 + 5

# 计算梯度: ∇g = (∂g/∂x, ∂g/∂y) = (2*(x-1), 2*(y-2))
def gradient_g(x, y):
    grad_x = 2 * (x - 1)
    grad_y = 2 * (y - 2)
    return np.array([grad_x, grad_y])

# 在点 (3, 4) 处计算梯度
point = np.array([3, 4])
grad = gradient_g(point[0], point[1])
print(f"\n函数 g(x,y) 在点 {point} 处的梯度为: {grad}")
print(f"这意味着:从该点出发,沿方向 ({grad[0]}, {grad[1]}) 函数上升最快。")
print(f"如果想让g下降,应该沿着负梯度方向 (-{grad[0]}, -{grad[1]}) 移动一小步。")

# === 3. 简单的梯度下降模拟 ===
# 使用梯度下降寻找函数g的极小值点
learning_rate = 0.1  # 学习率(步长)
current_point = np.array([5.0, 0.0]) # 起始点
points_path = [current_point.copy()]

# 迭代更新
for i in range(10):
    grad = gradient_g(current_point[0], current_point[1])
    # 核心更新公式: 新点 = 旧点 - 学习率 * 梯度
    current_point = current_point - learning_rate * grad
    points_path.append(current_point.copy())
    print(f"迭代 {i+1}: 位置 {current_point}, 梯度 {grad}")

# 绘制函数等高线和下降路径
x_range = np.linspace(-1, 7, 100)
y_range = np.linspace(-2, 6, 100)
X, Y = np.meshgrid(x_range, y_range)
Z = g(X, Y)

plt.figure(figsize=(8, 6))
plt.contourf(X, Y, Z, levels=20, cmap='viridis', alpha=0.6)
plt.colorbar(label='g(x, y)')
points_arr = np.array(points_path)
plt.plot(points_arr[:, 0], points_arr[:, 1], 'ro-', label='梯度下降路径')
plt.plot(1, 2, 'r*', markersize=15, label='最小值点 (1,2)') # 真实最小值点
plt.xlabel('x')
plt.ylabel('y')
plt.title('梯度下降寻找函数最小值')
plt.legend()
plt.grid(True)
plt.show()

实践练习

练习1:计算导数 给定函数 ( h(t) = 3t^3 - 2t + 1 ),请手动计算其导数 ( h'(t) ),并编程验证在 ( t=2 ) 时的导数值。

预期输出:

h'(t) = 9t^2 - 2
在 t=2 时,h'(2) = 34

练习2:计算梯度 对于函数 ( f(x, y) = 5x^2 + 3xy - y^2 ),请: a) 计算其在点 (1, -1) 处的梯度。 b) 判断在该点处,函数沿哪个方向(向量)下降最快?这个方向是唯一的吗?

预期输出:

a) 梯度 ∇f(1, -1) = (13, 6)
b) 下降最快方向是负梯度方向:(-13, -6)。方向是唯一的(不考虑长度)。

练习3:梯度下降一步 使用练习2中的函数和点 (1, -1)。假设学习率 ( \eta = 0.01 ),请你手动计算进行一次梯度下降后,新的点坐标是多少? (提示:( x_{new} = x_{old} - \eta \cdot \frac{\partial f}{\partial x} ), y同理)

预期输出:

新点坐标: (1 - 0.01*13, -1 - 0.01*6) = (0.87, -1.06)

常见错误

  1. 混淆导数和梯度:导数是针对单变量函数的,结果是一个标量;梯度是针对多变量函数的,结果是一个向量。
  2. 忽略链式法则:在计算复合函数导数时(如 ( \sin(2x) )),忘记应用链式法则(即 ( \frac{d}{dx}f(g(x)) = f'(g(x)) * g'(x) ))。这是神经网络反向传播的基础。
  3. 梯度计算错误:对某个变量求偏导时,误将其他变量也当作常数处理。例如,对 ( f(x, y)=xy ) 求 ( \frac{\partial f}{\partial x} ) 时,结果应该是 ( y )(将 ( y ) 视为常数),而不是 ( x ) 或 0。
  4. 误解梯度方向:梯度指向函数上升最快的方向,而梯度下降算法使用的是负梯度方向。这个方向只有在极小值点处才为零向量。
  5. 学习率选择不当:学习率太大,可能导致在极小值点附近震荡甚至发散;学习率太小,收敛速度会非常慢。这是一个重要的超参数。

小结

本节我们学习了微积分在机器学习中最核心的两个概念:

  • 导数:衡量单变量函数局部变化率的工具,是切线的斜率。
  • 梯度:多变量函数导数的推广,是一个向量,指向函数值增长最快的方向。
  • 机器学习中的应用:梯度向量,特别是损失函数关于模型参数的梯度,是优化算法(如梯度下降)的指南针。沿着梯度的反方向更新参数,能够有效降低损失,使模型性能不断提升。 理解导数和梯度,是理解后续所有基于梯度的优化算法(如SGD、Adam等)的基石。下一课,我们将深入探讨梯度下降算法的数学原理。

练习编辑器

rust
Loading...

继续学习

完成本课后,建议继续学习下一课「梯度下降的数学原理」 以巩固所学知识。