(Je publierai un article que j'ai oublié de publier il y a un an pour un brouillon de digestion)
J'ai abordé certaines des implémentations LDA à des fins de comparaison. Il semble que les options sont les suivantes, mais je vais résumer la procédure jusqu'à l'exécution LDA de chaque langue écrite dans un mémo.
Langue utilisée | Modèle d'utilisation | Extensibilité de la charge | algorithme | |
---|---|---|---|---|
Spark MLlib 1.6.0 | Scala,Java, Python,R |
Bibliothèque | Parallèle/Distribué | Variante Bayes, EM |
gensim | Python | Bibliothèque | Parallèle | Variante Bayes |
GibbsLDA++ | coquille | commander | - | Gibbs Sampling |
R | R | Bibliothèque | - | Gibbs Sampling |
Chacun est exécuté et le temps est mesuré, mais les conditions d'exécution sont assez différentes comme indiqué ci-dessous. Veuillez le lire sans aucun malentendu.
Exécuté dans les conditions $ k = 100 $ et $ iter = 50 $ pour 13 033 $ document $ 20 780 $ mots obtenus en effectuant une analyse morphologique et en supprimant les éléments morphologiques inutiles.
Spark MLlib
algorithme | Nodes | Cores | Temps d'exécution |
---|---|---|---|
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 |
Le temps d'exécution est plus lent que les autres car il inclut également le processus de lecture du fichier local et de création du BoW par RDD. Le résultat le plus lent de l'exécution distribuée est probablement dû au fait que le coût du brassage et du transfert de données entre les nœuds est plus élevé que le coût de calcul de LDA lui-même.
gensim
algorithme | Nodes | Cores | Temps d'exécution |
---|---|---|---|
Variante Bayes | 1 | 4 | 15.396 |
Variante Bayes | 1 | 1 | 20.576 |
Le gensim de Python semble n'être que la variante Bayes, mais il semble avoir un bon équilibre entre performances avec plus de travailleurs, traitement parallèle, vitesse rapide.
GibbsLDA++
algorithme | Nodes | Cores | Temps d'exécution |
---|---|---|---|
Gibbs Sampling | 1 | 1 | 58.993 |
C'était plus rapide que gensim près de $ k = 10 $ avec le traitement d'entrée / sortie des fichiers locaux en plus d'un seul thread, mais est-ce plus lent à mesure que $ k $ devient plus grand? L'échelle peut être difficile, mais convient-elle à une petite exécution ad hoc?
algorithme | Nodes | Cores | Temps d'exécution |
---|---|---|---|
Collapsed Gibbs Sampling | 1 | 1 | 24.247 |
Le calcul lui-même était étonnamment plus rapide que celui de GibbsLDA ++ R lda.collapsed.gibbs.sampler {lda}
(Cependant, le processus de lecture d'un fichier local et de le convertir en un format qui peut être passé à la bibliothèque était lent, donc il est lent au total). R est plus rapide que la vitesse pratique lda {lda}
et lda.cvb0 {lda}
C'est une bonne impression d'attendre la partie où vous pouvez essayer de nombreuses implémentations et algorithmes tels que: //www.inside-r.org/packages/cran/lda/docs/lda.cvb0).
gensim
# -*- coding: utf-8 -*-
#Exemple de LDA par Python gensim
from gensim import corpora, models
import time
#Lire les données du document(Analyse morphologique/Un fichier texte dans lequel les mots sont séparés par des espaces dans un document ligne par ligne avec une nomenclature extraite.)
texts = [ ]
for line in open('docs.gibbs', 'r'):
texts.append(line.split())
#Créer un dictionnaire(id:mot:Nombre d'apparitions)
dictionary = corpora.Dictionary(texts)
dictionary.save_as_text('./docs.dic')
# dictionary = corpora.Dictionary.load_from_text("./docs.dic")
#Création de corpus
corpus = [dictionary.doc2bow(text) for text in texts]
corpora.MmCorpus.serialize('corpus.mm', corpus)
# corpus = corpora.MmCorpus('corpus.mm')
#Calcul LDA
t0 = int(time.time() * 1000)
lda = models.ldamodel.LdaModel(corpus, num_topics=100, iterations=50)
t1 = int(time.time() * 1000)
print t1 - t0
#Calcul LDA(Version compatible multiprocesseur)
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 ++ et son port Java de JGibbsLDA sont des implémentations LDA en ligne de commande. J'ai implémenté Gibbs Sampling, mais il ne semble pas prendre en charge le traitement parallèle (support multi-core) ou le traitement distribué.
Téléchargez GibbsLDA ++ - 0.2.tar.gz
depuis GibbsLDA ++: A C / C ++ Gibbs Sampling LDA, décompressez et compilez.
$ tar zxvf GibbsLDA++-0.2.tar.gz
$ cd GibbsLDA++-0.2/
$ make all
Si g ++
est disponible, make all
terminera la construction et la commande src / lda
sera exécutée.
ʻError: 'atof' n'a pas été déclaré dans cette portée, ʻerror: 'printf' n'a pas été déclaré dans cette portée
[ici](http://yuutookun.hatenablog.com/entry/20120831/ 2 Ajoutez # include
au fichier faisant référence à 1346394002).
$ vim src/util.cpp
...
#include <stdio.h>
#include <stdlib.h> //ajouter à
#include <string>
...
$ vim src/lda.cpp
...
*/
#include <stdio.h> //ajouter à
#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>
Créez un fichier dans lequel les mots contenus dans le document sont listés séparés par des blancs afin que le nombre de documents soit sur la première ligne, puis "1 ligne = 1 document". S'il y a des lignes vides (documents avec 0 mots qui représentent des caractéristiques), l'erreur ʻDocument invalide (vide)! `Se produira.
$ head -n 5 docs.gibbs
13033
Demande de stockage Sélectionnez Carte Carte Cas de la carte Méthode de réponse Méthode Modèle interne possible Enregistrement de capacité Enregistrement Enregistrement Enregistrement Enregistrement Régler l'heure Enregistrer Enregistrer Enregistrer Enregistrer Enregistrer
Le monde, le monde, le monde, les choses importantes, le bon sens, le bon sens, le bon sens, le bon sens, le bon sens, le bon sens, moi-même
Jeu d'opération de vêtements de caractère
Meilleure date de la meilleure illusion
Téléphone Téléphone Téléphone Adieu Réel Présent Présent Comme Présent Comme S'il Vous Plaît S'il Vous Plaît Larmes Larmes Larmes Narita Conversation Yeux Négatifs Relation Salle Amour Uruguay Uruguay Uruguay Uruguai Owl Sentiments finaux Dans les coulisses…
…
Exécutez en spécifiant le nombre de sujets $ k $ et le nombre de répétitions sur la ligne de commande.
$ 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!
Lorsque vous avez terminé, vous devriez avoir des fichiers.
model-final.others
est le paramètre d'exécution lorsque ce modèle a été créé, et wordmap.txt
contient l'ID attribué au mot.
$ 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
Salut 2125
...
model-final.twords
liste les mots les plus caractéristiques pour chaque sujet, comme spécifié par l'option -twords
(ce fichier ne sera pas créé si l'option -twords
est omise).
$ cat model-final.twords
Topic 0th:
Personne 0.047465
Ressentir 0.019363
Qi 0.018178
Autre (0.016968
Normal 0.016004
Topic 1th:
Travail 0.043820
Heure 0.024824
Maison 0.019440
Maintenant 0.017962
Mère 0.016881
Topic 2th:
Si 0.033522
Mois 0.018820
Société 0.018083
Assurance 0.015252
Demande 0.012468
…
model-final.phi
est la probabilité d'apparition des mots pour chaque sujet. 1 ligne = 1 sujet et le nombre de colonnes dans une ligne correspond au nombre de mots du corpus. En d'autres termes, il s'agit d'une matrice de "$ k $ lignes (nombre total de mots) colonnes". Ce sont les données numériques qui sont à la base de model-final.twords
.
$ 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
est la probabilité que chaque document appartienne à quel sujet. Correspond à 1 ligne = 1 document et 1 colonne = 1 sujet. En d'autres termes, ce sont les données matricielles de "(nombre de documents) lignes $ k $ colonnes".
$ 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
est une liste de données source au format [mot ID: sujet] pour chaque ligne = 1 document.
$ 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 ++ est presque au point de créer un modèle numérique, vous devez donc mapper vous-même les résultats autres que «twords» aux documents et aux mots.
Personnellement, c'est un langage R qui est difficile à entrer dans la fonction de langage et qui est un peu timide, mais [lda.collapsed.gibbs.sampler {lda}](http://www.inside-r.org/packages/cran/lda/docs/lda Si vous regardez .collapsed.gibbs.sampler), vous pouvez voir que certains modèles de Collapsed Gibbs Sampling sont implémentés.
Il ne semble pas prendre en charge le traitement parallèle (support multicœur) ou le traitement distribué.
Tout d'abord, installez le langage R sur CentOS 7.2 (si la commande rpm
ci-dessous donne un 404, supprimez la partie fichier de l'URL pour trouver la version appropriée).
$ sudo rpm -ihv http://ftp.riken.jp/Linux/fedora/epel/7/x86_64/e/epel-release-7-5.noarch.rpm
$ sudo yum install R
Une fois l'installation de R terminée, lancez l'interface interactive et installez le package LDA. En chemin, j'essaye d'installer le paquet LDA dans / usr / lib64 / R / library
, mais je ne suis pas un utilisateur root
, donc je spécifie une bibliothèque personnelle. Il vous sera également demandé la source du téléchargement, alors sélectionnez le miroir CRAN du Japon (Tokyo).
Ci-dessous, reshape2
et ggplot2
sont également installés pour exécuter la démo.
$ 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)
Il semble que ne suivant pas le changement de spécification de ggplot2
stat_count () ne doit pas être utilisé avec ay esthétique.
Se produira et le graphique ne sera pas affiché. Si vous démarrez la partie qplot ()
correctement et manuellement, cela fonctionnera, mais comme le processus de calcul LDA lui-même est terminé, ignorez-le et continuez.
> 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"
Les résultats sortent.
vocab to use [
lda.collapsed.gibbs.sampler {lda} ](http://www.inside-r.org/packages/cran/lda/docs/lda.collapsed.gibbs.sampler) Préparez les fichiers de données correspondant à
, documents
.
Puisque «vocab» représente un corpus, faites d'abord une liste de mots $ N $ (sous forme de chaînes) contenus dans tous les documents. Cela fera que chaque mot sera représenté par un index $ i $ sur vocab
.
{\tt vocab} = \{w_0, w_1, ..., w_{N-1}\} \\
{\tt vocab[}i{\tt]} = w_i
En tant que fichier de données, créez un corpus de corpus_r.txt
avec 1 ligne = 1 mot, qui est une collection de mots dans tous les documents sans duplication.
$ head -n 5 corpus_r.txt
Assen
Capitale
la personne
Goutte
Lantanoïde
$ wc -l corpus_r.txt
20778 corpus_r.txt
documents
est une liste de documents $ d_k $. Le document $ d_k $ est représenté par l'index $ i_ {k, j} $ du mot contenu dans le document et la matrice $ m \ times 2 $ du nombre d'occurrences de ce mot dans le document $ c_j $.
{\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}
En tant que fichier de données, 1 ligne = 1 document, et préparez bow_r.txt
avec l'index (à partir de 0) des mots contenus dans le document et le nombre d'occurrences séparées par deux-points.
$ 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
Exécutez-le avec le code suivant. Il est plus gros d'analyser le fichier de données et de créer la structure de données supposée que le traitement LDA (il est peut-être plus facile d'écrire si vous êtes bon en R?).
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)
Lancer top.topic.words ()
listera les mots qui caractérisent chacun des sujets $ k = 100 $.
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] "problème" "période" "Ichiban" "Œil" "chambre" "Problème" "Idole" "boîte"
[2,] "Membre du Congrès" "S'il vous plaît" "Météo" "Fermer à clé" "Maison" "à partir de maintenant" "ventilateur" "partie"
[3,] "société" "procès" "Chine" "rotation" "toilette" "Temple" "Bizarre" "autocollant"
[4,] "religion" "toutes les personnes" "erreur" "Inutile" "eau" "Impossible" "Intérêt" "vernis"
[5,] "Principe" "Employé à plein temps" "Tout" "Chine" "La lessive" "Contenu" "Obéissant" "information"
[,9] [,10] [,11] [,12] [,13] [,14] [,15] [,16]
[1,] "Femme" "argent" "image" "site" "Chanson" "S'il vous plaît" "circuit" "travaux"
[2,] "Homme" "Myopie" "Attachement" "Méthode" "S'il vous plaît" "ma" "régiment" "Compagnie"
[3,] "Masculin" "adulte" "Plusieurs" "enregistrement" "piano" "Raison" "infanterie" "patron"
[4,] "Homme" "goûter" "Photo" "domaine" "musiques" "Ventes" "Courant" "Homme"
[5,] "femme" "Livre d'images" "Terre" "page" "Sentiment" "nombre" "Photo" "lieu de travail"
... (Continue jusqu'à 100 sujets)
Recommended Posts