在matlab中求解多个参数

时间:2015-08-11 17:11:05

标签: matlab optimization

我对matlab很新。我理解如何使用fminsearch,这对于查找单个参数非常有用。但是,我想优化一些参数。有人可以帮助演示我如何实现以下内容。在这种情况下,SolveForParameters会通过最小化从a计算的残差来返回最佳参数bcCalculateResidual。我意识到可能有多种方法可以做到这一点(例如,nlsmle等),但是任何例子都值得赞赏。在此示例中,input1input2input3在优化期间是常量,也是向量。

function [a,b,c] = SolveForParameters(input1, input2, input3, a, b, c) 
     %finds the parameters a, b, and c by minimizing the function CalculateResidual

     startA = 3; 
     startB = 1;
     startC = 0;

     %...EXAMPLE IMPLEMENTATION HERE...
end

function residual = CalculateResidual(input1, input2, input3, a, b, c)
    %for example
    residual = (sum(input1*(a-b)) + sum(input2)*sqrt(a*1.5)*a) / (sum(input3+b) + sum(input2/log(sum(input1))/(a+c)))
end

谢谢!

1 个答案:

答案 0 :(得分:2)

你非常接近。您需要做的是将要优化的所有参数放入单个向量。此外,在要最小化的剩余函数内,输入也必须在向量中。因此,a, b, c将作为向量传入您的残差函数,input1, input2, input3是常量,不会改变搜索的演变。这些也是相同长度的载体。

因此,你真的必须这样做。首先,更改残差函数,使其接受输入的矢量参数:

function residual = CalculateResidual(x, input1, input2, input3)
%for example
a = x(1); b = x(2); c = x(3); %// Change here
residual = (sum(input1*(a-b)) + sum(input2)*sqrt(a*1.5)*a) / (sum(input3+b) + sum(input2/log(sum(input1))/(a+c)));
end

现在,只需正常调用fminsearch,但指定一个参数向量作为起始位置:

X = fminsearch(@(x) CalculateResidual(x, input1, input2, input3), [startA;startB;startC]);

第一个输入是您尝试最小化的功能。在这种情况下,我们提供CalculateResidual的句柄,其中input1, input2, input3都是静态的。这是必需的,因为要为fminsearch最小化的函数只能接受带有一个输入参数的签名 - 即在某次迭代时要优化的参数。然后,将初始起点指定为矢量。

一旦你拥有了,那么你应该坚强!然后,您将从输出中解开参数并将它们分配给a,b,c,所以:

a = X(1); b = X(2); c = X(3);

要将它们拼凑在一起,您的代码将如下所示:

function [a,b,c] = SolveForParameters(input1, input2, input3) 
     %finds the parameters a, b, and c by minimizing the function CalculateResidual

     startA = 3; 
     startB = 1;
     startC = 0;

     X = fminsearch(@(x) CalculateResidual(x, input1, input2, input3), [startA;startB;startC]);

    a = X(1); b = X(2); c = X(3); %// Final assignment
end

function residual = CalculateResidual(x, input1, input2, input3)
    %for example
    a = x(1); b = x(2); c = x(3); %// Change here
    residual = (sum(input1*(a-b)) + sum(input2)*sqrt(a*1.5)*a) / (sum(input3+b) + sum(input2/log(sum(input1))/(a+c)));
end

使用input1 = sin(1:10), input2 = cos(1:10), input3 = tan(1:10)运行上述代码会给出以下a,b,c给出的起始位置:

>> format long g;
>> [a,b,c] = SolveForParameters(1:10, 11:20, 21:30)

Exiting: Maximum number of function evaluations has been exceeded
         - increase MaxFunEvals option.
         Current function value: -5.127366 


a =

   2.6014e-06


b =

  325.4224


c =

   -2.0911

您会收到退出警告,因为在给定默认迭代次数的情况下,我们无法将残差最小化。您可以通过增加函数求值的数量和优化例程所需的最大迭代次数来增加迭代总数。这可以通过optimset来完成。因此,让我们稍微改变您的代码:

function [a,b,c] = SolveForParameters(input1, input2, input3) 
     %finds the parameters a, b, and c by minimizing the function CalculateResidual

     startA = 3; 
     startB = 1;
     startC = 0;

     %// New - Change optimization options
    options = optimset('fminsearch');
    options.MaxFunEvals = 10000;
    options.MaxIter = 10000;

     %// New - also include options for optimization
     X = fminsearch(@(x) CalculateResidual(x, input1, input2, input3), [startA;startB;startC], options);

    a = X(1); b = X(2); c = X(3); %// Final assignment
end

function residual = CalculateResidual(x, input1, input2, input3)
    %for example
    a = x(1); b = x(2); c = x(3); %// Change here
    residual = (sum(input1*(a-b)) + sum(input2)*sqrt(a*1.5)*a) / (sum(input3+b) + sum(input2/log(sum(input1))/(a+c)));
end

执行options = optimset('fminsearch');会生成fminsearch中使用的默认参数。然后,我们通过将函数评估的数量和迭代次数更改为10000来覆盖默认值。我们还将此作为fminsearch的附加参数提供,以使函数知道我们正在为优化的默认参数提供一些更改例程。

通过这样做,我们现在得到:

>> [a,b,c] = SolveForParameters(1:10, 11:20, 21:30)

a =

   7.4210e-07


b =

  325.4225


c =

   -2.0911