我有一个大小为3065x57的数据矩阵X
和一个大小为3065x1的列矩阵y
,我想计算argmin
中定义的函数sum
代码如下。
我尝试了下面编码的内容,fminsearch
等,但没有效果。
另一个问题是我有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
循环。
答案 0 :(得分:1)
使用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,[],[]);
如果我错过任何内容,请告诉我,我会答应我的答案。
答案 1 :(得分:1)
如果要删除循环,可以使用矩阵运算:
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);
它可能比你为第一个解决方案编写的速度快得多。