线性搜索方法(line search method)是数值优化里面最基础的一个内容,也是比较经典的方法,这里和大家分享一下一些基本的东西,至于原理部分,推荐大家看一下这篇文章里面的关于descent direction的推导:
https://www.jianshu.com/p/a239a39d06f7
对于一个无约束的最小值问题:
假定函数f是一个连续一阶可导的函数。
那么如果想要求这个函数的最小数值解,我们可以使用线性搜索算法达到目标。
给定一个初始值x0
计算梯度向量(方向)
其次,确定一个合适的步长 使得:
对于步长的选取,可以采用定值,但是在复杂问题里面,常常是采用自适应的方法来调整步长的取值。
通用的线性搜索方法的更新表达式如下:
这里是线性搜索方法的比较合适的结果,我们可以看到最后,搜索是不断在收敛的,最后也找到了函数的最小值点,经过不断地迭代更新
主函数:
clc;clear
%% Use line search for findind the minimum of f
f=@(x)(x.^2-2.*x+0.28);
x_init=-150;
step=0.9;
iter=400;
[x_best,f_best,x_ind]=line_search(step,x_init,iter);
figure(1)
t=-200:1e-2:200;
plot(t,f(t))
hold on
scatter(x_init,f(x_init),'r','filled')
hold on
plot(x_ind,f(x_ind),'r')
hold on
scatter(x_best,f_best,'g','filled')
legend('objecitve function','start ponit','line search path','minimizer')
hold off
title('Funcion f')
xlabel('x')
ylabel('f')
print('line search path','-djpeg')
%% use a big stepsize for optimization
x_init=0;
step=1.1;
iter=27;
[x_best,f_best,x_ind]=line_search(step,x_init,iter);
figure(2)
t=-200:1e-2:200;
plot(t,f(t))
hold on
scatter(x_init,f(x_init),'k','filled')
hold on
plot(x_ind,f(x_ind),'r')
hold on
scatter(x_best,f_best,'g','filled')
legend('objecitve function','start point','line search path','minimizer')
hold off
title('Funcion f')
xlabel('x')
ylabel('f')
print('line search path with big step','-djpeg')
%% use differnet stepsize and check the convergece rate
step=[1e-1,1e-3,1e-5,1e-7];
x_init=-250;
epsilon=1e-20;
figure(3)
t=-300:0.1:200;
for i=1:size(step,2)
[time,x_ind]=line_search_converge(step(i),x_init,epsilon);
subplot(2,2,i)
scatter(x_init,f(x_init),'k','filled');
hold on
plot(t,f(t),'b')
hold on
plot(x_ind,f(x_ind),'g')
legend('start point','objecitve function','search path')
title(['time: ',num2str(time),'s stepsize: ',num2str(step(i))])
xlabel('x')
ylabel('f')
hold off
end
线性搜索算法:
function [x_best,f_best,x_ind]=line_search(step,x_init,iter)
f=@(x)(x.^2-2.*x+0.28);
step_size=step;
x0=x_init;
maxiter=iter;
grad_f=@(m)(2.*m-2);
x=x0;
x_ind=[];
x_ind=[x_ind;x0];
for i=1:maxiter
grad=grad_f(x);
x=x-step_size.*grad;
x_ind=[x_ind;x];
end
fprintf('the minimizer is obtained at %.2f and the min value of f is %.2f \n',x,f(x))
fprintf('the analytic minimizer is at 1.00 and the min value of f is %.2f \n',f(1))
x_best=x;
f_best=f(x_best);
end
在选取步长时,如果选择地比较大的话,容易导致搜索的发散,导致我们无法找到最优解,但是如果步长选择的太小,那么也存在问题,我们搜索所花费的时间将会比较多,这里仿真的时间看起来步长,主要是因为这是一个简单任务,在实际生活中,我们涉及的很多问题,都很复杂,步长如果太小,所花费的时间将是昂贵的。下面展示了步长过大和步长取小的结果。
步长过大
选取不同步长,收敛所需要的时间比较:
function [time,x_ind]=line_search_converge(step,x_init,epsilon)
f=@(x)(x.^2-2.*x+0.28);
step_size=step;
x0=x_init;
grad_f=@(m)(2.*m-2);
x=x0;
x_ind=[];
x_ind=[x_ind;x0];
tic;
for i=1:100000
x1=x;
grad=grad_f(x);
x=x-step_size.*grad;
x_ind=[x_ind;x];
if abs(x1-x)
在使用线性搜索算法的时候,需要考虑的主要问题时步长的选取,初始值的初始化,以及更新公式的正确性,在涉及到较复杂的线性甚至时非线性问题时,后面会介绍一些自适应和高阶的方法。