梯度下降
一、直观理解:沿着最陡的下坡方向一步步走
梯度下降(Gradient Descent)是求解无约束(或简单约束)非线性优化的基本一阶方法。把目标函数 想象成地面高度,当前位置的梯度 指向上升最快的方向,因此反方向 就是局部最陡的下坡方向。
每次沿下坡方向走一小步:
步长 太小会爬得极慢,太大可能越过谷底甚至发散。算法并不保证一次走到全局最低点:在非凸「山地」上,它可能停在某个局部山谷。
在数学建模中,梯度下降及其变体(动量、Adam 等)常见于参数拟合、机器学习式目标、以及理解 fminunc/fmincon 内部的一阶逻辑。对光滑凸问题,它可靠;对一般非凸问题,需要多初值与谨慎解释。
二、适用场景与优缺点
| 类型 | 说明 |
|---|---|
| 适用场景 | 目标可微;无约束或仅有简单边界;维度较高、海森矩阵难求;需要理解一阶优化或自写迭代;凸光滑问题的教学与中等精度求解。 |
| 核心优点 | 每步只需要梯度,存储 ;实现简单;大规模问题可配合随机梯度;理论清晰。 |
| 局限与缺点 | 收敛相对牛顿法更慢(尤其病态谷地);步长敏感;非凸时仅局部最优;有约束时需投影或改用 fmincon 等。 |
使用前确认:
- 是否可微,梯度能否解析或可靠数值差分;
- 问题是否(近似)凸;
- 变量尺度是否统一(否则梯度分量失衡);
- 终止精度与最大迭代是否匹配需求。
三、核心原理:下降方向与步长
1. 无约束问题
若 在 可微且取得局部极小,则一阶必要条件:
梯度下降构造点列使 (在步长合适时),并希望 。
2. 为什么是负梯度
由一阶泰勒展开:
当 充分小时,右侧小于 ,故负梯度是下降方向。
3. 步长策略
- 固定步长:实现简单,需 ( 为梯度 Lipschitz 常数)一类条件;
- 线搜索:如 Armijo / 回溯,保证充分下降;
- 精确线搜索:,一维问题可做,高维成本高。
4. 收敛性直觉
- 强凸且梯度 Lipschitz:线性收敛(误差按比例缩小);
- 病态二次型(海森条件数大):等高线又长又窄,负梯度来回震荡,收敛慢——这是引入牛顿法、预处理的动机;
- 非凸:可能收敛到鞍点或局部极小。
5. 投影梯度(简单约束)
若 且 为箱约束等易投影集合:
一般非线性约束更适合约束优化算法(SQP、内点)而非手写朴素投影。
四、关键决策
1. 解析梯度 vs 数值梯度
有公式尽量手写梯度,又快又准。数值差分步长 过大过小都会错。
2. 变量缩放
若 是 量级、 是 ,应标准化,否则步长难以共用。
3. 终止条件
常用:、相对函数下降、、迭代上限。应组合使用,避免数值噪声导致永不停止。
4. 多初值
非凸时从多个 启动,取最好结果,并报告初值敏感性。
5. 何时换方法
中小规模、需要二阶收敛:牛顿 / fminunc 拟牛顿;有复杂约束:fmincon;黑箱不可微:直接搜索或智能优化兜底。
五、MATLAB 示例
例 1:手写梯度下降求 Rosenbrock 附近的极小(示意)
Rosenbrock:,全局最小在 。
a = 1; b = 100;
f = @(x) (a - x(1))^2 + b*(x(2) - x(1)^2)^2;
grad = @(x) [ ...
-2*(a - x(1)) - 4*b*x(1)*(x(2) - x(1)^2); ...
2*b*(x(2) - x(1)^2) ...
];
x = [-1.2; 1.0]; % 经典初值
alpha0 = 1e-3;
maxIter = 20000;
tol = 1e-8;
histF = zeros(maxIter, 1);
for k = 1:maxIter
g = grad(x);
histF(k) = f(x);
if norm(g) < tol
histF = histF(1:k);
break;
end
% 回溯线搜索
alpha = 0.5;
c = 1e-4;
while f(x - alpha*g) > f(x) - c*alpha*(g'*g) && alpha > 1e-16
alpha = alpha * 0.5;
end
x = x - alpha * g;
end
fprintf("迭代 %d 次, x=(%.6f, %.6f), f=%.3e, ||g||=%.3e\n", ...
numel(histF), x(1), x(2), f(x), norm(grad(x)));
figure;
semilogy(histF, "LineWidth", 1.2);
xlabel("迭代"); ylabel("f(x)"); title("梯度下降目标值下降曲线");
grid on;
例 2:用 MATLAB 优化工具箱(BFGS 拟牛顿,一阶信息)
fun = @(x) (1 - x(1))^2 + 100*(x(2) - x(1)^2)^2;
x0 = [-1.2; 1];
opts = optimoptions("fminunc", ...
"Algorithm", "quasi-newton", ...
"SpecifyObjectiveGradient", false, ...
"Display", "iter");
[xOpt, fOpt, exitflag, output] = fminunc(fun, x0, opts);
fprintf("fminunc: exit=%d, x=(%.6f,%.6f), f=%.3e, iter=%d\n", ...
exitflag, xOpt(1), xOpt(2), fOpt, output.iterations);
例 3:带箱约束的投影梯度
% min (x-3)^2 + (y+1)^2 s.t. 0<=x,y<=1
f = @(x) (x(1)-3)^2 + (x(2)+1)^2;
g = @(x) [2*(x(1)-3); 2*(x(2)+1)];
x = [0.5; 0.5];
for k = 1:200
x = x - 0.1 * g(x);
x = min(max(x, 0), 1); % 投影到 [0,1]^2
end
disp(x'); % 应接近 (1,0)
六、如何解释结果
报告应包括:
- 目标函数与是否凸的判断(或声明未知);
- 初值、步长策略、终止容差;
- 最终点 、函数值、梯度范数;
- 迭代次数与下降曲线;
- 多初值时的最好/最差/分散程度;
exitflag(若用工具箱)含义;- 约束问题中是否满足边界/约束。
非凸时表述为「求得的局部极小」,不要写「全局最优」,除非有凸性或全局方法支持。
七、常见误区
1. 步长固定过大导致发散
目标值震荡上升时,首先减小步长或加回溯。
2. 把梯度下降当全局优化器
多峰函数必须多起点或换全局策略。
3. 忽略量纲
未缩放变量会导致某些方向几乎不动。
4. 数值梯度步长乱设
对单位量级变量过大; 会淹没于浮点误差。
5. 有复杂约束仍硬套无约束梯度下降
等式/不等式约束应使用拉格朗日、KKT 体系下的约束算法或 fmincon。
6. 收敛到 就以为一定是极小
还可能是鞍点;可检查海森正定性或做局部采样。
八、小结
梯度下降的核心思想可以概括为:
沿负梯度方向迭代更新决策变量,配合适当步长使目标值下降,直至梯度近似为零,从而找到局部极小点。
它是非线性规划的一阶基石,适合可微、大规模或教学场景。建模中应重视缩放、线搜索与多初值;需要更快收敛时考虑牛顿法,有约束时上升到 KKT 与 fmincon,黑箱难解时才考虑智能优化兜底。