3 Stimmen

Perl: Programmiereffizienz bei der Berechnung von Korrelationskoeffizienten für eine große Datenmenge

EDIT: Der Link sollte jetzt funktionieren, entschuldigen Sie die Störung

Ich habe eine Textdatei, die wie folgt aussieht:

Name, Test 1, Test 2, Test 3, Test 4, Test 5
Bob, 86, 83, 86, 80, 23
Alice, 38, 90, 100, 53, 32
Jill, 49, 53, 63, 43, 23.

Ich schreibe ein Programm, das aus dieser Textdatei eine Pearsonsche Korrelationskoeffiziententabelle erstellt, die wie folgt aussieht, wobei der Eintrag (x,y) die Korrelation zwischen Person x und Person y darstellt:

Name,Bob,Alice,Jill
Bob, 1, 0.567088412588577, 0.899798494392584
Alice, 0.567088412588577, 1, 0.812425393004088
Jill, 0.899798494392584, 0.812425393004088, 1

Mein Programm funktioniert, aber der Datensatz, mit dem ich es füttere, hat 82 Spalten und, was noch wichtiger ist, 54000 Zeilen. Wenn ich mein Programm jetzt ausführe, ist es unglaublich langsam und ich erhalte eine Fehlermeldung wegen Speichermangels. Gibt es eine Möglichkeit, wie ich zunächst einmal die Möglichkeit eines Fehlers wegen Speichermangels beseitigen und das Programm vielleicht ein wenig effizienter machen kann? Der Code ist hier: Code .

Vielen Dank für Ihre Hilfe,
Jack

Edit: Für den Fall, dass jemand anderes versucht, Berechnungen in großem Maßstab durchzuführen, konvertieren Sie Ihre Daten in das hdf5-Format. So habe ich dieses Problem schließlich gelöst.

4voto

Paul Tomblin Punkte 172816

Sie werden mindestens 54000^2*82 Berechnungen und Vergleiche durchführen müssen. Das wird natürlich eine Menge Zeit in Anspruch nehmen. Halten Sie alles im Speicher fest? Der wird auch ziemlich groß sein. Es wird langsamer sein, aber es könnte weniger Arbeitsspeicher verbrauchen, wenn Sie die Benutzer in einer Datenbank speichern und einen Benutzer mit allen anderen vergleichen, dann zum nächsten übergehen und ihn mit allen anderen vergleichen, anstatt ein riesiges Array oder einen Hash zu verwenden.

4voto

singingfish Punkte 3106

Werfen Sie einen Blick auf Krawatte::Datei um den hohen Speicherbedarf zu bewältigen, der entsteht, wenn die Eingabe- und Ausgabedateien im Speicher abgelegt werden.

4voto

dwarring Punkte 4684

Haben Sie CPAN durchsucht? Meine eigene Suche ergab eine weitere Methode gsl_stats_correlation zur Berechnung der Pearsons-Korrelation. Diese Methode ist in Math::GSL::Statik . Dieses Modul bindet sich an die GNU Scientific Library.

gsl_stats_correlation($data1, $stride1, $data2, $stride2, $n) - Diese Funktion berechnet effizient den Pearson-Korrelationskoeffizienten zwischen den Array-Referenzen $data1 und $data2, die beide die gleiche Länge $n haben müssen. r = cov(x, y) / ( \Hat\sigma_x \Hat\sigma_y ) = {1/(n-1) \sum (x_i - \Hat x) (y_i - \Hat y) \over \sqrt {1/(n-1) \sum (x_i - \Hat x)^2} \sqrt {1/(n-1) \sum (y_i - \Hat y)^2} }

3voto

daotoad Punkte 26089

Sie sollten sich Folgendes ansehen PDL :

PDL ("Perl Data Language") gibt Standard-Perl die Fähigkeit, kompakt kompakt zu speichern und schnell zu manipulieren die großen N-dimensionalen Datenarrays, die die das Brot und die Butter der wissenschaftlichen Datenverarbeitung

.

2voto

tsee Punkte 4970

Im Wesentlichen hat Paul Tomblin Ihnen die Antwort gegeben: Es ist eine Menge Rechenarbeit und wird daher lange dauern. Es sind viele Daten, also wird viel Speicherplatz benötigt.

Allerdings gibt es ein Problem: Wenn Sie Perl 5.10.0 verwenden, können Ihre Listenzuweisungen am Anfang jeder Methode Opfer eines subtilen Leistungsfehlers in dieser Perl-Version sein (vgl. Perlmutthread ).

Ein paar kleine Punkte:

Der Ausdruck kann das Programm sogar etwas verlangsamen, je nachdem, wohin er geht.

Es ist nicht nötig, die Ausgabedatei für jede Zeile neu zu öffnen! Machen Sie einfach etwas wie dies:

open FILE, ">", "file.txt" or die $!;
print FILE "Name, ", join(", ", 0..$#{$correlations[0]}+1), "\n";
my $rowno = 1;
foreach my $row (@correlations) {
  print FILE "$rowno, " . join(", ", @$row) . "\n";
  $rowno++;
}
close FILE;

Schließlich, während ich Perl verwenden, wann immer ich kann, mit einem Programm und Datensatz wie Sie beschreiben, könnte es der einfachste Weg, um einfach C++ mit seinen iostreams (die machen Parsing einfach genug) für diese Aufgabe zu verwenden.

Beachten Sie, dass dies alles nur eine kleine Optimierung ist. Es gibt keinen algorithmischen Gewinn.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X