2017-02-13 149 views
1

我计算约束线性最小二乘问题的解决方案如下:lsqlin优化计算(MATLAB)

lb = zeros(7,1); 
ub = ones(7,1); 
for i = 1:size(b,2) 
    x(:,i) = lsqlin(C,b(:,i),[],[],[],[],lb,ub); 
end 

其中Cm x 7bm x nn相当大,导致计算时间较慢。有没有什么办法可以加快这个程序,并摆脱慢循环的for。我正在使用lsqlin而不是pinv\,因为我需要将我的解决方案限制在0-1的边界(lbub)。

+0

您可以随时尝试切换默认解算器。尝试'''内部点'''。不知道该循环是什么,以及你期望我们如何处理它。 – sascha

+0

我尝试了不同的求解器,但问题是一样的。我正在使用for循环,因为如果我试图给出'x = lsqlin(C,b,[],[],[],[],lb,ub);'我得到一个'Inner matrix dimensions must agree错误。另一方面,如果我使用'pinv(C)* b'​​或'C \ b',它就像一个魅力,但对于'lsqlin'我需要通过'for'循环来完成,因为我需要约束我需要使用'lsqlin'。因此,我只是问是否有任何可能性来优化或放弃'for'循环。 – ThT

回答

2

for循环不一定是缓慢的原因 - 你没有预先分配,并且lsqlin可能会在每次迭代时打印出很多东西。但是,您可以通过将C矩阵转换为稀疏块对角矩阵C2n相同的块(see here)来加速此过程。这一次解决了所有的问题。如果新的C2不稀疏,则可能会使用更多的内存,并且计算时间可能会比使用for循环的时间长很多。

n = size(b,2); 
C2 = kron(speye(n),C); 
b2 = b(:); 
lb2 = repmat(lb,n,1); % or zeros(7*n,1); 
ub2 = repmat(ub,n,1); % or ones(7*n,1); 
opts = optimoptions(@lsqlin,'Algorithm','interior-point','Display','off'); 
x = lsqlin(C2,b2,[],[],[],[],lb2,ub2,[],opts); 

使用optimoptions,我已经specified the algorithm并设置'Display''off',以确保任何输出,并警告不会减慢计算。

在我的机器上,这比使用for环路(具有适当的预分配和设置选项)快6-10倍。此方法假定具有m*n*7元素的稀疏C2矩阵可以放入内存中。如果没有,基于回路的for方法将是唯一的选择(除了编写自己的专用版本lsqlin或利用问题中的任何其他缺点)。

+0

非常感谢您的回答。你的解决方案似乎使窍门;-)。我使用了稀疏块对角线矩阵,但我没有预先分配消息,但没有预先分配(我打算尝试接下来的一件事),这是一个我不知道的技巧,它似乎帮助了很多。再次感谢您的帮助。 – ThT

+0

只是另一个问题。如何最优化,是使用稀疏块对角矩阵,明智的记忆。因为例如,在我的情况下,我不得不处理大小为'C'(193200x7)'b'(193200x16450)或更大的矩阵,这很糟糕,我之前没有提到过。正如您可以理解在实践中尝试解决方案一样,现在我遇到了内存问题(250Gb对于C2预分配不够)。任何暗示? – ThT

+0

我假设'm'小于'n',因为你表示'n'在你的问题中很大。你稀疏的'C2'将需要与193200x7x16450阵列大致相同的内存(而不是完整阵列,比这大16450倍!)。你的'b'已经大于我的Matlab版本的默认最大数组大小(你可能不得不进入偏好来改变限制)。除非系统的其他部分稀疏,否则如果您受到内存限制,则“for”循环是要走的路。 – horchler