第2章:数学基础
数学是人工智能的基石。本章将带您了解 AI 中最常用的数学概念——线性代数、概率统计、微积分和优化理论。我们会注重直观理解而非公式堆砌,并配合 Python 代码示例,帮助您建立扎实的数学直觉。
2.1 线性代数
线性代数是 AI 中最基础也最常用的数学工具。神经网络中的数据都是以向量和矩阵的形式表示和处理的。
向量的直观理解
向量可以被理解为:
- 数学上:一组有序的数字 [x₁, x₂, ..., xₙ]
- 几何上:空间中的一个箭头,有方向和长度
- AI 中:一个数据点的特征表示
图:二维向量 v = [3, 2] 的几何表示
在 AI 中,一个数据样本通常表示为一个向量。例如,描述一个房屋:
import numpy as np
# 一个房屋的特征向量:[面积(平米), 卧室数, 距地铁距离(公里)]
house = np.array([120, 3, 0.5])
print(f"房屋特征向量: {house}")
print(f"向量维度: {len(house)}")
# 多个房屋组成矩阵
houses = np.array([
[120, 3, 0.5], # 房屋1
[80, 2, 1.2], # 房屋2
[150, 4, 0.3], # 房屋3
])
print(f"\n房屋数据矩阵:\n{houses}")
print(f"矩阵形状: {houses.shape}") # (3, 3) 表示3行3列
矩阵运算
矩阵乘法在 AI 中无处不在,它是神经网络前向传播的核心操作。
想象你在做"信息转换"——输入数据是一个矩阵,权重是另一个矩阵,矩阵乘法就是把输入信息按照权重进行转换,得到新的表示。
import numpy as np
# 输入数据:3个样本,每个样本2个特征
X = np.array([
[1, 2],
[3, 4],
[5, 6]
])
# 权重矩阵:2个输入特征 → 3个输出特征
W = np.array([
[0.1, 0.2, 0.3],
[0.4, 0.5, 0.6]
])
# 矩阵乘法:X (3×2) @ W (2×3) = Y (3×3)
Y = X @ W
print(f"输入形状: {X.shape}")
print(f"权重形状: {W.shape}")
print(f"输出形状: {Y.shape}")
print(f"\n输出结果:\n{Y}")
特征值与特征向量
特征值和特征向量描述了一个矩阵的"固有特性"。
🎯 直观理解
想象你拉伸一张橡胶膜:
- 某些方向上的向量,拉伸后方向不变,只是长度变化
- 这些特殊的向量就是特征向量
- 长度变化的倍数就是特征值
在 AI 中,特征值分解用于降维(PCA)、图神经网络等领域。
import numpy as np
# 定义一个对称矩阵
A = np.array([[4, 2],
[2, 3]])
# 计算特征值和特征向量
eigenvalues, eigenvectors = np.linalg.eig(A)
print("矩阵 A:")
print(A)
print(f"\n特征值: {eigenvalues}")
print(f"特征向量:\n{eigenvectors}")
# 验证:A @ v = λ @ v
v1 = eigenvectors[:, 0]
lambda1 = eigenvalues[0]
print(f"\n验证 A @ v1 = λ1 @ v1:")
print(f"A @ v1 = {A @ v1}")
print(f"λ1 @ v1 = {lambda1 * v1}")
2.2 概率论与统计
AI 充满了不确定性——数据有噪声、预测有误差。概率论为我们处理不确定性提供了数学框架。
概率分布
概率分布描述了随机变量取不同值的可能性。
| 分布类型 | 描述 | AI 应用场景 |
|---|---|---|
| 正态分布 | 钟形曲线,自然界最常见的分布 | 数据标准化、初始化神经网络权重 |
| 均匀分布 | 所有结果概率相等 | 随机初始化、随机采样 |
| 伯努利分布 | 二选一(成功/失败) | 二分类问题的标签分布 |
| 类别分布 | 多选一 | 多分类问题的输出概率 |
import numpy as np
import matplotlib.pyplot as plt
# 生成正态分布数据
np.random.seed(42)
normal_data = np.random.normal(loc=0, scale=1, size=1000)
print(f"正态分布数据 - 均值: {np.mean(normal_data):.3f}, 标准差: {np.std(normal_data):.3f}")
# 可视化(在实际代码中可运行)
# plt.hist(normal_data, bins=30, density=True, alpha=0.7)
# plt.title('正态分布')
# plt.show()
贝叶斯定理
贝叶斯定理是概率论中最重要的公式之一,它描述了如何根据新证据更新我们的信念。
贝叶斯公式
P(A|B) = P(B|A) × P(A) / P(B)
- P(A):先验概率(在观察数据之前的信念)
- P(A|B):后验概率(观察到数据 B 后的更新信念)
- P(B|A):似然(在 A 成立时观察到 B 的概率)
假设:
- 收到邮件中包含"免费"这个词的概率是 5%
- 垃圾邮件占所有邮件的 20%
- 垃圾邮件中包含"免费"的概率是 50%
问:如果一封邮件包含"免费",它是垃圾邮件的概率是多少?
# 贝叶斯定理计算
# P(垃圾邮件|包含"免费") = P(包含"免费"|垃圾邮件) × P(垃圾邮件) / P(包含"免费")
P_spam = 0.20 # 先验概率:邮件是垃圾邮件的概率
P_free_given_spam = 0.50 # 似然:垃圾邮件包含"免费"的概率
P_free = 0.05 # 证据:所有邮件包含"免费"的概率
# 应用贝叶斯定理
P_spam_given_free = (P_free_given_spam * P_spam) / P_free
print(f"先验概率 P(垃圾邮件) = {P_spam:.2%}")
print(f"似然 P(包含'免费'|垃圾邮件) = {P_free_given_spam:.2%}")
print(f"后验概率 P(垃圾邮件|包含'免费') = {P_spam_given_free:.2%}")
print(f"\n看到'免费'一词后,垃圾邮件的概率从 {P_spam:.0%} 上升到 {P_spam_given_free:.0%}!")
假设检验的基本思想
假设检验帮助我们判断观察到的数据是真实的规律还是随机波动。
基本流程
- 提出假设:原假设 H₀(通常是无效果的假设)vs 备择假设 H₁
- 收集数据:进行实验或观测
- 计算统计量:衡量观察结果与假设的差异
- 做出决策:如果差异足够大(p-value < 0.05),拒绝原假设
from scipy import stats
import numpy as np
# 实例:新药是否有效?
# 对照组(旧药)和实验组(新药)的恢复时间
control_group = np.random.normal(10, 2, 100) # 旧药平均10天恢复
experiment_group = np.random.normal(8.5, 2, 100) # 新药平均8.5天恢复
# t检验
t_stat, p_value = stats.ttest_ind(control_group, experiment_group)
print(f"t统计量: {t_stat:.3f}")
print(f"p值: {p_value:.6f}")
print(f"\n结论: {'新药显著更有效!' if p_value < 0.05 else '没有显著差异'}")
2.3 微积分
微积分是研究变化的数学。在 AI 中,我们用它来优化模型参数,使预测越来越准确。
导数的直观理解
导数表示函数在某一点的变化率或斜率。
import numpy as np
# 定义函数 f(x) = x^2
def f(x):
return x ** 2
# 数值计算导数(导数的定义)
def derivative(f, x, h=1e-5):
return (f(x + h) - f(x - h)) / (2 * h)
# 测试不同点的导数
test_points = [-3, -1, 0, 1, 3]
print("函数 f(x) = x² 在各点的导数:")
print("-" * 40)
for x in test_points:
deriv = derivative(f, x)
print(f"f'({x}) = {deriv:.3f}")
print("\n观察:当 x < 0 时,导数为负(函数递减);当 x > 0 时,导数为正(函数递增)")
print("在 x = 0 处,导数为 0,这是函数的最小值点!")
梯度:多元函数的导数
在多元函数中,梯度是一个向量,指向函数增长最快的方向。
想象你站在山坡上:
- 梯度告诉你哪个方向最陡峭
- 梯度的模长告诉你坡度有多陡
- 负梯度指向山脚(函数值减小的方向)
import numpy as np
# 定义二元函数 f(x, y) = x² + y²(像一个碗的形状)
def f(x, y):
return x**2 + y**2
# 梯度 [∂f/∂x, ∂f/∂y] = [2x, 2y]
def gradient(x, y):
return np.array([2*x, 2*y])
# 在不同点计算梯度
test_points = [(3, 0), (0, 3), (2, 2), (-1, -1)]
print("函数 f(x,y) = x² + y² 在各点的梯度:")
print("-" * 50)
for x, y in test_points:
grad = gradient(x, y)
print(f"在点 ({x}, {y}): 梯度 = {grad}, 方向指向函数增长最快的方向")
链式法则
链式法则是求复合函数导数的方法。它是反向传播算法的理论基础。
链式法则
如果 z = f(y),y = g(x),则 dz/dx = dz/dy × dy/dx
通俗解释:变化像链条一样传递。x 的变化先影响 y,y 的变化再影响 z。
import numpy as np
# 链式法则示例
# 假设一个神经网络的一层:z = sigmoid(w*x + b)
def sigmoid(x):
return 1 / (1 + np.exp(-x))
def sigmoid_derivative(x):
s = sigmoid(x)
return s * (1 - s)
# 前向传播
x = 2.0 # 输入
w = 0.5 # 权重
b = 0.1 # 偏置
y = w * x + b # 线性变换
z = sigmoid(y) # 激活函数
print(f"输入 x = {x}")
print(f"线性输出 y = w*x + b = {y:.4f}")
print(f"激活输出 z = sigmoid(y) = {z:.4f}")
# 反向传播:计算 ∂z/∂w
dz_dy = sigmoid_derivative(y) # ∂z/∂y
dy_dw = x # ∂y/∂w
dz_dw = dz_dy * dy_dw # 链式法则: ∂z/∂w = ∂z/∂y × ∂y/∂w
print(f"\n反向传播计算:")
print(f"∂z/∂y (激活函数导数) = {dz_dy:.4f}")
print(f"∂y/∂w (线性变换导数) = {dy_dw}")
print(f"∂z/∂w (链式法则) = {dz_dw:.4f}")
print(f"\n这意味着:权重 w 增加 0.01,输出 z 将增加约 {dz_dw * 0.01:.6f}")
2.4 优化理论
机器学习本质上是一个优化问题:找到最佳参数,使模型表现最好。
损失函数
损失函数衡量模型预测与真实值之间的差距。我们的目标是最小化损失函数。
| 损失函数 | 公式 | 适用场景 |
|---|---|---|
| 均方误差 (MSE) | 1/n Σ(yᵢ - ŷᵢ)² | 回归问题 |
| 交叉熵损失 | -Σ yᵢ log(ŷᵢ) | 分类问题 |
| 绝对误差 (MAE) | 1/n Σ|yᵢ - ŷᵢ| | 对异常值更鲁棒的回归 |
import numpy as np
# 损失函数示例
def mse_loss(y_true, y_pred):
"""均方误差"""
return np.mean((y_true - y_pred) ** 2)
def mae_loss(y_true, y_pred):
"""平均绝对误差"""
return np.mean(np.abs(y_true - y_pred))
# 示例数据
y_true = np.array([1, 2, 3, 4, 5])
y_pred_good = np.array([1.1, 2.1, 2.9, 4.1, 5.0]) # 好的预测
y_pred_bad = np.array([2, 3, 1, 5, 2]) # 差的预测
print("损失函数计算:")
print(f"好预测的 MSE: {mse_loss(y_true, y_pred_good):.4f}")
print(f"差预测的 MSE: {mse_loss(y_true, y_pred_bad):.4f}")
print(f"\n损失越小,说明预测越准确!")
梯度下降
梯度下降是机器学习中最核心的优化算法,它沿着梯度的反方向更新参数,逐步降低损失。
import numpy as np
import matplotlib.pyplot as plt
# 梯度下降优化示例:找到函数 f(x) = x^2 + 2x + 2 的最小值
# 这个函数在 x = -1 时取得最小值 f(-1) = 1
def f(x):
"""目标函数"""
return x**2 + 2*x + 2
def df(x):
"""导数(梯度)"""
return 2*x + 2
# 梯度下降参数
learning_rate = 0.3 # 学习率(步长)
n_iterations = 15 # 迭代次数
x = 3.0 # 初始值
# 记录优化过程
history = [x]
print("梯度下降优化过程:")
print("-" * 50)
print(f"初始: x = {x:.4f}, f(x) = {f(x):.4f}")
for i in range(n_iterations):
gradient = df(x) # 计算梯度
x = x - learning_rate * gradient # 更新参数(向负梯度方向移动)
history.append(x)
if i < 5 or i == n_iterations - 1: # 只打印前5步和最后一步
print(f"第{i+1}步: x = {x:.4f}, f(x) = {f(x):.4f}, 梯度 = {gradient:.4f}")
print("-" * 50)
print(f"理论最优值: x = -1, f(x) = 1")
print(f"实际收敛到: x = {x:.4f}, f(x) = {f(x):.6f}")
- 学习率太大:步长过大,可能跳过最优点甚至发散
- 学习率太小:收敛速度极慢,需要很多迭代
- 学习率适中:稳定快速地收敛到最优点
凸优化
凸优化研究的是凸函数的最小化问题。凸函数有一个很好的性质:局部最小值就是全局最小值。
✓ 凸函数
✗ 非凸函数
- 线性回归、逻辑回归等模型的损失函数是凸函数,保证能找到全局最优
- 深度学习中的损失函数通常是非凸的,存在多个局部最小值
- 理解凸优化有助于我们设计更好的优化策略和初始化方法
import numpy as np
# 判断函数凸性的简单示例
# 凸函数的二阶导数 ≥ 0
def check_convexity():
"""
f(x) = x^2 是凸函数,f''(x) = 2 > 0
f(x) = x^3 不是凸函数,f''(x) = 6x,有正有负
"""
# 测试点
x_values = np.linspace(-2, 2, 100)
# f(x) = x^2 的二阶导数
f1_second_deriv = 2 # 恒为正
# f(x) = x^3 的二阶导数
f2_second_deriv = 6 * x_values
print("凸性判断:")
print(f"f(x) = x² 的二阶导数 = {f1_second_deriv} > 0,是凸函数 ✓")
print(f"f(x) = x³ 的二阶导数 = 6x,有正有负,不是凸函数 ✗")
# 在深度学习中,我们主要关注能否找到足够好的解
# 而不一定是全局最优解
print("\n深度学习提示:")
print("神经网络通常非凸,但实践表明,")
print"SGD 等优化器仍能找到足够好的解!")
check_convexity()
本章小结
在本章中,我们学习了 AI 的数学基础:
📐 线性代数
- 向量表示数据和特征
- 矩阵用于数据转换
- 特征值分解用于降维
🎲 概率统计
- 概率分布描述不确定性
- 贝叶斯定理更新信念
- 假设检验验证结论
📈 微积分
- 导数表示变化率
- 梯度指向增长最快方向
- 链式法则支持反向传播
🎯 优化理论
- 损失函数衡量误差
- 梯度下降寻找最优
- 凸优化保证全局最优
- 运行所有代码示例,观察输出结果
- 尝试修改参数(如学习率、初始值),看看效果
- 如果某些概念还不清晰,不必强求,后续实战章节会加深理解