目录
一、前言
二、定义
三、代码实现
四、改良后
五、总结
一、前言
作为非精确线性搜索方法的一种,旨在降低计算量,提高算法效率。在迭代过程中没有必要把线性搜索搞得十分精确,因此我们可以放松对的精度要求,只要求每一步迭代都能够缩小区间即可。
Goldstein准则也称为Armijo-Goldstein准则,是一种用于确定步长的优化准则,旨在改进Armijo准则的不足。
由于网上实在找不到答案,本人无奈,只得看看视频讲解以及代码后做此纪录。
二、定义
要求目标函数值位于两条特定直线之间,以避免步长过小。这两条直线由当前点的函数值、梯度及步长共同决定。
设定为(0, 0.5)之间的常数,若步长α满足:
则称步长α满足Goldstein准则。
其中,第一个不等式是充分下降条件,第二个保证了不会取的太小。
满足准则的区间为,成为可接受区间。
与Armijo准则相比,Goldstein准则通过设定上下界来确保步长不会过小,从而提高了优化算法的效率。
三、代码实现
MATLAB代码如下:
check_goldstein为简单判断是否符合准则条件,该代码为gpt自动生成的,后面作者改良了,该代码基于《最优化方法》第二版第三章课后题7.(1)。
function is_goldstein = check_goldstein(f, x_k, grad_f_k, d_k, alpha, c)
% 检查给定的步长alpha是否满足Goldstein准则
%
% 输入:
% f - 函数句柄,用于计算函数值
% x_k - 当前点
% grad_f_k - 当前点的梯度
% d_k - 搜索方向
% alpha - 步长
% c - Goldstein准则中的常数,通常在(0, 0.5)之间
%
% 输出:
% is_goldstein - 逻辑值,如果alpha满足Goldstein准则则为true,否则为false
% 计算新点的函数值
f_k_plus_alpha = f(x_k + alpha * d_k);
% 计算Goldstein准则的上下界
upper_bound = f(x_k) + c * alpha * grad_f_k' * d_k;
lower_bound = f(x_k) + (1 - c) * alpha * grad_f_k' * d_k;
% 检查步长是否满足Goldstein准则
is_goldstein = (f_k_plus_alpha <= upper_bound) && (f_k_plus_alpha >= lower_bound);
end
编写主函数来计算最佳步长
% 定义函数句柄
f = @(x) -2*x^3 + 21*x^2 - 60*x + 50; % 例如,一个简单的二次函数
% 当前点
x_k = 0.5;
% 当前点的梯度(可以通过数值微分或符号微分得到)
grad_f_k = -6 * x_k^2 + 42*x_k - 60; % 对于这个简单的二次函数,梯度可以直接计算
% 搜索方向(例如,负梯度方向)
d_k = -grad_f_k;
% 初始步长和Goldstein准则中的常数
alpha = 1;
p = 0.1;
% 检查步长是否满足Goldstein准则
is_goldstein = check_goldstein(f, x_k, grad_f_k, d_k, alpha, p);
% 如果不满足,可以调整步长并重新检查(这里只是一个简单的示例,实际中可能需要更复杂的步长调整策略)
while ~is_goldstein
alpha = alpha / 2; % 例如,将步长减半
is_goldstein = check_goldstein(f, x_k, grad_f_k, d_k, alpha, p);
end
% 输出满足Goldstein准则的步长
fprintf('满足Goldstein准则的步长为:%f \n', alpha);
可以得出结果为0.0625最佳步长
思路为:
取1开始第一次迭代,为,为负梯度方向。
根据定义步骤算出第一次迭代结果,然后进行到第四步时
将步4的赋值改为,进行多次迭代即可完成该题
四、改良后
% 定义目标函数
f = @(x) -2*x^3 + 21*x^2 - 60*x + 50;
% 梯度函数(对于此简单函数,可以直接计算)
grad_f = @(x) -6 * x^2 + 42*x - 60;
% 初始点
x_k = 0.5;
% 初始步长和Goldstein准则中的常数
alpha = 1;
p = 0.1;
% 最大迭代次数
max_iter = 100;
% 函数值的变化,太小则迭代停止
tol = 1e-6;
% 记录迭代过程中的x值和函数值
x_values = x_k;
f_values = f(x_k);
for iter = 1:max_iter %增加迭代计数
% 计算当前点的梯度
grad_f_k = grad_f(x_k);
% 搜索方向(负梯度方向)
d_k = -grad_f_k;
% 检查步长是否满足Goldstein准则
is_goldstein = false;
while ~is_goldstein
% 计算新点的函数值
f_k_plus_alpha = f(x_k + alpha * d_k);
% 计算Goldstein准则的上下界
upper_bound = f(x_k) + p * alpha * grad_f_k' * d_k;
lower_bound = f(x_k) + (1 - p) * alpha * grad_f_k' * d_k;
% 检查步长是否满足Goldstein准则
is_goldstein = (f_k_plus_alpha <= upper_bound) && (f_k_plus_alpha >= lower_bound);
% 如果不满足,调整步长(这里使用减半策略)
if ~is_goldstein
alpha = alpha / 2; %没有根据教材,直接二分法计算步长
end
end
% 更新x_k
x_k = x_k + alpha * d_k;
% 存储新的x值和函数值
x_values = [x_values, x_k];
f_values = [f_values, f(x_k)];
% 检查停止条件(函数值的变化)
if abs(f(x_k) - f_values(end-1)) < tol
break;
end
% 可选:输出迭代信息
fprintf('第%d次迭代: x_k = %.6f, f(x_k) = %.6f, alpha = %.6f\n', iter, x_k, f(x_k), alpha);
end
% 输出最终结果
fprintf('x: %.6f\n', x_k);
fprintf('f(x): %.6f\n', f(x_k));
fprintf('一共迭代%d次\n', iter-1);
结果为五次迭代
五、总结
作者课本中Goldstein准则提到了搜索区间,但是课后题中没有区间这一条件,但是结果感觉是正确的。
本人刚开始学习最优化
如有错误还请评论区指正。