0

I'm fairly new to matlab. I understand how to use fminsearch and that works well for finding a single parameter. However, I'd like to optimize a few parameters. Can someone help demonstrate how I could implement the following. In this case, SolveForParameters returns the optimal parameters a, b, and c by minimizing the residual, which is computed from CalculateResidual. I realize there are probably multiple ways to do this (eg, nls, mle, etc), but any examples are appreciated. In this example, input1, input2, and input3 are constant during the optimization and are also vectors.

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

Thanks!

2
  • Are input1, input2 and input3 all static? That is, do these change over time?... or are they constant during the optimization? You didn't specify what these parameters are. Commented Aug 11, 2015 at 17:25
  • Sorry, they are static. Commented Aug 11, 2015 at 17:28

1 Answer 1

3

You're pretty close. What you have to do is place all of the parameters that you want to optimize into a single vector . Also, inside the residual function you want to minimize, the inputs must also be in a vector. Therefore, a, b, c would be passed in as a vector into your residual function, and input1, input2, input3 are constant and don't change over the evolution of the search. These are also vectors of the same length.

Therefore, you really just have to do this. First, change your residual function so that it accepts a vector parameter of inputs:

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

Now, just call fminsearch normally but specifying a vector of parameters as the starting position:

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

The first input is a function that you are trying to minimize. In this case, we provide a handle to CalculateResidual with input1, input2, input3 all being static. This is required because the function you want to minimize for fminsearch can only accept a signature with one input argument - namely the parameters to be optimized at a certain iteration. You then specify the initial starting points as a vector.

Once you have that, then you should be solid! You would then unwrap the parameters from the output and assign them to a,b,c, so:

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

To piece it all together, your code would look like this:

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

Running the above code with input1 = sin(1:10), input2 = cos(1:10), input3 = tan(1:10) gives me the following a,b,c given the start positions:

>> 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

You get that exit warning because we couldn't quite minimize the residuals given the default number of iterations. You can increase the total number of iterations by increasing the number of function evaluations and maximum iterations the optimization routine takes. That can be done with optimset. Therefore, let's change your code slightly:

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

Doing options = optimset('fminsearch'); generates the default parameters used in fminsearch. We then override the defaults by changing the number of function evaluations and number of iterations to 10000. We also provide this as an additional parameter to fminsearch to let the function know we are providing some changes to the default parameters for the optimization routine.

By doing this, we now get:

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

a =

   7.4210e-07


b =

  325.4225


c =

   -2.0911
Sign up to request clarification or add additional context in comments.

5 Comments

I am very sorry. input1, 2, and 3 were meant to be vectors. I updated the code above. Could you modify?
@CodeGuy - Done. Have a look.
Question: let's say that I want "a" to be a whole number. For example, let's say in my residual I need to grab element "a" from input1. How could I do this? How could I force the optimizer to find an integer for one of the parameters?
If you want to force a to be integer, that's a completely different ballgame. You'll want to look at Mixed Integer Linear Programming. Try MATLAB's intlinprog function: mathworks.com/help/optim/ug/intlinprog.html. If you want a to be integer, that would require me to change my entire answer.... and I think you should perhaps post that as a new question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.