Leafar
Leafar

Reputation: 63

Computing argmin of a symbolic function with a lot of variables

I have a data matrix X of size 3065x57 and a column matrix y of size 3065x1, and I want to compute the argmin the function sum defined in the code below.

I tried what is coded below, fminsearch and so on, but none work. Another problem is the fact that I have 57 symbolic variables, so MATLAB computations are very slow.

What can be done to speed up computaions?

function [] = argmin(X,y)
w = transpose(sym('w', [1 57]));
sum = 0;
for i=1:3065
    sum = sum + log(1+exp(transpose(w)*transpose(X(i,:)))) -...
        y(i,1)*transpose(w)*transpose(X(i,:));
end
F = matlabFunction(sum);
argmin = fsolve(F,zeros(1,57))
end

EDIT: I tried the following:

fun = @(w)log(1+exp(transpose([w(1);w(2);w(3);w(4);w(5);w(6);w(7);w(8);w(9);w(10)])*...
    [1;1;1;1;1;1;1;1;1;1]))-...
    transpose([w(1);w(2);w(3);w(4);w(5);w(6);w(7);w(8);w(9);w(10)])*...
    [1;1;1;1;1;1;1;1;1;1]

x0 = [1,1,1,1,1,1,1,1,1,1];
x = fminsearch(fun,x0)

However, I can't do the for loop.

Upvotes: 1

Views: 850

Answers (2)

Durkee
Durkee

Reputation: 778

When using things like fminsearch and fmincon, you don't have to use an anonymous function in the sense you are using it. You can create your own function and make that into an anonymous function.

Also, your minimization variable does not have to be a symbol. As said in the comments this is very slow and unnecessary for your problem.

Code:

function sum = argmin_fun(x,y,w)

sum = 0;

for ii = 1:3065
    sum = sum + log(1 + exp(w'*x(ii,:)')) - y(ii)*w'*x(ii,:)';
end

return

From your script, you can then call

x = randn(3065,57);
y = randn(3065,1);
fun = @(w) argmin_fun(x,y,w);
x0 = ones(57,1);
minimized_vals = fminsearch(fun,x0);

A few notes:

Consider using an options variable so you can set up options parameters such as how well you want it to be optimized, max iterations, as well as other parameters, you can set it up like this.

opts1 = optimset('Display','iter','MaxIter',100);
minimized_vals = fminsearch(fun,x0,opts1);

If you have the optimization toolbox, consider using fmincon or one of the other optimizers, fminsearch is good for problems with 1-10 variables but becomes much less accurate for large scale problems. With fmincon you can also set up boundary constraints for minimum and maximum values. There are workarounds with fminsearch but they aren't as easy to implement.

In terms of performance, the error function of fminsearch achieved an error value of 9637.23 while fmincon achieved an error value of 1945.63 without any constraints added.

[minimized_vals,error_val] = fmincon(fun,x0,[],[]);

Let me know if I missed anything and I'll ammend my answer.

Upvotes: 1

OmG
OmG

Reputation: 18838

If you want remove the loop, you can use matrix operations:

 a = transpose(w)*transpose(X);

a is a vector with size of 1 x 3065 (as w' is 1 x 57 and X' is 57 x 3065). Now you can do the second operation like the following:

b = transpose(y).*a

So, sum would be:

totalSum =  sum(log(1+exp(a)) - b);

You should consider that as the sum is a function in Matlab, it would be better change the name of sum variabletosum`.

In sum, we can remove the loop and replace the loop with the followings:

a = transpose(w)*transpose(X); % w: 57 x 1, X:3065 x 57
b = b = transpose(y).*a; % y: 3065 x 1, a: 1 x 3065
totalSum =  sum(log(1+exp(a)) - b);

It could be so faster than which you write for the first solution.

Upvotes: 1

Related Questions