2017-02-13 5 views
1

Ich bin die Lösung eines erzwungener linearer Berechnung der kleinsten Quadrate Problem wie folgt:lsqlin optimierte Berechnung (Matlab)

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

wo C ist m x 7 und bm x n ist. n ist ziemlich groß, was zu einer langsamen Rechenzeit führt. Gibt es eine Möglichkeit, diesen Vorgang zu beschleunigen und die langsame for Schleife loszuwerden. Ich verwende lsqlin anstelle von pinv oder \, weil ich meine Lösung auf die Grenzen von 0-1 beschränken muss (lb und ub).

+0

Sie können immer versuchen, den Standardlöser zu wechseln. Probieren Sie '' ''interior-point''' aus. Ich bin mir nicht sicher, wofür diese Schleife funktioniert und wie Sie von uns erwarten, dass wir daran arbeiten. – sascha

+0

Ich habe versucht, die verschiedenen Löser, aber das Problem ist das gleiche. Ich benutze die for-Schleife, weil ich versuche, 'x = lsqlin (C, b, [], [], [], [], lb, ub) zu geben;' Ich bekomme eine 'Innere Matrix Dimensionen müssen übereinstimmen .' Fehler. Auf der anderen Seite, wenn ich 'pinv (C) * b 'oder' C \ b' benutze, funktioniert es wie ein Zauber, aber für den 'lsqlin' muss ich es durch die 'for'-Schleife machen und da brauche ich die Einschränkungen Ich brauche den 'lsqlin'. Daher frage ich nur, ob es eine Möglichkeit gibt, die For-Schleife zu optimieren oder zu verwerfen. – ThT

Antwort

2

Die for Schleife ist nicht unbedingt der Grund für jede Langsamkeit - Sie sind nicht Vorbelegung und lsqlin wird wahrscheinlich eine Menge Zeug auf jeder Iteration ausdrucken. Sie können dies jedoch möglicherweise beschleunigen, indem Sie Ihre C Matrix in eine dünn besetzte Blockdiagonalmatrix, C2, mit n identischen Blöcken (see here) umwandeln. Dies löst alle n Probleme auf einmal. Wenn die neue C2 nicht spärlich ist, können Sie viel mehr Speicher verwenden und die Berechnung kann viel länger dauern als mit der for-Schleife.

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); 

Mit optimoptions, habe ich specified the algorithm und setzen 'Display'-'off' um sicherzustellen, dass alle Ausgänge und Warnungen nicht die Berechnungen verlangsamen.

Auf meinem Computer ist dies 6-10 mal schneller als mit einem for-Schleife (mit geeigneten Vor-Zuweisung und Einstellmöglichkeiten). Dieser Ansatz geht davon aus, dass die spärliche C2 Matrix mit m*n*7 Elementen in den Speicher passen kann. Wenn nicht, wird ein for loop-basierter Ansatz die einzige Option sein (abgesehen davon, dass Sie Ihre eigene spezialisierte Version von lsqlin schreiben oder jede andere Erschwernis in dem Problem ausnutzen).

+0

vielen dank für ihre antwort. Deine Lösung scheint den Trick zu machen ;-). Ich hatte auch Nachrichten ausgeschaltet, aber keine Vorabzuweisung (das nächste, was ich ausprobieren wollte), während ich die spärliche Blockdiagonalmatrix benutze, ist ein Trick, den ich nicht kenne und der mir sehr hilft. Danke für deine Hilfe noch einmal. – ThT

+0

nur eine andere Frage. Wie optimal, ist die Verwendung der Sparse-Blockdiagonalmatrix speicherorientiert. Da ich zum Beispiel in meinem Fall mit Matrizen der Größe 'C' (193200x7)' b' (193200x16450) oder größer umgehen muss, ist mein Nachteil, dass ich das früher nicht erwähnt habe. Wie Sie Ihre Lösung in der Praxis ausprobieren können, habe ich jetzt das Problem mit dem Speicher (250 GB sind nicht genug für die C2-Vorbelegung). Irgendein Hinweis dafür? – ThT

+0

Ich nahm an, dass 'm' kleiner als' n' war, weil Sie angegeben haben, dass 'n' in Ihrer Frage groß war. Ihr spärliches 'C2' benötigt ungefähr den gleichen Speicher wie ein 193200x7x16450-Array (im Gegensatz zu einem vollständigen Array, das 16450-mal größer ist als das!). Ihr 'b' ist in meiner Version von Matlab bereits größer als die standardmäßige maximale Array-Größe (wahrscheinlich mussten Sie die Einstellung ändern, um das Limit zu ändern). Eine "for" -Schleife ist der Weg zu gehen, wenn Sie Speicher gebunden sind, es sei denn, andere Teile des Systems sind spärlich. – horchler

Verwandte Themen