如何在不使用循环的情况下最小化函数

时间:2016-07-27 09:15:25

标签: matlab function minimization

我有一个函数(ExpSemivariance),它创建了一个包含11个元素的向量。然后,这些元素在散点图中以图形表示,我打算通过使用最小残差(在这种情况下,但可以使用任何其他最小化函数)找到最适合“ExpSemivariance”的曲线(理论)

Nug = 5;
Sill = 7899;
alpha = 1.7;

Step = 10;
q = 11;

      for i=1:q
          Theoretical(i,1) = Nug+Sill*(1-exp(-(Lag(i,1)/R)^alpha));
      end
      Error = sum(abs(Theoretical-ExpSemivariance));
      while Step > 1
          R = R + Step;
          for i=1:q
              Theoretical(i,1) = Nug+Sill*(1-exp(-(Lag(i,1)/R)^alpha));
          end
          error = sum(abs(Theoretical-ExpSemivariance));
          if error > Error
              R = R - Step;
              Step = Step/2;
          else
              Error = error;
          end
      end

唯一的变量是'R',上面的脚本工作得很好。

问题是,我假设alpha是1.7。但实际上我需要同时找到正确的α值(范围从1:2,步长0.1)和R(范围从1-4000),这最大限度地减少了误差(在ExpSemivariance和理论之间)。有没有合适的方法来做到这一点?

由于

1 个答案:

答案 0 :(得分:0)

我认为你最好调查mathematical optimization,因为我的印象是你试图重新发明轮子(例如sum(abs(x))sum(x.^2)少得多。在优化中,因为后者更容易解决,因为后者的衍生物很容易计算;而且,你选择step的方式对我来说似乎有点不常见。)

在MATLAB中,如果您有优化工具箱,则已经为您实现了许多相关算法。它们是获得良好结果的可靠方法(除非您希望完全控制您使用的优化算法),这样您就不必滚动自己的算法(可能不那么可靠)。此外,如果您浏览互联网,我非常肯定您应该能够找到具有类似功能的免费实施。

方法1:离散网格/强力

如果你想要什么,真的是为了最小化你的函数和数据之间的错误匹配R = {1, ..., 4000}alpha = {1, 1.1, ..., 2}的某些离散值,那么我会使用for循环覆盖所有那些变量或使用矢量化可能加快这一点。

% still requires Lag, ExpSemivariance
Nug   = 5;
Sill  = 7899;

model = @(R, alpha) Nug + Sill .* ( 1 - exp(-(Lag./R).^alpha));
cost  = @(R, alpha) sum(abs(model(R, alpha) - ExpSemivariance));

R     = 1:4000;
alpha = 1:0.1:2;

% this creates matrices (RR, alphaalpha) for all combinations of values (R, alpha)
[RR, alphaalpha] = ndgrid(R, alpha);

% now evaluate it over the complete grid of combinations
error = arrayfun(cost, RR, alphaalpha);

errorMin   = min(error(:));         % compute the minimum
idxMinimum = find(error==errorMin); % find it in your results
RMin       = RR(idxMinimum);
alphaMin   = alphaalpha(idxMinimum);

% since this is 2D, you can still visualize this:
figure;
mesh(R, alpha, error); hold all;
plot3(RMin, alphaMin, errorMin, '.k')
xlabel('R');
ylabel('alpha');
zlabel('error');

当然,有更好的算法(但我对它们不够熟悉;我所知道的一切都是它一般都是一个非常难的问题)。 另外,请注意我的方法非常蛮力,因此扩展性很差:添加更多变量,或扫描更精细的网格将很快耗尽您的计算机资源。如果是这种情况,那么逐渐扫描网格确实是值得的,或者使用多个for循环来跟踪到目前为止看到的最佳值。

方法2:基于连续变量/优化

这是优化中更常见的问题(而且,我认为,您也试图解决的问题)。它假设Ralpha是实数值(因此可以取任何值,可能在一定范围内),这样您就可以让优化算法为您进行循环,以确定最小化的值目标函数。

在您的情况下,如果您确定Ralpha的范围,我会调查fmincon函数。从我的头脑(即不保证代码工作),我认为你应该能够称之为:

% still requires Lag, ExpSemivariance
Nug  = 5;
Sill = 7899;

R     = [1 10  4000]; % minimum, initial guess, maximum
alpha = [1 1.7 2   ]; % minimum, initial guess, maximum
theta = [R; alpha];   % parameter vector for optimization toolbox
thetaMin  = theta(:,1);
thetaMax  = theta(:,3);
thetaInit = theta(:,2);

model     = @(R, alpha) Nug + Sill .* ( 1 - exp(-(Lag./R).^alpha));
error     = @(R, alpha) sum(abs(model(R, alpha) - ExpSemivariance));
objective = @(theta) error(theta(1), theta(2));

% execute "help fmincon"/"doc fmincon" for more information about this
thetaOpt = fmincon(objective, thetaInit, [], [], [], [], thetaMin, thetaMax);
RMin     = thetaOpt(1)
alphaMin = thetaOpt(2)

这种方法很好地概括了更多的变量和更大的范围(实际上,使用这种方法甚至无限范围也是可行的)。

实际循环发生在fmincon内,它使用经过良好测试的算法来确定应该采取哪些步骤来改善您的拟合。它并非完全万无一失,因为具有良好的初始值使得在更短的时间内更有可能获得更好的Ralpha值。但要学习进出,您应该深入研究优化理论和/或优化工具箱的文档。如果您的效果不佳,我建议您先尝试将abs(x)更改为(x).^2,因为对于大多数优化算法来说,这样做要容易得多。