[PYTHON] Vergleich von LDA-Implementierungen

(Ich werde einen Artikel veröffentlichen, den ich vor einem Jahr vergessen habe, für den Entwurf der Verdauung zu veröffentlichen.)

Ich habe einige der LDA-Implementierungen zum Vergleich angesprochen. Es scheint, dass die Optionen wie folgt sind, aber ich werde das Verfahren zum Ausführen der LDA jeder Sprache, die in einem Memo geschrieben ist, zusammenfassen.

Verwendete Sprache Nutzungsmuster Erweiterbarkeit laden Algorithmus
Spark MLlib 1.6.0 Scala,Java,
Python,R
Bibliothek Parallel/Verteilt Variante Bayes, EM
gensim Python Bibliothek Parallel Variante Bayes
GibbsLDA++ Schale Befehl - Gibbs Sampling
R R Bibliothek - Gibbs Sampling

Ausführungskosten

Jedes wird ausgeführt und die Zeit wird gemessen, aber die Ausführungsbedingungen sind sehr unterschiedlich, wie unten gezeigt. Bitte lesen Sie es ohne Missverständnisse.

Wird unter den Bedingungen von $ k = 100 $ und $ iter = 50 $ für $ 13.033 $ ausgeführt. Dokument $ 20.780 $ Wörter, die durch Durchführen einer morphologischen Analyse und Entfernen unnötiger morphologischer Elemente erhalten wurden.

Spark MLlib

Algorithmus Nodes Cores Ausführungszeit
EM 5 80 224.092
EM 1 8 81.854
EM 1 1 112.606
Variante Bayes 1 8 220.147
Variante Bayes 1 1 310.367

Die Ausführungszeit ist langsamer als bei anderen, da RDD auch die lokale Datei liest und die BoW erstellt. Die langsamsten Ergebnisse der verteilten Ausführung sind wahrscheinlich auf die höheren Kosten für das Mischen und die Datenübertragung zwischen Knoten zurückzuführen als die LDA-Berechnungskosten selbst.

gensim

Algorithmus Nodes Cores Ausführungszeit
Variante Bayes 1 4 15.396
Variante Bayes 1 1 20.576

Pythons Gensim scheint nur eine Variante von Bayes zu sein, aber es scheint ein gutes Leistungsgleichgewicht mit mehr Arbeitern, paralleler Verarbeitung und hoher Geschwindigkeit zu haben.

GibbsLDA++

Algorithmus Nodes Cores Ausführungszeit
Gibbs Sampling 1 1 58.993

Es war schneller als Gensim in der Nähe von $ k = 10 $ mit Eingabe / Ausgabe-Verarbeitung von lokalen Dateien zusätzlich zu einem einzelnen Thread, aber ist es langsamer, wenn $ k $ größer wird? Der Maßstab mag schwierig sein, aber ist er für eine kleine Ad-hoc-Ausführung geeignet?

R Sprache

Algorithmus Nodes Cores Ausführungszeit
Collapsed Gibbs Sampling 1 1 24.247

Die Berechnung selbst war überraschend schneller als "lda.collapsed.gibbs.sampler {lda}" von GibbsLDA ++ R (Das Lesen und Konvertieren einer lokalen Datei in ein Format, das an die Bibliothek übergeben werden kann, war jedoch langsam, sodass sie insgesamt langsam ist). R ist schneller als die praktische Geschwindigkeit lda {lda} und [lda.cvb0 {lda}](http Es ist ein guter Eindruck, viele Implementierungen und Algorithmen zu erwarten (z. B. //www.inside-r.org/packages/cran/lda/docs/lda.cvb0).

Versuchen Sie, jede Implementierung zu verwenden

gensim

# -*- coding: utf-8 -*-
#LDA-Beispiel von Python Gensim
from gensim import corpora, models
import time

#Dokumentdaten lesen(Morphologische Analyse/Eine Textdatei, in der Wörter in einem zeilenweisen Dokument mit extrahierter Nomenklatur durch Leerzeichen getrennt sind.)
texts = [ ]
for line in open('docs.gibbs', 'r'):
    texts.append(line.split())

#Wörterbuch erstellen(id:Wort:Anzahl der Auftritte)
dictionary = corpora.Dictionary(texts)
dictionary.save_as_text('./docs.dic')
# dictionary = corpora.Dictionary.load_from_text("./docs.dic")

#Korpuserstellung
corpus = [dictionary.doc2bow(text) for text in texts]
corpora.MmCorpus.serialize('corpus.mm', corpus)
# corpus = corpora.MmCorpus('corpus.mm')

#LDA-Berechnung
t0 = int(time.time() * 1000)
lda = models.ldamodel.LdaModel(corpus, num_topics=100, iterations=50)
t1 = int(time.time() * 1000)
print t1 - t0

#LDA-Berechnung(Multiprozessor-kompatible Version)
t0 = int(time.time() * 1000)
lda = models.ldamulticore.LdaMulticore(corpus, num_topics=10, iterations=50, workers=4)
t1 = int(time.time() * 1000)
print t1 - t0

GibbsLDA++

GibbsLDA ++ und sein Java-Port von JGibbsLDA sind Befehlszeilen-LDA-Implementierungen. Ich habe Gibbs Sampling implementiert, aber es scheint keine parallele Verarbeitung (Multi-Core-Unterstützung) oder verteilte Verarbeitung zu unterstützen.

Bauen

Laden Sie GibbsLDA ++ - 0.2.tar.gz von GibbsLDA ++: A C / C ++ Gibbs Sampling LDA herunter, entpacken und erstellen Sie es.

$ tar zxvf GibbsLDA++-0.2.tar.gz
$ cd GibbsLDA++-0.2/
$ make all

Wenn "g ++" verfügbar ist, wird "make all" den Build abschließen und der Befehl "src / lda" wird ausgeführt.

Wenn "Fehler:" atof "in diesem Bereich nicht deklariert wurde", tritt "hier:" printf "nicht in diesem Bereich auf" (http://yuutookun.hatenablog.com/entry/20120831/) 2 Fügen Sie der Datei, die sich auf 1346394002 bezieht, # include hinzu.

$ vim src/util.cpp
...
#include <stdio.h>
#include <stdlib.h>  //hinzufügen
#include <string>
...
$ vim src/lda.cpp
...
*/

#include <stdio.h>  //hinzufügen
#include "model.h"
...
$ make clean; make all
make -C src/ -f Makefile clean
make[1]: Entering directory `/export/home/t_takami/git/gibbslda++/GibbsLDA++-0.2/src'
...
make[1]: Leaving directory `/export/home/t_takami/git/gibbslda++/GibbsLDA++-0.2/src'

$ src/lda --help
Please specify the task you would like to perform (-est/-estc/-inf)!
Command line usage:
        lda -est -alpha <double> -beta <double> -ntopics <int> -niters <int> -savestep <int> -twords <int> -dfile <string>
        lda -estc -dir <string> -model <string> -niters <int> -savestep <int> -twords <int>
        lda -inf -dir <string> -model <string> -niters <int> -twords <int> -dfile <string>

Datenaufbereitung

Erstellen Sie eine Datei, in der die im Dokument enthaltenen Wörter durch Leerzeichen getrennt aufgelistet sind, sodass die Anzahl der Dokumente in der ersten Zeile und dann "1 Zeile = 1 Dokument" steht. Wenn Leerzeilen vorhanden sind (Dokumente mit 0 Wörtern, die Features darstellen), tritt ein "Ungültiges (leeres) Dokument!" - Fehler auf.

$ head -n 5 docs.gibbs
13033
Speicheranforderung Karte auswählen Kartengehäuse Antwortmethode Methode Möglich Internes Modell Kapazität Aufzeichnung Aufzeichnung Aufzeichnung Aufzeichnung Zeit einstellen Speichern Speichern Speichern Speichern Speichern
Die Welt, die Welt, die Welt, die wichtigen Dinge, der gesunde Menschenverstand, der gesunde Menschenverstand, der gesunde Menschenverstand, der gesunde Menschenverstand, der gesunde Menschenverstand, der gesunde Menschenverstand, ich
Charakter Kleidung Operation Spiel Blondes Charakter Modell Silberhaar
Best Best Delusion Date Date
Telefon Telefon Telefon Abschied Echtes Geschenk Geschenk Wie Geschenk Wie Bitte Bitte Tränen Tränen Tränen Tränen Narita Gespräch Negative Augen Beziehungsraum Liebe Uruguay Uruguay Uruguay Uruguai Eule Letzte Gefühle hinter den Kulissen…
…

Ausführungsergebnis

Führen Sie dies aus, indem Sie die Anzahl der Themen $ k $ und die Anzahl der Wiederholungen in der Befehlszeile angeben.

$ src/lda -est -niters 50 -ntopics 10 -twords 5 -dfile docs.gibbs
Sampling 50 iterations!
Iteration 1 ...
...
Iteration 50 ...
Gibbs sampling completed!
Saving the final model!

Wenn Sie fertig sind, sollten Sie einige Dateien haben.

model-final.others ist der Ausführungsparameter, als dieses Modell erstellt wurde, und wordmap.txt enthält die dem Wort zugewiesene ID.

$ cat model-final.others
alpha=5.000000
beta=0.100000
ntopics=10
ndocs=13033
nwords=20779
liter=50

$ cat wordmap.txt
20779
T-Shirt 4601
Ai 1829
Aiko 19897
Gruß 2125
...

model-final.twords listet die charakteristischsten Wörter für jedes Thema auf, wie durch die Option -twords angegeben (diese Datei wird nicht erstellt, wenn die Option -twords weggelassen wird).

$ cat model-final.twords
Topic 0th:
Person 0.047465
Fühle 0.019363
Qi 0.018178
Anderes (0.016968
Normal 0.016004
Topic 1th:
Arbeit 0.043820
Zeit 0.024824
Haus 0.019440
Jetzt 0.017962
Mutter 0.016881
Topic 2th:
Wenn 0.033522
Monat 0.018820
Firma 0.018083
Versicherung 0.015252
Anfrage 0.012468
…

model-final.phi ist die Wahrscheinlichkeit des Auftretens eines Wortes für jedes Thema. 1 Zeile = 1 Thema, und die Anzahl der Spalten in einer Zeile entspricht der Anzahl der Wörter auf dem Korpus. Mit anderen Worten, es ist eine Matrix von "$ k $ Zeilen (Gesamtzahl der Wörter) Spalten". Es sind die numerischen Daten, die die Grundlage für model-final.twords bilden.

$ head -c 100 model-final.phi
0.000002 0.000002 0.000002 0.000002 0.000799 0.000002 0.000002 0.002415 0.000002 0.000002 0.000002 0

model-final.theta ist die Wahrscheinlichkeit, dass jedes Dokument zu welchem Thema gehört. Entspricht 1 Zeile = 1 Dokument und 1 Spalte = 1 Thema. Mit anderen Worten, es sind die Matrixdaten von "(Anzahl der Dokumente) Zeilen $ k $ Spalten".

$ head -n 5 model-final.theta
0.081081 0.216216 0.067568 0.067568 0.162162 0.081081 0.067568 0.108108 0.081081 0.067568
0.076923 0.076923 0.123077 0.092308 0.076923 0.076923 0.107692 0.076923 0.076923 0.215385
0.086207 0.103448 0.103448 0.086207 0.137931 0.086207 0.103448 0.086207 0.086207 0.120690
0.090909 0.090909 0.109091 0.127273 0.090909 0.090909 0.090909 0.090909 0.090909 0.127273
0.035971 0.028777 0.111511 0.323741 0.050360 0.086331 0.248201 0.039568 0.028777 0.046763

model-final.tassign ist eine Liste des Formats [Wort-ID: Thema] für jede Zeile Originaldaten = 1 Dokument.

$ head -n 5 model-final.tassign
0:1 1:4 2:1 3:7 3:7 4:8 4:7 5:5 6:1 6:1 7:4 8:1 9:4 10:1 11:4 11:4 11:4 11:4 12:1 13:0 14:1 14:1 14:1 14:1
15:9 15:9 15:9 16:3 17:6 18:6 19:2 19:9 19:2 19:2 19:9 19:9 20:9 20:9 20:9
21:2 22:9 23:1 24:4 25:6 26:9 9:4 27:4
28:9 28:2 29:9 30:3 30:3
31:4 31:6 31:6 32:3 33:2 34:3 34:3 35:3 35:3 1:5 1:2 36:3 36:3 36:3 37:6 38:2 39:6 40:6 41:6 42:3 42:6 43:6 44:3 …

GibbsLDA ++ ist fast so weit, ein numerisches Modell zu erstellen, dass Sie die anderen Ergebnisse als "Twords" selbst Dokumenten und Wörtern zuordnen müssen.

R Sprache

Persönlich ist es eine R-Sprache, die schwer in die Sprachfunktion zu bekommen ist und ein wenig schüchtern ist, aber lda.collapsed.gibbs.sampler {lda} Wenn Sie sich .collapsed.gibbs.sampler) ansehen, können Sie sehen, dass einige Modelle von Collapsed Gibbs Sampling implementiert sind.

Es scheint keine parallele Verarbeitung (Multi-Core-Unterstützung) oder verteilte Verarbeitung zu unterstützen.

Installation

Installieren Sie zuerst die R-Sprache unter CentOS 7.2 (wenn der folgende Befehl "rpm" eine 404 ergibt, löschen Sie den Dateiteil der URL, um die entsprechende Version zu finden).

$ sudo rpm -ihv http://ftp.riken.jp/Linux/fedora/epel/7/x86_64/e/epel-release-7-5.noarch.rpm
$ sudo yum install R

Starten Sie nach Abschluss der R-Installation die interaktive Schnittstelle und installieren Sie das LDA-Paket. Unterwegs versuche ich, das LDA-Paket in "/ usr / lib64 / R / library" zu installieren, aber ich bin kein "root" -Benutzer, daher gebe ich eine persönliche Bibliothek an. Sie werden auch nach der Downloadquelle gefragt. Wählen Sie daher den CRAN-Spiegel für Japan (Tokio).

Unten werden zusätzlich "reshape2" und "ggplot2" installiert, um die Demo auszuführen.

$ R
R version 3.2.3 (2015-12-10) -- "Wooden Christmas-Tree"
Copyright (C) 2015 The R Foundation for Statistical Computing
Platform: x86_64-redhat-linux-gnu (64-bit)
...
> install.packages("lda")
...
Would you like to use a personal library instead?  (y/n) y
...
Selection: 13
...
> install.packages("reshape2")
> install.packages("ggplot2")
> require("lda")
> demo(lda)

Es scheint, dass nicht nach der Spezifikationsänderung von ggplot2 stat_count () nicht mit irgendeiner Ästhetik verwendet werden darf. Wird auftreten und das Diagramm wird nicht angezeigt. Wenn Sie den Teil qplot () korrekt und manuell starten, funktioniert er. Da der LDA-Berechnungsprozess selbst abgeschlossen ist, ignorieren Sie ihn und fahren Sie fort.

> top.topic.words(result$topics, 5)
     [,1]         [,2]        [,3]        [,4]       [,5]       [,6]
[1,] "algorithm"  "learning"  "model"     "learning" "neural"   "learning"
[2,] "model"      "algorithm" "report"    "neural"   "networks" "network"
[3,] "algorithms" "paper"     "models"    "networks" "network"  "feature"
[4,] "data"       "examples"  "bayesian"  "paper"    "learning" "model"
[5,] "results"    "number"    "technical" "network"  "research" "features"
     [,7]        [,8]          [,9]        [,10]
[1,] "knowledge" "problem"     "paper"     "learning"
[2,] "system"    "genetic"     "decision"  "reinforcement"
[3,] "reasoning" "control"     "algorithm" "paper"
[4,] "design"    "performance" "results"   "problem"
[5,] "case"      "search"      "method"    "method"

Die Ergebnisse kommen heraus.

Datenaufbereitung

Vokabular zur Verwendung von [ lda.collapsed.gibbs.sampler {lda} `](http://www.inside-r.org/packages/cran/lda/docs/lda.collapsed.gibbs.sampler) Bereiten Sie die Datendateien vor, die "," Dokumenten "entsprechen.

Da vocab einen Korpus darstellt, erstellen Sie zuerst eine Liste von $ N $ Wörtern (als Zeichenfolgen), die in allen Dokumenten enthalten sind. Dies führt dazu, dass jedes Wort durch einen Index $ i $ auf vocab dargestellt wird.

{\tt vocab} = \{w_0, w_1, ..., w_{N-1}\} \\
{\tt vocab[}i{\tt]} = w_i

Erstellen Sie als Datendatei einen Korpus von "corpus_r.txt" mit 1 Zeile = 1 Wort. Dies ist eine Sammlung von Wörtern in allen Dokumenten ohne Duplizierung.

$ head -n 5 corpus_r.txt
Assen
Hauptstadt
Person
Tropfen
Lantanoid
$ wc -l corpus_r.txt
20778 corpus_r.txt

documents ist eine Liste von Dokumenten $ d_k $. Das Dokument $ d_k $ wird durch eine $ m \ times 2 $ -Matrix des Index $ i_ {k, j} $ des im Dokument enthaltenen Wortes und der Anzahl der Vorkommen dieses Wortes im Dokument $ c_j $ dargestellt.

{\tt documents} = \{ d_0, d_1, ..., d_k, ..., d_{m-1} \} \\
d_k = \begin{pmatrix}
i_{k,0} & i_{k,1} & ... & i_{k,n-1} \\
c_{k,0} & c_{k,1} & ... & c_{k,n-1}
\end{pmatrix}

Als Datendatei ist 1 Zeile = 1 Dokument und bereiten Sie "bow_r.txt" mit dem Index (beginnend mit 0) der im Dokument enthaltenen Wörter und der Anzahl der durch einen Doppelpunkt getrennten Vorkommen vor.

$ head -n 5 bow_r.txt
74:1    1109:1  1788:1  7000:2  10308:2 10552:1 12332:2 13489:1 14996:1 15448:1 15947:1 16354:4 17577:1 18262:1 19831:4
3256:3  5278:1  9039:1  12247:1 14529:6 17026:3
2181:1  4062:1  6270:1  6508:1  7405:1  8662:1  15448:1 18905:1
8045:2  9323:1  5934:2
288:3   624:1   691:1   820:2   1078:2  1109:2  1148:3  1251:1  2025:1  2050:1  2072:1  2090:1  2543:2  2626:1  2759:1…
$ wc -l bow_r.txt
13017 bow_r.txt

Ausführungsergebnis

Führen Sie es mit dem folgenden Code aus. Es ist größer, die Datendatei zu analysieren und die angenommene Datenstruktur zu erstellen als die LDA-Verarbeitung (vielleicht ist es einfacher zu schreiben, wenn Sie gut in R sind?).

require("lda")

vocab <- as.vector(read.table("corpus_r.txt", header=FALSE)$V1)

file <- file("bow_r.txt", "r")
docs <- list()
repeat {
  line <- readLines(con=file, 1)
  if(length(line) == 0) break
  doc <- NULL
  for(tc in strsplit(line, "\t")[[1]]){
    col <- c()
    for(c in strsplit(tc, ":")[[1]]){
      col <- c(col, as.integer(c))
    }
    if(is.null(doc))  doc <- cbind(col)
    else              doc <- cbind(doc, col)
  }
  docs <- append(docs, list(doc))
}
close(file)

result = lda.collapsed.gibbs.sampler(docs, 100, vocab, 50, 0.1, 0.1)

top.topic.words(result$topics, 5)

Wenn Sie "top.topic.words ()" ausführen, werden die Wörter aufgelistet, die jedes der $ k = 100 $ -Themen charakterisieren.

     [,1]   [,2]     [,3]     [,4]     [,5]     [,6]   [,7]       [,8]
[1,] "Problem" "Zeitraum"   "Ichiban"   "Auge"     "Zimmer"   "Problem" "Idol" "Box"
[2,] "Kongressabgeordnete" "Bitte" "Wetter"   "Sperren" "Haus"     "von jetzt an" "Ventilator"   "Teil"
[3,] "Gesellschaft" "Versuch"   "China"   "Drehung"   "Toilette" "Tempel" "Seltsam"       "Aufkleber"
[4,] "Religion" "jedermann" "Fehler" "Nicht notwendig"   "Wasser"     "Unmöglich" "Interesse"     "Lack"
[5,] "Prinzip" "Vollzeitangestellter" "Alles"   "China"   "Waschen"   "Inhalt" "Gehorsam"     "Information"
     [,9]   [,10]      [,11]    [,12]      [,13]    [,14]      [,15]  [,16]
[1,] "Weiblich" "Silber"       "Bild"   "Seite? ˅"   "Lied"     "Bitte"   "Schaltkreis" "Arbeitsplätze"
[2,] "Mann"   "Kurzsichtigkeit"     "Anhang"   "Methode"     "Bitte" "Meine"     "Regiment" "Unternehmen"
[3,] "männlich" "aufgewachsen"     "Mehrere"   "Anmeldung"     "Klavier" "Grund"     "Infanterie" "Boss"
[4,] "Mann"   "Snack" "Foto"   "Domain" "Musik"   "Der Umsatz"     "Aktuell" "Mann"
[5,] "Frau"   "Bilderbuch"     "Erde" "Seite"   "Gefühl"   "Nummer" "Foto" "Arbeitsplatz"
... (Fortsetzung bis zu 100 Themen)

Recommended Posts

Vergleich von LDA-Implementierungen
Vergleich von Online-Klassifikatoren
Vergleich der Anpassungsprogramme
Vergleich von 4 Arten von Python-Webframeworks
Vergleich von Apex und Lamvery
Geschwindigkeitsvergleich der Python-XML-Perspektive
Vergleich der eigenständigen DB-Migrationstools für 2020
Vergleich japanischer Konvertierungsmodule in Python3
Vergleich von Edelstein, Bündler und Pip, Venv
Python-String-Vergleich / benutze 'Liste' und 'In' anstelle von '==' und 'oder'
[EDA] Einführung von Sweetviz (Vergleich mit + Pandas-Profiling)
Vergleich von Lösungen bei Gewichtsanpassungsproblemen
Vergleich von Klassenvererbung und Konstruktorbeschreibung
Versuchen Sie den Geschwindigkeitsvergleich der BigQuery Storage API
Tipps: Vergleich der Größe von drei Werten
Vergleich von Python Serverless Frameworks-Zappa mit Chalice
Vergleich von L1-Regularisierung und Leaky Relu
Vergleich der Matrixtranspositionsgeschwindigkeit durch Python
Geschwindigkeitsvergleich von murmurhash3, md5 und sha1