Python sucht eine große Listengeschwindigkeit

8

Ich bin auf ein Geschwindigkeitsproblem gestoßen, als ich eine sehr große Liste durchsucht habe. Ich habe eine Datei mit vielen Fehlern und sehr seltsamen Wörtern darin. Ich versuche, difflib zu verwenden, um die beste Übereinstimmung in einer Wörterbuchdatei zu finden, die 650.000 Wörter enthält. Dieser Ansatz funktioniert sehr gut, ist aber sehr langsam und ich frage mich, ob es einen besseren Weg gibt, dieses Problem anzugehen. Dies ist der Code:

%Vor%

Danke für die Hilfe, Software-Engineering ist nicht einmal nah an meiner starken Klage. Sehr geschätzt.

    
English Grad 23.12.2013, 21:12
quelle

4 Antworten

4

Zwei Dinge, die eine kleine Hilfe bieten könnten:

1) Verwenden Sie den Ansatz in diese SO-Antwort um Ihre große Datei am effizientesten zu lesen.

2) Ändern Sie Ihren Code von

%Vor%

bis

%Vor%

Sie konvertieren jeden Satz in niedrigere 650.000-fache. Keine Notwendigkeit dafür.

    
Oniofchaos 23.12.2013, 21:21
quelle
3

1) Ich würde headwordList als Menge und nicht als Liste speichern, um einen schnelleren Zugriff zu ermöglichen, da es sich um eine Hash-Datenstruktur handelt.

2) Sie haben sentenceList als Liste definiert und versuchen dann, sie als Wörterbuch mit sentenceList[x] = y zu verwenden. Ich würde speziell für Zählungen eine andere Struktur definieren.

3) Sie erstellen sentenceList , was nicht getan werden muss.

%Vor%

4) Sie werden nie line in Token setzen, was bedeutet, dass Sie die gesamte Zeile vor dem Zeilenumbruchzeichen in der sentenceList speichern und sehen, ob sie in einer Wortliste enthalten ist

    
C.B. 23.12.2013 21:20
quelle
3

Sie sollten headwordList in ein set ändern.

Der Test word in headwordList wird sehr langsam sein. Es muss für jedes Wort in headwordList ein Zeichenfolgenvergleich durchgeführt werden. Es wird Zeit brauchen, die proportional zur Länge der Liste ist; Wenn Sie die Länge der Liste verdoppeln, verdoppeln Sie den Zeitaufwand für den Test (im Durchschnitt).

Bei einem set dauert es immer die gleiche Zeit, um den in -Test durchzuführen; Es hängt nicht von der Anzahl der Elemente in set ab. Das wird eine enorme Beschleunigung.

Nun kann diese ganze Schleife vereinfacht werden:

%Vor%

All dies ist das Wort von headwordList , das das höchste Verhältnis hat, und behalte es (aber behalte es nur, wenn das Verhältnis über 0,86 ist). Hier ist ein schneller Weg, dies zu tun. Ich werde den Namen headwordList in nur headwords ändern, da ich möchte, dass es ein set und nicht ein list ist.

%Vor%

Dies mag ein bisschen schwierig erscheinen, aber es ist der schnellste Weg, dies in Python zu tun. Wir rufen die eingebaute Funktion max() auf, um das SequenceMatcher Ergebnis zu finden, das die höchste Ratio hat. Zuerst erstellen wir einen "Generator-Ausdruck", der alle Wörter in headwords ausprobiert und dabei SequenceMatcher() aufruft. Aber wenn wir fertig sind, wollen wir auch wissen, was das Wort ist. Der Generatorausdruck erzeugt also Tupel, wobei der erste Wert im Tupel das SequenceMatcher -Ergebnis und der zweite Wert das Wort ist. Die Funktion max() kann nicht wissen, dass das, was uns interessiert, das Verhältnis ist, also müssen wir es sagen; Wir machen das, indem wir eine Funktion erstellen, die prüft, was uns wichtig ist, und dann diese Funktion als key= Argument übergeben. Jetzt findet max() den Wert mit dem höchsten Verhältnis für uns. max() konsumiert alle vom Generator-Ausdruck erzeugten Werte und gibt einen einzelnen Wert zurück, den wir dann in die Variablen m und word entpacken.

In Python empfiehlt es sich, Variablennamen wie sentence_list anstelle von sentenceList zu verwenden. Bitte beachten Sie diese Richtlinien: Ссылка

Es ist keine gute Übung, eine inkrementierende Indexvariable zu verwenden und sie in indizierte Positionen in einer Liste einzuteilen. Beginnen Sie stattdessen mit einer leeren Liste und verwenden Sie die Methodenfunktion .append() , um Werte anzuhängen.

Sie könnten auch besser ein Wörterbuch mit Wörtern und ihren Verhältnissen erstellen.

Beachten Sie, dass Ihr ursprünglicher Code einen Fehler zu haben scheint: Sobald ein Wort einen Prozentsatz von mehr als 0.86 hat, werden alle Wörter in sentenceList gespeichert, unabhängig von ihrem Verhältnis. Der Code, den ich oben geschrieben habe, speichert nur Wörter, bei denen das eigene Verhältnis hoch genug ist.

EDIT: Dies ist eine Frage zu Generatorausdrücken, die in Klammern gesetzt werden müssen.

Immer wenn ich diese Fehlermeldung erhalte, spalte ich normalerweise den Generatorausdruck selbst aus und weise ihn einer Variablen zu. So:

%Vor%

Das schlage ich vor. Aber wenn es Ihnen nichts ausmacht, dass eine komplizierte Zeile noch belebter aussieht, können Sie einfach ein zusätzliches Klammerpaar hinzufügen, wie in der Fehlermeldung vorgeschlagen, sodass der Generatorausdruck vollständig geklammert ist. Wie so:

%Vor%

In Python können Sie die expliziten Klammern um einen Generatorausdruck weglassen, wenn Sie den Ausdruck an eine Funktion übergeben, aber nur, wenn es das einzige Argument für diese Funktion ist. Da wir auch ein Argument key= übergeben, benötigen wir einen vollständig eingeklammerten Generatorausdruck.

Aber ich denke, es ist einfacher zu lesen, wenn Sie das Genexp in einer eigenen Zeile aufteilen.

EDIT: @Peter Wood wies darauf hin, dass in der Dokumentation vorgeschlagen wird, SequenceMatcher für die Geschwindigkeit wiederzuverwenden. Ich habe keine Zeit, das zu testen, aber ich denke, das ist der richtige Weg.

Glücklicherweise wurde der Code einfacher! Immer ein gutes Zeichen.

EDIT: Ich habe gerade den Code getestet. Dieser Code funktioniert für mich; Schau, ob es für dich funktioniert.

%Vor%     
steveha 23.12.2013 21:20
quelle
0

Dies ist eine Datenstrukturfrage. Was Sie tun möchten, ist, Ihre Liste in etwas mit schnellerer Elementsuchgeschwindigkeit zu verwandeln, zum Beispiel würde ein binärer Suchbaum hier gut funktionieren: Zeitkomplexität ist nur O (log n) im Gegensatz zu O (n) in einer Liste (das ist in Vergleich unglaublich schnell).

Es gibt eine ziemlich einfache Erklärung hier:

Ссылка

Aber wenn Sie mit den Baumkonzepten nicht vertraut sind, möchten Sie vielleicht vorher ein paar Kapitel beginnen:

Ссылка

    
Ruslan Osipov 23.12.2013 21:26
quelle