【问题标题】:Is there a faster way to solve my newton algorithm?有没有更快的方法来解决我的牛顿算法?
【发布时间】:2019-12-15 01:29:36
【问题描述】:

我有这个牛顿算法,它似乎要花很长时间才能找到解决方案。以至于我让它坐了一整夜,什么也没发生。我想知道这是我做错了什么还是我遗漏了什么。

Gobs=[0.61 1.14 2.33 4.76 6.65 4.77 2.38 1.13 0.59];
x=[-3.0, -2.5, -2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.5];
syms m h
p1=[m;h];

F = ((((6.67*p1(1)*p1(2))/((x(1)^2)+p1(2)^2)^(3/2))-Gobs(1))^2+(((6.67*p1(1)*p1(2))/((x(2)^2)+p1(2)^2)^(3/2))-Gobs(2))^2 + (((6.67*p1(1)*p1(2))/((x(3)^2)+p1(2)^2)^(3/2))-Gobs(3))^2 + (((6.67*p1(1)*p1(2))/((x(4)^2)+p1(2)^2)^(3/2))-Gobs(4))^2 + (((6.67*p1(1)*p1(2))/((x(5)^2)+p1(2)^2)^(3/2))-Gobs(5))^2 + (((6.67*p1(1)*p1(2))/((x(6)^2)+p1(2)^2)^(3/2))-Gobs(6))^2 + (((6.67*p1(1)*p1(2))/((x(7)^2)+p1(2)^2)^(3/2))-Gobs(7))^2 + (((6.67*p1(1)*p1(2))/((x(8)^2)+p1(2)^2)^(3/2))-Gobs(8))^2 + (((6.67*p1(1)*p1(2))/((x(9)^2)+p1(2)^2)^(3/2))-Gobs(9))^2);

dfm = diff(F,'m');
dfh = diff(F,'h');
d2fm = diff(dfm,'m'); 
d2fh = diff(dfh,'h');
dfmh = diff(dfm,'h');
dfhm = diff(dfh,'m');
G = [dfm;dfh];
Hnewton = [d2fm dfmh; dfmh d2fh];    

m =1.6;
h =1.7;

p1 = subs(p1);
n=1;
tm(n)=p1(1);
th(n)=p1(2);
for i=1:2
F1 = subs(F);
p2 = p1-(subs(Hnewton)+ (100/n)*eye(2))\subs(G);
m=p2(1);
p=p2(2);
F2 = subs(F);
if (F2)>0.9;
p1 = p2;
m=p2(1);
h=p2(2);
else break
end
n=n+1;
tm(n)=p2(1);
th(n)=p2(2);
end

plot(th,tm,'r-','LineWidth',1.4)

【问题讨论】:

  • 很难遵循您的代码,但是将所有内容都保留为符号变量总是会使代码非常慢。使用 diff 找到所需的所有函数后,使用 matlabFunction 将它们转换为快速匿名函数。
  • 哦,好吧,我会尽量不使用它们。我尝试转换,它说我不能使用非标量数组,我试图将其转换为单元格,但这也不起作用。
  • 我尝试将它们转换为函数句柄,但是我在调​​整其余代码时遇到了问题。
  • @ChelseaG。matlab 中没有函数句柄的导数。sym 变量仅用于计算给定函数的gradienthessian .在函数评估中,这两个被转换为函数句柄并确保它们的输入是向量
  • @MiroFeliciano 使用内置函数gradient()hessian。为了评估它们都被转换成函数句柄,不要使用subs。提供函数本身和优化的已知值,我会发布适当的答案。

标签: matlab newtons-method


【解决方案1】:

定义要优化的函数的两个版本:

  • F_eval 函数句柄类型用于评估F

  • F syms 函数用于梯度hessian矩阵

要评估梯度G 和hessian 矩阵Hnewton,使用它们对应的函数句柄

% Gradient
G_eval = matlabFunction(G,'Vars',{[m h]});

% Hessian 
Hnewton_eval = matlabFunction(Hnewtonn,'Vars',{[m h]}); 

还有循环停止条件错误:

使用两个连续函数评估之间的差异

阅读下面的代码


clc
clear
syms m h
p1 = [m h];

Gobs=[0.61 1.14 2.33 4.76 6.65 4.77 2.38 1.13 0.59];
x=[-3.0, -2.5, -2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.5];
% Define the input known array x first 
% Used only for gradient and hessian, syms function  
F =(...
    (((6.67*p1(1)*p1(2))/((x(1)^2)+p1(2)^2)^(3/2))-Gobs(1))^2 ...
    +(((6.67*p1(1)*p1(2))/((x(2)^2)+p1(2)^2)^(3/2))-Gobs(2))^2 ...
    +(((6.67*p1(1)*p1(2))/((x(3)^2)+p1(2)^2)^(3/2))-Gobs(3))^2 ...
    +(((6.67*p1(1)*p1(2))/((x(4)^2)+p1(2)^2)^(3/2))-Gobs(4))^2 ... 
    +(((6.67*p1(1)*p1(2))/((x(5)^2)+p1(2)^2)^(3/2))-Gobs(5))^2 ... 
    +(((6.67*p1(1)*p1(2))/((x(6)^2)+p1(2)^2)^(3/2))-Gobs(6))^2 ...
    +(((6.67*p1(1)*p1(2))/((x(7)^2)+p1(2)^2)^(3/2))-Gobs(7))^2 ...
    +(((6.67*p1(1)*p1(2))/((x(8)^2)+p1(2)^2)^(3/2))-Gobs(8))^2 ... 
    +(((6.67*p1(1)*p1(2))/((x(9)^2)+p1(2)^2)^(3/2))-Gobs(9))^2 ...
   );
% Used for evaluating the function , function handle 
F_eval = @(p)...
    (...
    (((6.67*p(1)*p(2))/((x(1)^2)+p(2)^2)^(3/2))-Gobs(1))^2 ...
    +(((6.67*p(1)*p(2))/((x(2)^2)+p(2)^2)^(3/2))-Gobs(2))^2 ...
    +(((6.67*p(1)*p(2))/((x(3)^2)+p(2)^2)^(3/2))-Gobs(3))^2 ...
    +(((6.67*p(1)*p(2))/((x(4)^2)+p(2)^2)^(3/2))-Gobs(4))^2 ... 
    +(((6.67*p(1)*p(2))/((x(5)^2)+p(2)^2)^(3/2))-Gobs(5))^2 ... 
    +(((6.67*p(1)*p(2))/((x(6)^2)+p(2)^2)^(3/2))-Gobs(6))^2 ...
    +(((6.67*p(1)*p(2))/((x(7)^2)+p(2)^2)^(3/2))-Gobs(7))^2 ...
    +(((6.67*p(1)*p(2))/((x(8)^2)+p(2)^2)^(3/2))-Gobs(8))^2 ... 
    +(((6.67*p(1)*p(2))/((x(9)^2)+p(2)^2)^(3/2))-Gobs(9))^2 ...
   );


% Gradient and Hessian in syms 
G = gradient(F);
Hnewton = hessian(F);

%% Tranform into function handle


G_eval = matlabFunction(G,'Vars',{[m h]});

Hnewton_eval = matlabFunction(Hnewton,'Vars',{[m h]});

%% Starting guess
m = 1.6;
h =1.7;
n = 1;
pold = [m h];

%% Record 
% First column is m, second is h
solution_history = pold;

%% Infinite loop
while true

     % Use function handle only for evaluation
     F1 = F_eval(pold);

     psol = pold -(Hnewton_eval(pold)+ (100/n)*eye(2))\G_eval(pold);

     [l,~] = size(psol);

     F2_best = F_eval(psol(1, :));
     p_best = psol(1, :);

     % Find the solution which minimize the most F
     for i = 1:l
         if  F_eval(psol(i, :)) < F2_best
             F2_best = F_eval(psol(i, :));
             p_best = psol(1, :);
         end
     end

    F2 = F2_best;
    pnew = p_best;
     solution_history = [solution_history; pnew];

     n = n + 1;

     pold = pnew;
     % Insert stopping condition here  
      if n == 5
          break;
      end

end

tm = solution_history(:, 1);
th = solution_history(:, 2);

plot(th,tm,'r-','LineWidth',1.4)

【讨论】:

  • 哦,没想过用两个版本的功能,谢谢!虽然我在p2 = p1 -(Hnewton_eval(p1)+ (100/n)*eye(2))\G_eval(p1); 行中收到错误,说我没有足够的论据,而且我不明白为什么。
  • 我还编辑了主要问题以包括 Gobsx,这也丢失了。附言我的 MatLab 版本是 R2015a。
  • @MiroFeliciano 答案已更新,只是在使用 matlabFunction() 时错过了大括号。你的停止条件很奇怪。
  • 我的停止标准是基于等高线水平的,所以当它低于某个水平时它会停止。我不得不转置您发布的一些变量,因为矩阵的大小不同。我的问题是我怎样才能迭代地做到这一点?因为你的while循环我猜它只做一次,我想要更多次
  • 非常感谢,它工作正常!我唯一的问题是它不是我想要的,但也许这是我的错误表述
猜你喜欢
  • 2019-11-11
  • 2012-06-24
  • 2015-06-22
  • 2015-01-18
  • 1970-01-01
  • 1970-01-01
  • 2015-08-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多