WICHTIG: Der Betrieb von goMatlab.de wird privat finanziert fortgesetzt. - Mehr Infos...

Mein MATLAB Forum - goMatlab.de

Mein MATLAB Forum

 
Gast > Registrieren       Autologin?   

Partner:




Forum
      Option
[Erweitert]
  • Diese Seite per Mail weiterempfehlen
     


Gehe zu:  
Neues Thema eröffnen Neue Antwort erstellen

Schleifen vermeiden

 

klaus1

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 24.05.2012, 15:28     Titel: Schleifen vermeiden
  Antworten mit Zitat      
Hallo,
ich habe mich jetzt eine Stunden durch Beiträge durchgelesen, jedoch nix gefunden was mir bei meinem Problem weiterhilft.

Ich habe eine Matrix A(26,100k) und möchte nun jede Zeile mit jeder vergleichen und die euklidische Distanz von jedem Zeilenpärchen berechnen.

Da ich mich mit Matlab speziell nicht gut auskenne, habe ich es mit einer Doppelschleife probiert. Dies funktioniert zwar, ist jedoch unendlich langsam....

vielleich hat ja jemand eine Idee wie ich mein Problem effizienter lösen kann. Das währe toll.

Vielen Dank im vorraus schonmal


klaus


Vito
Forum-Guru

Forum-Guru


Beiträge: 315
Anmeldedatum: 02.11.09
Wohnort: Stuttgart
Version: ---
     Beitrag Verfasst am: 24.05.2012, 15:57     Titel:
  Antworten mit Zitat      
Hi,

kannst du bitte dein Code mal reinstellen vielleicht kann man da was machen Very Happy .
Bitte stell deine Matrix als *.mat auch rein.

Gruß,
Vito
Private Nachricht senden Benutzer-Profile anzeigen
 
klaus1

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 24.05.2012, 16:13     Titel:
  Antworten mit Zitat      
ok hier mal mein Code:


Code:

for k = 1: size(matrix,1)
    for l = 1:size(matrix,1)
        i = 1;
        i = i+k-1;
        j = 1;
        j = j+l-1;
   

        variable(1,:) = matrix(i,:);
        variable(2,:) = matrix(j,:);
        variable(:,any(isnan(variable))) = [];

        dist = pdist(variable);
        dist_rms = dist./sqrt(length(variable));

        dist_matrix(i,j) = dist_rms;
       
       
 
    end
end    

 


Ich weiß nicht genau ob ich meine Matrix als .mat Datei hier hochladen kann, da ich nicht weiß wie die rechtliche Lage hierbei ist Smile ( ist ein nicht veröffentlichter Datensatz aus einer Forschungsarbeit den ich halt auswerten soll)

Aber im Prinzip eine 26x100000 Matrix mit Werten zwischen - 30 bis 30 und NaN Werten.

hoffe das reicht dir Smile
Gruß
 
Vito
Forum-Guru

Forum-Guru


Beiträge: 315
Anmeldedatum: 02.11.09
Wohnort: Stuttgart
Version: ---
     Beitrag Verfasst am: 24.05.2012, 17:13     Titel:
  Antworten mit Zitat      
Hi,

probier folgendes:
Code:

for j = 1:100000
    for k = 1:100000
        M(j,k) =norm(matrix(k,:)-matrix(j,:));
    end
end
 

Das geht recht schnell Very Happy ich habe es selbst mit einer 1000x1000 Matrix versucht.

Gruß,
Vito
Private Nachricht senden Benutzer-Profile anzeigen
 
klaus1

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 25.05.2012, 11:33     Titel:
  Antworten mit Zitat      
Hallo,

in der Tat, geht schneller Smile . Allerdings habe ich einige NaN Werte in meiner Matrix mit der die norm Funktion wohl nicht umgehen kann :/

Mein M(j,k) besteht dann nur aus NaN Werten.

Ich müsste also vorher in der Schleife von jedem Paar matrix(k,Smile und matrix(j,Smile die NaN Werte eliminieren.

Wenn ich das allerdings so versuche:
Code:


for j = 1:100000
 
    for k = 1:100000
       
       matrix(k,any(isnan(matrix))) = [];
       matrix(j,any(isnan(matrix))) = [];
       
       M(j,k) =norm(tmat(k,:)-tmat(j,:));
       
    end
 
end
 


bekomme ich immer den Fehler:


??? Subscripted assignment dimension mismatch.

Error in ==> test at 10
matrix(k,any(isnan(matrix))) = [];

Ich weiß leider nicht genau woran das liegt
Vorher eliminieren scheidet leider aus, da ich dann zu wenig Werte insgesammt hätte.


Gruß
 
Vito
Forum-Guru

Forum-Guru


Beiträge: 315
Anmeldedatum: 02.11.09
Wohnort: Stuttgart
Version: ---
     Beitrag Verfasst am: 25.05.2012, 12:10     Titel:
  Antworten mit Zitat      
Hi,

mach doch folgendes:
Code:

idxNaN = find(any(isnan(matrix),2)); % findet die indizies aller NaNs.
matrix(idxNaN)=[];                          % eleminiert sie aus der Matrix.

for j = 1:100000
 
    for k = 1:100000
       M(j,k) =norm(tmat(k,:)-tmat(j,:));        
    end
 
end

 
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 27.05.2012, 18:46     Titel:
  Antworten mit Zitat      
Hallo klaus1,

Bitte beschreibe die Dimension des Inputs und Outputs nochmal. Zunächst sagtest Du es ging um die Norm zwischen den Zeilen eine [26 x 1e5] Matrix. Dann wäre die Ausgabe [26 x 26].

Mit dem for "j = 1:100000, for k = 1:100000" Ansatz erzeugst Du allerdings eine [1e5 x 1e5] Matrix. Das ist aber eine ganz andere Geschichte.

In beiden Fällen ist eine Pre-allozierung wichtig: Erzeuge zunächst die Ausgabe-Matrix mit ZEROS(), Inf() oder NaN(), so dass der gesamte Speicherbereich alloziert wird, statt ihn stückchenweise zu vergrößern. Bei einer [26 x 26] Matrix ist das nicht dramatisch, bei einer [1e5 x 1e5] Matrix aber deutlich.

Dann ist die erzeugte Matrix symmetrisch, wenn man also ein Element oberhalb der Diagonalen erzeugt hat, kennt man auch den Wert des entsprechenden Elements unterhalb der Diagonalen. Das spart nochmal die halbe Rechenzeit.
PDIST ist langsamer als NORM, die Vektor-Multiplikation v*v' ist aber noch deutlich schneller:
Code:
n = size(A, 1);
D = zeros(n, n);
for i = 1:n
   vi = A(i, :);
   for j = i+1:n
      v = A(j, :) - vi;
      v = v(isfinite(v));
      k = sqrt((v * v') / length(v));
      D(i,j) = k;
      D(j,i) = k;
   end
end

Als nächster Schritt kann man beachten, dass in Matlab die Matrizen spaltenweise gespeichert werden. Der Zugriff auf A(:,i) ist viel effizienter als auf A(i,:), da benachbarte Elemente auch zusammen im Prozessor-Cache zu finden sind. Also:
Code:
Q = A';
n = size(A, 1);
D = zeros(n, n);
for i = 1:n
   vi = Q(:, i);
   for j = i+1:n
      v = Q(:, j) - vi;
      v = v(isfinite(v));
      k = sqrt((v' * v) / length(v));
      D(i,j) = k;
      D(j,i) = k;
   end
end

Während der Orginal-Code (pdist) auf meinem 2009a/64/Win7 Rechner 7.7 Sekunden benötigt, braucht der SQRT(v*v') Code mit Ausnutzung der Symmetrie 1.0 Sekunden und mit der Transposition Q=A'; SQRT(v'*v) noch 0.7 Sekunden.
Ich rate, dass ein C-Mex weitere 10 mal schneller wäre.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
klaus1

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 30.05.2012, 15:54     Titel:
  Antworten mit Zitat      
Hey,
danke jan!!
jetzt braucht mein komplettes Programm anstatt 13min nurnoch 50sec.
Die weiteren Teile meines Programmes kann man bestimmt auch noch ziemlich optimieren, aber das ist schon ok so. Ansonsten hätt ich irgerntwie ein schlechtes Gewissen, wenn ich hier mein koplettes Script ausfragen würde Smile


ich habe mich wohl etwas schlecht ausgedrückt. Tatsächlich soll eine 26x26 Matrix rauskommen, wie in deinem Vorschlag.

Also nochmal vielen Dank an euch beide

Gruß
 
Neues Thema eröffnen Neue Antwort erstellen



Einstellungen und Berechtigungen
Beiträge der letzten Zeit anzeigen:

Du kannst Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.
Du kannst Dateien in diesem Forum posten
Du kannst Dateien in diesem Forum herunterladen
.





 Impressum  | Nutzungsbedingungen  | Datenschutz | FAQ | goMatlab RSS Button RSS

Hosted by:


Copyright © 2007 - 2025 goMatlab.de | Dies ist keine offizielle Website der Firma The Mathworks

MATLAB, Simulink, Stateflow, Handle Graphics, Real-Time Workshop, SimBiology, SimHydraulics, SimEvents, and xPC TargetBox are registered trademarks and The MathWorks, the L-shaped membrane logo, and Embedded MATLAB are trademarks of The MathWorks, Inc.