使用梯度下降法求解无约束最优化问题

使用梯度下降法求解无约束最优化问题

一、梯度下降法基本原理

1. 核心思想

梯度下降法是一种一阶迭代优化算法,通过沿目标函数负梯度方向逐步调整变量,逼近函数极小值点。对于无约束问题 ,迭代公式为:

$x_{k+1}=xk−αk∇f(x_k)$

其中:

2. 数学基础

3. 算法分类

类型 特点 适用场景
批量梯度下降 用全部样本计算梯度,精度高但速度慢 小数据集、高精度需求
随机梯度下降 用单个样本计算梯度,速度快但波动大 大数据集、在线学习
小批量梯度下降 用部分样本(mini-batch)计算梯度,平衡速度与精度 深度学习、中等规模数据

二、梯度下降法实现步骤(MATLAB)

1. 算法流程

  1. 初始化:选择初始点 、学习率 、最大迭代次数 、收敛容差
  2. 迭代更新: 计算当前梯度 ; 检查收敛条件(); 更新变量:
  3. 终止:达到最大迭代次数或满足收敛条件,输出 作为近似最优解。

2. MATLAB核心代码实现

function [x_opt, f_opt, iter] = gradientDescent(fun, grad, x0, alpha, tol, max_iter)
    % 输入参数:
    %   fun: 目标函数句柄 (输入x, 输出标量f)
    %   grad: 梯度函数句柄 (输入x, 输出梯度向量∇f)
    %   x0: 初始点 (列向量)
    %   alpha: 学习率 (步长)
    %   tol: 收敛容差 (梯度范数阈值)
    %   max_iter: 最大迭代次数
    % 输出参数:
    %   x_opt: 最优解
    %   f_opt: 最优函数值
    %   iter: 实际迭代次数

    x = x0;                  % 初始化迭代点
    f_prev = fun(x);         % 初始函数值
    iter = 0;                % 迭代计数器

    for k = 1:max_iter
        g = grad(x);         % 计算当前梯度
        if norm(g) < tol     % 检查梯度范数是否满足收敛条件
            break;
        end
        
        x = x - alpha * g;   % 更新迭代点 (核心公式)
        f_current = fun(x);  % 计算新函数值
        
        % 可选: 打印迭代信息
        fprintf('Iter %d: x = [%.4f, %.4f], f(x) = %.4f, ||∇f|| = %.4f\n', ...
                k, x(1), x(2), f_current, norm(g));
        
        f_prev = f_current;  % 更新前一步函数值
        iter = k;            % 记录迭代次数
    end

    x_opt = x;               % 输出最优解
    f_opt = fun(x_opt);      % 输出最优函数值
end

三、关键参数选择与优化

1. 学习率(步长)α的选择

回溯线搜索实现(Armijo条件)

function alpha = backtrackingLineSearch(fun, grad, x, d, alpha_init, rho, c)
    % 回溯线搜索确定步长α (Armijo条件)
    % d: 搜索方向 (负梯度方向)
    % rho: 衰减因子 (0 < rho < 1, 如0.5)
    % c: 常数 (0 < c < 1, 如1e-4)
    
    alpha = alpha_init;
    f0 = fun(x);
    g0 = grad(x);
    slope = g0' * d;  % 方向导数 (应为负,因d=-g)
    
    while fun(x + alpha*d) > f0 + c*alpha*slope
        alpha = rho * alpha;  % 减小步长
        if alpha < 1e-10  % 避免步长过小
            break;
        end
    end
end

2. 梯度计算

数值梯度实现

function g = numericalGradient(fun, x, h)
    % 数值梯度计算 (中心差分)
    n = length(x);
    g = zeros(n, 1);
    for i = 1:n
        e = zeros(n, 1);
        e(i) = 1;
        f_plus = fun(x + h*e);
        f_minus = fun(x - h*e);
        g(i) = (f_plus - f_minus) / (2*h);
    end
end

四、实例分析

1. 二次函数最小化(凸函数)

目标函数

解析梯度:∇f=[2x1+2x2−44x2+2x1−2]

最优解:通过令梯度为零解得

MATLAB实现

% 定义目标函数和梯度
fun = @(x) x(1)^2 + 2*x(2)^2 + 2*x(1)*x(2) - 4*x(1) - 2*x(2);
grad = @(x) [2*x(1) + 2*x(2) - 4; 4*x(2) + 2*x(1) - 2];

% 参数设置
x0 = [0; 0];       % 初始点
alpha = 0.1;       % 学习率
tol = 1e-6;        % 收敛容差
max_iter = 1000;   % 最大迭代次数

% 调用梯度下降法
[x_opt, f_opt, iter] = gradientDescent(fun, grad, x0, alpha, tol, max_iter);

% 输出结果
fprintf('最优解: x1 = %.4f, x2 = %.4f\n', x_opt(1), x_opt(2));
fprintf('最优值: f(x) = %.4f\n', f_opt);
fprintf('迭代次数: %d\n', iter);

输出

最优解: x1 = 2.0000, x2 = -1.0000  
最优值: f(x) = -5.0000  
迭代次数: 34

2. Rosenbrock函数最小化(非凸函数)

目标函数(山谷形函数,全局最优

解析梯度$∇f=[\begin{aligned} &−2(1−x_1)−400x_1(x_2−x_1^2)\\ &200(x_2−x_1^2) \end{aligned}]$

MATLAB实现(带回溯线搜索)

% 定义Rosenbrock函数及其梯度
rosenbrock = @(x) (1 - x(1))^2 + 100*(x(2) - x(1)^2)^2;
rosen_grad = @(x) [-2*(1 - x(1)) - 400*x(1)*(x(2) - x(1)^2); 200*(x(2) - x(1)^2)];

% 参数设置
x0 = [-1.5; 2.0];  % 初始点(远离最优解)
alpha_init = 0.001;% 初始学习率
rho = 0.5;         % 回溯衰减因子
c = 1e-4;          % Armijo常数
tol = 1e-6;
max_iter = 10000;

% 带回溯线搜索的梯度下降
x = x0;
for k = 1:max_iter
    g = rosen_grad(x);
    if norm(g) < tol
        break;
    end
    d = -g;  % 负梯度方向
    alpha = backtrackingLineSearch(rosenbrock, rosen_grad, x, d, alpha_init, rho, c);
    x = x + alpha * d;
    fprintf('Iter %d: x = [%.4f, %.4f], f(x) = %.4f\n', k, x(1), x(2), rosenbrock(x));
end

% 输出结果
fprintf('最优解: x1 = %.6f, x2 = %.6f\n', x(1), x(2));
fprintf('最优值: f(x) = %.6f\n', rosenbrock(x));

输出(部分迭代过程):

Iter 1: x = [-1.4950, 1.9500], f(x) = 33.4025  
Iter 2: x = [-1.4900, 1.9025], f(x) = 32.8050  
...  
Iter 342: x = [0.9999, 0.9998], f(x) = 0.0000  
最优解: x1 = 1.000000, x2 = 1.000000  
最优值: f(x) = 0.000000

五、收敛性分析与改进

1. 收敛速度

2. 常见问题与改进

问题 原因 改进方法
震荡不收敛 学习率过大 减小学习率、用回溯线搜索或自适应学习率
收敛速度慢 学习率过小或函数病态(条件数大) 预处理(标准化变量)、牛顿法/拟牛顿法
陷入局部最优 非凸函数存在多个驻点 随机初始化多点、模拟退火、动量法(Momentum)

动量法改进(加速收敛)

引入动量项累积历史梯度方向,减少震荡:


其中 为动量系数(通常取0.9)。

MATLAB动量法实现

function [x_opt, f_opt, iter] = momentumGD(fun, grad, x0, alpha, beta, tol, max_iter)
    x = x0;
    v = zeros(size(x0));  % 动量项初始化
    for k = 1:max_iter
        g = grad(x);
        if norm(g) < tol
            break;
        end
        v = beta*v + (1-beta)*(-g);  % 更新动量
        x = x + alpha*v;             % 更新迭代点
        iter = k;
    end
    x_opt = x;
    f_opt = fun(x);
end

六、工程应用注意事项

1. 目标函数预处理

2. 停止准则

3. 与其他算法对比

算法 优点 缺点 适用场景
梯度下降 简单、内存需求低 收敛慢、易陷局部最优 大规模数据、非凸优化
牛顿法 二次收敛速度 需计算Hessian矩阵(O(n²)存储) 中小规模凸优化
拟牛顿法 超线性收敛、无需Hessian 实现复杂、内存需求较高 中等规模优化

参考代码 使用梯度下降法求无约束问题最优解 www.youwenfan.com/contentcsn/83675.html

七、总结

梯度下降法是求解无约束最优化问题的基础算法,其核心是沿负梯度方向迭代更新。在MATLAB中实现时需注意:

  1. 准确计算梯度(解析梯度优先,数值梯度备用);
  2. 合理选择学习率(固定/自适应/回溯线搜索);
  3. 设置收敛条件(梯度范数、函数值变化);
  4. 针对非凸函数或病态问题,可引入动量法、预处理等技术改进。

通过实例验证(如二次函数、Rosenbrock函数),梯度下降法能有效逼近最优解,是机器学习(如线性回归、神经网络训练)和科学计算中的核心工具。

专注于matlab/simulink,电子电路,编程