计算具有大量变量的符号函数的 argmin
Computing argmin of a symbolic function with a lot of variables
我有一个大小为 3065x57 的数据矩阵 X
和一个大小为 3065x1 的列矩阵 y
,我想计算 argmin
定义的函数 sum
在下面的代码中。
我尝试了下面的编码,fminsearch
等等,但是 none 有效。
另一个问题是我有 57 个符号变量,因此 MATLAB 计算非常慢。
如何加快计算速度?
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
编辑:我尝试了以下方法:
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)
但是,我无法执行 for
循环。
当使用 fminsearch
和 fmincon
之类的东西时,您不必在使用它的意义上使用匿名函数。您可以创建自己的函数并将其变成匿名函数。
此外,您的最小化变量不必是符号。正如评论中所说,这对于您的问题来说非常缓慢且不必要。
代码:
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
然后您可以从您的脚本中调用
x = randn(3065,57);
y = randn(3065,1);
fun = @(w) argmin_fun(x,y,w);
x0 = ones(57,1);
minimized_vals = fminsearch(fun,x0);
一些注意事项:
考虑使用一个选项变量,这样你就可以设置选项参数,比如你希望优化它的程度、最大迭代次数,以及其他参数,你可以这样设置。
opts1 = optimset('Display','iter','MaxIter',100);
minimized_vals = fminsearch(fun,x0,opts1);
如果您有优化工具箱,请考虑使用 fmincon
或其他优化器之一,fminsearch
适用于具有 1-10 个变量的问题,但对于大规模问题而言准确性要低得多。使用 fmincon
您还可以为最小值和最大值设置边界约束。 fminsearch
有变通办法,但实施起来并不容易。
在性能方面,fminsearch
的误差函数实现了9637.23的误差值,而fmincon
在没有添加任何约束的情况下实现了1945.63的误差值。
[minimized_vals,error_val] = fmincon(fun,x0,[],[]);
如果我遗漏了什么,请告诉我,我会修改我的答案。
如果要去除循环,可以使用矩阵运算:
a = transpose(w)*transpose(X);
a
是一个大小为 1 x 3065 的向量(因为 w'
是 1 x 57 而 X'
是 57 x 3065)。
现在你可以像下面这样进行第二个操作:
b = transpose(y).*a
因此,sum
将是:
totalSum = sum(log(1+exp(a)) - b);
你应该考虑到 sum
是 Matlab 中的一个函数,最好更改 sum
变量的名称to
sum`。
总而言之,我们可以删除循环并用以下内容替换循环:
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);
它可能比您为第一个解决方案编写的速度更快。
我有一个大小为 3065x57 的数据矩阵 X
和一个大小为 3065x1 的列矩阵 y
,我想计算 argmin
定义的函数 sum
在下面的代码中。
我尝试了下面的编码,fminsearch
等等,但是 none 有效。
另一个问题是我有 57 个符号变量,因此 MATLAB 计算非常慢。
如何加快计算速度?
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
编辑:我尝试了以下方法:
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)
但是,我无法执行 for
循环。
当使用 fminsearch
和 fmincon
之类的东西时,您不必在使用它的意义上使用匿名函数。您可以创建自己的函数并将其变成匿名函数。
此外,您的最小化变量不必是符号。正如评论中所说,这对于您的问题来说非常缓慢且不必要。
代码:
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
然后您可以从您的脚本中调用
x = randn(3065,57);
y = randn(3065,1);
fun = @(w) argmin_fun(x,y,w);
x0 = ones(57,1);
minimized_vals = fminsearch(fun,x0);
一些注意事项:
考虑使用一个选项变量,这样你就可以设置选项参数,比如你希望优化它的程度、最大迭代次数,以及其他参数,你可以这样设置。
opts1 = optimset('Display','iter','MaxIter',100);
minimized_vals = fminsearch(fun,x0,opts1);
如果您有优化工具箱,请考虑使用 fmincon
或其他优化器之一,fminsearch
适用于具有 1-10 个变量的问题,但对于大规模问题而言准确性要低得多。使用 fmincon
您还可以为最小值和最大值设置边界约束。 fminsearch
有变通办法,但实施起来并不容易。
在性能方面,fminsearch
的误差函数实现了9637.23的误差值,而fmincon
在没有添加任何约束的情况下实现了1945.63的误差值。
[minimized_vals,error_val] = fmincon(fun,x0,[],[]);
如果我遗漏了什么,请告诉我,我会修改我的答案。
如果要去除循环,可以使用矩阵运算:
a = transpose(w)*transpose(X);
a
是一个大小为 1 x 3065 的向量(因为 w'
是 1 x 57 而 X'
是 57 x 3065)。
现在你可以像下面这样进行第二个操作:
b = transpose(y).*a
因此,sum
将是:
totalSum = sum(log(1+exp(a)) - b);
你应该考虑到 sum
是 Matlab 中的一个函数,最好更改 sum
变量的名称to
sum`。
总而言之,我们可以删除循环并用以下内容替换循环:
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);
它可能比您为第一个解决方案编写的速度更快。