Supplied objective function must return a scalar value

68 views (last 30 days)
I am trying to code a ML algorithm in Matlab. These are my different functions:
sigmoid.m:
function g = sigmoid(z)
g = zeros(size(z));
g = 1 ./ (1+exp(z));
costFunction.m
function [J, grad ] = costFunction(theta, X, y)
m = length(y); % number of training examples
z = -X * theta;
g = sigmoid(z);
J = 1/m * ((-y * log(g)') - ((1 - y) * log(1 - g)'));
grad = zeros(size(theta'));
grad = (1/m) * (X' * (g - y));
end
ex2.m (This is the main file of my project and I put the relative lines I get this error message)
options = optimset('GradObj', 'on', 'MaxIter', 400);
[theta, cost] = ...
fminunc(@(t)(costFunction(t, X, y)), initial_theta, options);
The error message:
> Error using fminunc (line 348) Supplied objective function must return Supplied objective function must return
> a scalar value.
>
> Error in ex2 (line 97) fminunc(@(t)(costFunction(t, X, y)),
> initial_theta, options);
I don't know is there enough information above or not? If not, let me know to add extra information.
  2 Comments
Jay Guwalani
Jay Guwalani on 19 Nov 2021
% Try using this in cost function || I guess the issue is with the (.)
% elementwise ops
H=sigmoid(X*theta);
J=(sum(-y.*log(H)-(1-y).*log(1-H))/m);
grad=(1/m)*(X'*(H-y));

Sign in to comment.

Accepted Answer

reza
reza on 20 Jan 2019
Edited: reza on 20 Jan 2019
I changed the following line of code:
J = 1/m * ((-y * log(g)') - ((1 - y) * log(1 - g)'));
To the following line of code:
J = 1/m * (((-y)' * log(g)) - ((1 - y)' * log(1 - g)));
And problem solved!
The y and g were 100*1 matrices and with previous code I had J=100*100 matrix, but with new code I have J=1*1 matrix or scalar number and problem solved!
  1 Comment
Rik
Rik on 20 Jan 2019
Since it is the conclusion of my answer that you needed to change something to achieve a scalar output, I would say this derives from my answer, but anyway, happy to help.
This also shows the value of comments: I had no way of knowing what your code does, so I could only point you in a general direction. If you want your code understandable to others, make sure to write comments and function headers. Some people go as far as saying you should have a line of comment for every line of code, but I would say that is being excessive.

Sign in to comment.

More Answers (1)

Rik
Rik on 20 Jan 2019
Depending on your input variable sizes, your code is not guaranteed to return the same size output as the input size. The documentation of fminunc states the following:
"fun is a function that accepts a vector or array x and returns a real scalar f, the objective function evaluated at x."
The initial_theta determines the size of the theta that the solver will use.
Also, I can't find a sigmoid function in the Matlab doc. Do you mean this FEX entry?
%to more easily explain what's going on, assign some names to dimensions:
[a,b]=size(X);[c,d]=size(y);
[e,f]=size(initial_theta);
And now to your function:
function [J, grad ] = costFunction(theta, X, y)
m = length(y); % number of training examples
%m is either c or d
z = -X * theta;
%z is [a,f], unless theta is a scalar, then z is [a,b]
g = sigmoid(z);
%same as z (so [a,b] or [a,f])
J = 1/m * ((-y * log(g)') - ((1 - y) * log(1 - g)'));
%1/m is a scalar
%(-y * log(g)') is [c,d]*[f,a] or [c,d]*[b,a], so [c,a], but will error if d and b (or d and f) are not equal
%((1 - y) * log(1 - g)') is the same size as the other term
%so J is [c,a], unless this line returns an error
grad = zeros(size(theta'));
%this line doesn't do anything, as grad gets overwritten
grad = (1/m) * (X' * (g - y));
%1/m is scalar
%(X' * (g - y)) is [b,a]*[c,d] so [b,d] and asserts that a==c and that [a,b] (or [a,f]) is the same as [c,d]
end
So this function places quite a lot of implicit restrictions on your inputs.
To successfully evaluate, the following must all be true:
[a,b]=size(X);[c,d]=size(y);
[e,f]=size(initial_theta);
theta_is_scalar=numel(theta)==1;
%J restrictions
assert(a==1)
assert(c==1)
if theta_is_scalar
assert(d==f)%so assert(d==1)
else
assert(b==e)
assert(b==d)
end
%grad restrictions
assert(b==1)
assert(c==1)
assert(a==c)
if theta_is_scalar
%[a,b] is [c,d]
assert(b==d)
else
%[a,f] is [c,d]
assert(f==d)
end
Concluding this:
%scalar theta:
X must be [1,1]
y must be [1,1]
%non-scalar theta:
X must be [1,1]
y must be [1,1]
initial_theta must be [1,1]
So all the inputs must be scalar.
  5 Comments
Rik
Rik on 16 Jul 2020
Why are you using globals?
And if the error is the same, it is likely that the solution is also the same: make sure your objective function returns a scalar.
Walter Roberson
Walter Roberson on 16 Jul 2020
The user posted this elsewhere, and I responded there. The syms x [1 4] is a problem and it cannot be fixed without redefining the calculation.

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!