AI_数学基础-最优化方法-1.凸优化基础
AI数学基础:凸优化基础
学习目标:掌握凸优化核心概念(凸函数、凹函数),理解局部最优与全局最优的关系(凸优化的核心优势),熟练掌握无约束优化问题的核心求解方法(梯度下降法),能完成简单手工计算,通过代码实现无约束优化求解,为机器学习模型训练(线性回归、神经网络权重优化)奠定基础。
说明:知识点侧重“AI 实战关联”,不深究复杂数学推导,重点掌握“概念含义”“判定方法”“求解思路”“AI 场景应用”。
1. 凸函数与凹函数
凸函数是凸优化的核心基础,其特性决定了局部最优即为全局最优,也是 AI 中优先选择凸损失函数(如均方误差、交叉熵)的原因。
1.1 前置概念:凸集
定义:对于集合 D 中的任意两点 x_1, x_2,以及任意 \theta \in [0,1],点 \theta x_1 + (1-\theta)x_2 仍属于 D,则 D为凸集。
通俗理解:集合内任意两点的连线完全落在集合内。
AI 应用:机器学习中模型参数(如权重 w、偏置 b)构成的空间通常为凸集。
1.2 凸函数与凹函数的定义
设函数 f 定义在凸集 D 上。
凸函数
对于任意 x_1, x_2 \in D 和 \theta \in [0,1],满足:
f(\theta x_1 + (1-\theta)x_2) \le \theta f(x_1) + (1-\theta)f(x_2)
通俗解读:函数上任意两点的弦位于函数图像的上方(函数曲线呈“下凸”形状,开口向上)。
几何含义:凸函数是“碗状”的。
凹函数
对于任意 x_1, x_2 \in D 和 \theta \in [0,1],满足:
f(\theta x_1 + (1-\theta)x_2) \ge \theta f(x_1) + (1-\theta)f(x_2)
通俗解读:弦位于函数图像的下方(曲线呈“上凸”形状,开口向下)。
几何含义:凹函数是“山丘状”的。
线性函数 f(x)=ax+b 既是凸函数也是凹函数。
1.3 判定方法(AI 高频使用)
一阶条件(可微函数)
- 凸函数:f(y) \ge f(x) + \nabla f(x)^T (y - x), \quad \forall x,y
- 凹函数:f(y) \le f(x) + \nabla f(x)^T (y - x), \quad \forall x,y
含义:凸函数始终位于其任意切线(或切平面)之上。
二阶条件(二阶可微)
- 一元函数:
- 凸函数 \iff f''(x) \ge 0(严格凸 f''(x) > 0)
- 凹函数 \iff f''(x) \le 0(严格凹 f''(x) < 0)
- 多元函数:
- 凸函数 \iff \nabla^2 f(x) \succeq 0(Hessian 矩阵半正定)
- 凹函数 \iff \nabla^2 f(x) \preceq 0(Hessian 矩阵半负定)
AI 实战:手动计算时,一元函数直接用二阶导数符号判断即可;多元函数了解概念即可,实际由代码计算 Hessian。
1.4 常见凸函数与凹函数(AI 中经常出现)
| 类型 | 函数示例 | 说明 |
|---|---|---|
| 凸函数 | f(x)=x^2, f(x)=x, f(x)=e^{ax}, f(x)=x\log x\;(x>0) | 平方损失、绝对值损失、指数损失、负熵 |
| 多元凸函数 | 均方误差 L(w)=\frac{1}{n}\sum_{i=1}^n (y_i - w^T x_i)^2 | 线性回归损失(严格凸) |
| 凹函数 | f(x)=\log x\;(x>0), f(x)=\sqrt{x}, f(x)=-x^2 | 对数似然(最大化)、几何平均 |
1.5 手工计算示例
示例 1:判断 f(x)=x^2+2x 的凸性
- 求一阶导数:f'(x)=2x+2
- 求二阶导数:f''(x)=2 > 0
- 结论:严格凸函数。
示例 2:判断 f(x)=\log x\;(x>0) 的凸性
- f'(x)=1/x
- f''(x)=-1/x^2 < 0 // -1 * x^-2
- 结论:严格凹函数。
示例 3:验证凸函数定义(以 f(x)=x^2 为例)
取 x_1=1,\;x_2=3,\;\theta=0.5:
- 左侧:f(0.5×1+0.5×3)=f(2)=4
- 右侧:0.5×f(1)+0.5×f(3)=0.5×1+0.5×9=5
由于 4 \le 5,满足定义,因此 f(x)=x^2 是凸函数。
示例 4:一元函数二阶条件判断
| 函数 | 二阶导数 | 凸/凹性 |
|---|---|---|
| f(x)=x^2 | 2>0 | 严格凸 |
| f(x)=x^3 | 6x(变号) | 非凸非凹 |
| f(x)=-x^2 | -2<0 | 严格凹 |
1.6 Python 代码示例:凸函数判定与可视化
import numpy as np import matplotlib.pyplot as plt # 定义函数 def f1(x): return x**2 + 2*x # 凸函数 def f2(x): return np.log(x) # 凹函数(x>0) def f3(x): return x**3 - 3*x # 非凸非凹 # 数值求导 def numerical_derivative(f, x, h=1e-5): return (f(x+h) - f(x-h)) / (2*h) def numerical_second_derivative(f, x, h=1e-5): return (f(x+h) - 2*f(x) + f(x-h)) / (h**2) # 测试凸函数 f1 x = np.linspace(-3, 2, 100) f1_vals = f1(x) f1_der2 = [numerical_second_derivative(f1, xi) for xi in x] plt.figure(figsize=(10,4)) plt.subplot(1,2,1) plt.plot(x, f1_vals, 'b-', label='f(x)=x²+2x') plt.axvline(x=-1, color='r', linestyle='--', label='全局最优 x=-1') plt.legend() plt.grid(True) plt.subplot(1,2,2) plt.plot(x, f1_der2, 'g-', label='二阶导数') plt.axhline(y=0, color='r', linestyle='--') plt.title(f'二阶导数均值 = {np.mean(f1_der2):.2f} (>0 ⇒ 凸函数)') plt.legend() plt.grid(True) plt.tight_layout() plt.show() print(f"f(x)=x²+2x 的二阶导数均值:{np.mean(f1_der2):.2f} → 严格凸函数")2. 局部最优 vs 全局最优
2.1 概念定义
- 局部最优:存在邻域 N,使得 f(x^*) \le f(x)(最小化问题)对所有 x\in N 成立。
- 全局最优:对所有 x\in \text{dom}f,f(x^*) \le f(x) 成立。
2.2 凸优化的核心性质
对于凸函数的最小化问题:任意局部最优解都是全局最优解。
- 原因:凸函数的“下凸”特性使得局部最低点不可能是“坑中坑”。
- 意义:AI 中优先选择凸损失函数(如均方误差、交叉熵),确保梯度下降等算法能找到全局最优,避免陷入局部最优。
2.3 反例:非凸函数
非凸函数可能存在多个局部最优,梯度下降可能收敛到局部最优而非全局最优。例如神经网络损失函数通常非凸,需通过调参、随机初始化等技巧缓解。
2.4 手工计算示例
示例 1:凸函数(局部最优 = 全局最优)
f(x)=x^2+2x
- 令 f'(x)=2x+2=0,得 x=-1
- f''(x)=2>0,故 x=-1 是局部最小值
- 由于函数严格凸,该点也是全局最小值,f(-1)=-1
示例 2:非凸函数(局部最优 ≠ 全局最优)
f(x)=x^3-3x
- f'(x)=3x^2-3=0 \Rightarrow x=1 或 x=-1
- f''(x)=6x:f''(1)=6>0(局部最小),f''(-1)=-6<0(局部最大)
- 当 x\to -\infty 时 f(x)\to -\infty,无全局最小值;当 x\to +\infty 时 f(x)\to +\infty,无全局最大值。仅存在局部最优。
3. 无约束优化问题
3.1 问题定义
\underset{x\in\mathbb{R}^n}{\text{minimize}}\quad f(x)
其中 f 通常为凸函数(AI 中为损失函数)。最大化问题可转化为最小化问题:\max f(x) = -\min (-f(x))。
3.2 最优性条件
对于凸函数,x^* 是最优解的充要条件为梯度为零:
\nabla f(x^*) = 0
(一元函数:f'(x^*)=0 且 f''(x^*)\ge 0)
3.3 梯度下降法(Gradient Descent, GD)
基本思想
沿负梯度方向(函数下降最快的方向)迭代更新变量,逐步逼近最优解。
迭代公式(一元函数)
x_{k+1} = x_k - \eta f'(x_k)
- x_k:第 k 次迭代的值
- \eta:学习率(步长),控制更新幅度
- f'(x_k):梯度(一阶导数)
多元函数形式
\mathbf{x}_{k+1} = \mathbf{x}_k - \eta \nabla f(\mathbf{x}_k)
学习率的影响
- \eta 过大:可能不收敛,甚至发散
- \eta 过小:收敛速度慢
- 常用策略:衰减学习率、自适应学习率(Adam 等)
3.4 梯度下降的三种变种(AI 实战重点)
| 变种 | 每次使用的样本数 | 特点 |
|---|---|---|
| 批量梯度下降(BGD) | 全部样本 | 收敛稳定,计算量大(小样本适用) |
| 随机梯度下降(SGD) | 1 个样本 | 计算快,收敛波动大,可跳出局部最优 |
| 小批量梯度下降(MBGD) | 部分样本(如 32, 64) | 兼顾速度与稳定性,AI 中最常用 |
3.5 牛顿法(进阶选读)
牛顿法使用二阶 Hessian 矩阵加速收敛,适用于 f 二阶可导的凸函数。
x_{k+1} = x_k - \alpha_k [\nabla^2 f(x_k)]^{-1} \nabla f(x_k)
优点:收敛速度快(二次收敛)。
缺点:计算 Hessian 矩阵及逆矩阵开销大,高维不实用。
AI 中较少直接使用,但理解其对理解优化算法有帮助。
3.6 手工计算示例:梯度下降迭代
问题:\min f(x)=x^2+2x,初始 x_0=1,学习率 \eta=0.1,迭代 5 次。
梯度:f'(x)=2x+2。
| 迭代 k | x_k | 梯度 g_k | x_{k+1}=x_k-0.1g_k |
|---|---|---|---|
| 0 | 1.0000 | 4.0000 | 0.6000 |
| 1 | 0.6000 | 3.2000 | 0.2800 |
| 2 | 0.2800 | 2.5600 | 0.0240 |
| 3 | 0.0240 | 2.0480 | -0.1808 |
| 4 | -0.1808 | 1.6384 | -0.3446 |
| 5 | -0.3446 | 1.3108 | -0.4757 |
迭代 5 次后 x_5\approx -0.476,逐步逼近最优解 x^*=-1。
若使用牛顿法,一步直达最优:x_1 = x_0 - f'(x_0)/f''(x_0) = 1 - 4/2 = -1。
4. 代码实践(AI 场景)
4.1 梯度下降求解一元凸函数
import numpy as np import matplotlib.pyplot as plt def f(x): return x**2 + 2*x def grad(x): return 2*x + 2 def gradient_descent(init_x, lr=0.1, iterations=10): x = init_x history = [x] for _ in range(iterations): x = x - lr * grad(x) history.append(x) return np.array(history) x0 = 1.0 lr = 0.1 iters = 10 path = gradient_descent(x0, lr, iters) x_vals = np.linspace(-3, 2, 100) plt.plot(x_vals, f(x_vals), 'b-', label='f(x)=x²+2x') plt.plot(path, f(path), 'ro-', markersize=6, label='梯度下降路径') plt.axvline(x=-1, color='g', linestyle='--', label='全局最优 x=-1') plt.legend() plt.grid(True) plt.title(f'梯度下降 (lr={lr}, {iters}次迭代)') plt.show() print("迭代过程:", [f"{x:.4f}" for x in path])4.2 梯度下降变种:线性回归(多元凸函数)
import numpy as np import matplotlib.pyplot as plt # 生成模拟数据(真实权重 w1=2, w2=3) np.random.seed(42) X = np.random.randn(1000, 2) y = 2 * X[:, 0] + 3 * X[:, 1] + np.random.randn(1000) * 0.1 def mse_loss(w, X, y): return np.mean((X @ w - y) ** 2) def gradient(w, X, y): pred = X @ w return 2 * X.T @ (pred - y) / len(X) # 批量梯度下降 def bgd(X, y, init_w, lr=0.01, epochs=100): w = init_w.copy() losses = [] for _ in range(epochs): w -= lr * gradient(w, X, y) losses.append(mse_loss(w, X, y)) return w, losses # 随机梯度下降 def sgd(X, y, init_w, lr=0.01, epochs=100): w = init_w.copy() losses = [] n = len(X) for _ in range(epochs): idx = np.random.randint(n) X_i, y_i = X[idx:idx+1], y[idx:idx+1] grad_i = 2 * X_i.T @ (X_i @ w - y_i) w -= lr * grad_i losses.append(mse_loss(w, X, y)) return w, losses # 小批量梯度下降 def mbgd(X, y, init_w, batch_size=32, lr=0.01, epochs=100): w = init_w.copy() losses = [] n = len(X) for _ in range(epochs): idx = np.random.choice(n, batch_size, replace=False) X_batch, y_batch = X[idx], y[idx] grad_batch = 2 * X_batch.T @ (X_batch @ w - y_batch) / batch_size w -= lr * grad_batch losses.append(mse_loss(w, X, y)) return w, losses init_w = np.array([0.5, 0.5]) w_bgd, loss_bgd = bgd(X, y, init_w) w_sgd, loss_sgd = sgd(X, y, init_w) w_mbgd, loss_mbgd = mbgd(X, y, init_w) plt.plot(loss_bgd, label='BGD') plt.plot(loss_sgd, label='SGD', alpha=0.7) plt.plot(loss_mbgd, label='MBGD') plt.xlabel('Epoch') plt.ylabel('MSE Loss') plt.legend() plt.title('三种梯度下降收敛曲线') plt.grid(True) plt.show() print("最终权重:") print(f"BGD: w1={w_bgd[0]:.4f}, w2={w_bgd[1]:.4f}") print(f"SGD: w1={w_sgd[0]:.4f}, w2={w_sgd[1]:.4f}") print(f"MBGD: w1={w_mbgd[0]:.4f}, w2={w_mbgd[1]:.4f}") print(f"真实: w1=2.0000, w2=3.0000")5. 学习资料推荐
书籍
- 《Convex Optimization》– Stephen Boyd, Lieven Vandenberghe(经典,理论与代码结合)
- 《凸优化》(中译本)– 适合系统学习
在线课程
- Stanford Convex Optimization(Stephen Boyd 主讲)
- B站:凸优化从入门到放弃(中文讲解)
实战参考
- Scipy.optimize.minimize – 内置优化器
- Gradient Descent Variants(英文,三种变种详解)
- CVXPY – Python 凸优化建模工具
快速上手建议
- 先掌握:凸函数判定(二阶导数)、梯度下降迭代公式、学习率的影响。
- 再动手:运行上述代码,观察收敛曲线,修改学习率看效果。
- 最后进阶:阅读 Boyd 教材第 1–3 章和第 9–10 章,理解收敛性分析。
