fminunc error message multiple variables

Hello everyone!
I want to minimize the following function that I wrote:
function ll = ll_wbl(A, N, Y, X, sum_ll)
%A=theta, A(1)=beta, A(2)=kappa
lambda=exp(X*A(1));
ll=N*log(A(2))+(A(2)-1).*log(Y)-A(2).*log(lambda)-(Y./lambda).^A(2);
ll=-ll;
if sum_ll==true
ll=sum(ll);
end
%grad=sum(Y.*X);
end
over the vector A by using fminunc:
clc; clear;
data = xlsread('ema1996_reduced.xls', 'Sheet1');
UNDUR = data(:,1);
UI = data(:,2);
RR = data(:,3);
RRUI=data(:,4);
DR=data(:,5);
DRUI=data(:,6);
LWAGE=data(:,7);
TENURE=data(:,8);
NONWHITE=data(:,9);
% Store as Y and X matrices
N = size(data, 1);
Y = UNDUR;
X = [ones(N, 1) UI RR RRUI DR DRUI LWAGE TENURE NONWHITE];
A0=zeros(2,1);
% Optmizer settings
options = optimoptions(@fminunc, 'Algorithm', 'quasi-newton');
% Estimate model
[A, fval, exitflag, output ] = fminunc(@ll_wbl, A0, options, Y, X, true);
Unfortunately, this doesn't work out somehow.
I get the following error:
Not enough input arguments.
Error in ll_wbl (line 9)
if sum_ll==true
Error in fminunc (line 278)
f = feval(funfcn{3},x,varargin{:});
Caused by:
Failure in initial objective function evaluation. FMINUNC cannot continue.
I don't understand what's going on here since I am a newbie. Maybe someone can help me out?
Thanks in advance!

 Accepted Answer

Hi,
fminunc is only able to pass the optimization variable to the objective function. Since your function needs additionally input arguments, you need to pass them to the objective function.
Read here:
Best regards
Stephan

12 Comments

Hi,
thanks for your answer. I'm sorry, I'm not familiar with MATLAB language. Do you mean pass a variable, that I need to include the variable 'N' in my objective function since my function also needs N as an input?
I tried to do it but still get an error:
Input:
A0=zeros(2,1);
% Optmizer settings
options = optimoptions(@fminunc,'Algorithm','quasi-newton');
% Estimate model
[A, fval, exitflag, output] = fminunc(@ll_wbl, A0, options, N, Y, X, true);
Output:
A0=zeros(2,1);
% Optmizer settings
options = optimoptions(@fminunc,'Algorithm','quasi-newton');
% Estimate model
[A, fval, exitflag, output] = fminunc(@ll_wbl, A0, options, N, Y, X, true);
Error using fminunc (line 352)
FMINUNC requires all values returned by functions to be of data type double.
In your case it should look like:
[A, fval, exitflag, output] = fminunc(@(A)ll_wbl(A, N, Y, X, sum_ll), A0, options);
Note that you will have to define
sum_ll =true;
before your fminunc call
Hi Stephan,
thank you so much for your effort!
Unfortunately, when I run the script:
A0=[0 0];
% Optmizer settings
options = optimoptions(@fminunc,'Algorithm','quasi-newton');
% Estimate model
[A, fval, exitflag, output] = fminunc(@(A)ll_wbl(A, N, Y, X, true), A0, options);
I still get an error message:
A0=[0 0];
% Optmizer settings
options = optimoptions(@fminunc,'Algorithm','quasi-newton');
sum_ll=true;
% Estimate model
[A, fval, exitflag, output] = fminunc(@(A)ll_wbl(A, N, Y, X, sum_ll), A0, options);
Error using fminunc (line 352)
FMINUNC requires all values returned by functions to be of data type double.
Also when defining sum_ll=true before running fminunc I get the same error message and cannot find where I went wrong... :(
your function sets the result
ll = sum_ll
which results in data type logical not double. use this instead:
ll = double(sum_ll)
There was one mistake in my function. I wanted to have the option that the function calculates the sum over all ll values, so the script of the function must be:
function ll = ll_wbl(A,N, Y, X, sum_ll)
%A=theta, A(1)=beta, A(2)=kappa
lambda=exp(X*A(1));
ll=N*log(A(2))+(A(2)-1).*log(Y)-A(2).*log(lambda)-(Y./lambda).^A(2);
ll=-ll;
if sum_ll==true
ll = sum(ll);
end
end
(I edited my original post).
Using the same script as before:
A0=[0 0];
% Optmizer settings
options = optimoptions(@fminunc,'Algorithm','quasi-newton');
% Estimate model
[A, fval, exitflag, output] = fminunc(@(A)ll_wbl(A, N, Y, X, true), A0, options);
Still using double or not using it I get the following error:
Error using fminunc (line 357)
Supplied objective function must return a scalar value.
My function ll_wbl returns a 1x9 double matrix when using sum_ll=true. Is this the problem?
yes this is not allowed. the result which has to be minimized has to be a scalar.
is ll a matrix?
the you can sum the values this way (in R2018b):
ll = sum(ll,'all');
in other releases use:
ll = sum(sum(ll))
But the strange thing is, I tried the exact same thing with another distribution, there my function returns a 1x2 double matrix using sum_ll=true and everything works out:
function:
function ll = ll_poisson(beta, Y, X, sum_ll)
lambda = exp(X * beta);
ll = Y .* log(lambda) - log(factorial(Y)) - lambda;
ll = -ll;
if sum_ll == true
ll = sum(ll);
end
end
script:
n = 200;
b0 = 1;
b1 = 1;
b = [b0 b1]';
% Simulate data
X = [ones(n,1) rand(n,1)];
lambda = exp(X*b);
Y = poissrnd(lambda);
% Initial parameter vector
beta0 = zeros(2, 1);
% Optmizer settings
options = optimoptions(@fminunc, 'Algorithm', 'quasi-newton');
% Estimate model
[beta, fval, exitflag, output ] = fminunc(@ll_poisson, beta0, options, Y, X, true);
I don't get how poisson works out but wbl doesn't since in my opinion it's the exact same thing just using other functions & dimensions of matrices.
consider:
x = ones(1,5)
sum(x)
y = ones(5,1)
sum(y)
z = ones(3,3)
sum(z)
but:
sum(sum(z))
So if you apply sum to a vector no matter if row or column vector ,the result is a scalar .If you apply it to a matrix the result is a vector and you have to sum this again to get a scalar.
I think if I sum up the sum my objective is the wrong one for calculating the Maximum Likelihood estimator for the function (which is my goal).
I'm not sure but there must be another possibility since it also worked for my poisson function.
your poisson function returns a scalar. fminunc returns 2 values, the result of the Optimization, but the function gives back a single value - this is why it works.
you can check this by removing the semicolon operator in this line:
ll = sum(ll);
fmincon calls the function severeal times, and in every call tgere comes ll as a scalar value back as result.
Allright, I see the difference.
Then it might be useful to use sum(sum(ll)) although I still have to think about if it gives me what I want to :)
Thank you so much for your effort!!!
please accept useful answers. i wish you success !

Sign in to comment.

Asked:

on 6 Jan 2019

Commented:

on 6 Jan 2019

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!