Je travaille sur un projet où je souhaite extraire des informations sur le contenu d'une série d'essais ouverts. Dans ce projet particulier, 148 personnes ont écrit des essais sur une organisation étudiante hypothétique dans le cadre d'une expérience plus vaste. Bien que dans mon domaine (psychologie sociale), la façon typique d'analyser ces données serait de coder les essais à la main, je voudrais le faire quantitativement, car le codage manuel est à la fois laborieux et un peu trop subjectif pour mon goût.
Au cours de mes recherches sur les moyens d'analyser quantitativement les données de réponses gratuites, je suis tombé sur une approche appelée modélisation de sujet (ou Latent Dirichlet Allocation, ou LDA). La modélisation de sujet prend une représentation en sac de mots de vos données (une matrice de document de terme) et utilise des informations sur les co-occurrences de mots pour extraire les sujets latents des données. Cette approche semble parfaite pour mon application.
Malheureusement, lorsque j'ai appliqué la modélisation de sujet à mes données, j'ai découvert deux problèmes:
- Les sujets découverts par la modélisation de sujets sont parfois difficiles à interpréter
- Lorsque je réexécute mes modèles de sujet avec une graine aléatoire différente, les sujets semblent changer radicalement
Le problème 2 me concerne particulièrement. Par conséquent, j'ai deux questions connexes:
- Y a-t-il quelque chose que je puisse faire dans la procédure LDA pour optimiser la procédure d'ajustement de mon modèle pour l'interprétabilité et la stabilité? Personnellement, je ne me soucie pas autant de trouver le modèle avec la perplexité la plus faible et / ou le meilleur ajustement du modèle - je veux principalement utiliser cette procédure pour m'aider à comprendre et à caractériser ce que les participants à cette étude ont écrit dans leurs essais. Cependant, je ne veux certainement pas que mes résultats soient un artefact de la graine aléatoire!
- En ce qui concerne la question ci-dessus, existe-t-il des normes concernant la quantité de données dont vous avez besoin pour effectuer un LDA? La plupart des articles que j'ai vus qui ont utilisé cette méthode analysent de grands corpus (par exemple, une archive de tous les articles scientifiques des 20 dernières années), mais, puisque j'utilise des données expérimentales, mon corpus de documents est beaucoup plus petit.
J'ai posté les données de l'essai ici pour quiconque veut se salir les mains, et j'ai collé le code R que j'utilise ci-dessous.
require(tm)
require(topicmodels)
# Create a corpus from the essay
c <- Corpus(DataframeSource(essays))
inspect(c)
# Remove punctuation and put the words in lower case
c <- tm_map(c, removePunctuation)
c <- tm_map(c, tolower)
# Create a DocumentTermMatrix. The stopwords are the LIWC function word categories
# I have a copy of the LIWC dictionary, but if you want to do a similar analysis,
# use the default stop words in tm
dtm <- DocumentTermMatrix(c, control = list(stopwords =
c(dict$funct, dict$pronoun, dict$ppron, dict$i, dict$we, dict$you, dict$shehe,
dict$they, dict$inpers, dict$article, dict$aux)))
# Term frequency inverse-document frequency to select the desired words
term_tfidf <- tapply(dtm$v/rowSums(as.matrix(dtm))[dtm$i], dtm$j, mean) * log2(nDocs(dtm)/colSums(as.matrix(dtm)))
summary(term_tfidf)
dtm <- dtm[, term_tfidf >= 0.04]
lda <- LDA(dtm, k = 5, seed = 532)
perplexity(lda)
(terms <- terms(lda, 10))
(topics <- topics(lda))
Modifier:
J'ai essayé de modifier nstart
comme suggéré par Flounderer dans les commentaires. Malheureusement, comme indiqué ci-dessous, même en définissant nstart
1000 résultats, les sujets varient considérablement d'une graine aléatoire à une graine aléatoire. Juste pour souligner encore une fois, la seule chose que je change dans l'estimation des deux modèles ci-dessous est la graine aléatoire utilisée pour démarrer l'estimation du modèle, et pourtant les sujets ne semblent pas du tout cohérents dans ces deux séries.
lda <- LDA(dtm, k = 5, seed = 535, control = list(nstart = 1000))
(terms <- terms(lda, 10))
Topic 1 Topic 2 Topic 3 Topic 4 Topic 5
[1,] "international" "ethnicity" "free" "credit" "kind"
[2,] "communicate" "true" "team" "mandatory" "bridge"
[3,] "gain" "asians" "cooperate" "music" "close"
[4,] "use" "hand" "order" "seen" "deal"
[5,] "big" "hold" "play" "barrier" "designed"
[6,] "communication" "effective" "big" "stereotypes" "effort"
[7,] "america" "emphasis" "beginning" "asians" "implemented"
[8,] "chinese" "halls" "china" "fantastic" "websites"
[9,] "ethnicity" "minorities" "difference" "focusing" "planned"
[10,] "networks" "population" "easier" "force" "body"
lda <- LDA(dtm, k = 5, seed = 536, control = list(nstart = 1000))
(terms <- terms(lda, 10))
Topic 1 Topic 2 Topic 3 Topic 4 Topic 5
[1,] "kind" "international" "issue" "willing" "play"
[2,] "easier" "ethnicity" "close" "use" "trying"
[3,] "gain" "communication" "currently" "hand" "unity"
[4,] "websites" "communicate" "implemented" "networks" "decision"
[5,] "credit" "bridge" "particularly" "stereotypes" "gap"
[6,] "effort" "america" "credit" "communicate" "normally"
[7,] "barriers" "connection" "fulfill" "came" "asians"
[8,] "effects" "kind" "grew" "asians" "created"
[9,] "established" "order" "perspectives" "big" "effective"
[10,] "strangers" "skills" "big" "budget" "prejudice"
la source
LDA
fonction dutopicmodels
package. En particulier, vous pouvez essayer d'nstart
agrandir. Ceci est garanti pour rendre vos résultats plus stables, car la fonction LDA s'exécutera encore et encore avec différentes graines aléatoires, puis retournera le meilleur résultat. Malheureusement, augmenternstart
jusqu'à, disons, 1000 fera que l'algorithme fera 1000 fois plus de travail (suite)nstart
et de regarder le site Web du cours pour voir si l'un ou l'autre produit quelque chose d'utile. (BTW, si vous insérez vos commentaires dans une réponse, je voterai. Je voudrais voir si quelqu'un d'autre a des conseils avant d'accepter quoi que ce soit, mais je pense que vos commentaires sont plus que suffisants pour compter comme une réponse).Réponses:
Pour ma propre curiosité, j'ai appliqué un algorithme de clustering sur lequel j'ai travaillé à cet ensemble de données.
J'ai temporairement mis les résultats ici (choisissez l'ensemble de données d'essais).
Il semble que le problème ne soit pas les points de départ ou l'algorithme, mais les données. Vous pouvez `` raisonnablement '' (subjectivement, dans mon expérience limitée) obtenir de bons clusters même avec 147 instances tant qu'il y a des sujets / concepts / thèmes / clusters cachés (tout ce que vous souhaitez appeler).
Si les données n'ont pas de sujets bien séparés, quel que soit l'algorithme que vous utilisez, vous risquez de ne pas obtenir de bonnes réponses.
la source
La notion de «sujets» dans les soi-disant «modèles de sujets» est trompeuse. Le modèle ne connaît pas ou n'est pas du tout conçu pour connaître des "sujets" sémantiquement cohérents. Les "sujets" ne sont que des distributions sur des jetons (mots). En d'autres termes, le modèle capture simplement la cooccurrence d'ordre élevé des termes. Que ces structures signifient quelque chose ou non n'est pas l'objectif du modèle.
Le modèle "LDA" comprend deux parties (essentiellement tous les modèles graphiques): a) la définition du modèle et b) une implémentation d'un algorithme d'inférence pour déduire / évaluer les paramètres du modèle. La chose que vous avez mentionnée peut ou non être le problème du modèle "LDA" mais peut être un bug / erreur / mauvaise configuration de l'implémentation spécifique que vous avez utilisée (package R).
Presque toutes les implémentations de "LDA" nécessitent une randomisation. Et par la nature des algorithmes d'inférence (par exemple, MCMC ou inférence variationnelle), vous obtiendrez des solutions minimales locales ou une distribution de nombreuses solutions. Donc, en bref, ce que vous avez observé est en quelque sorte attendu.
Suggestions pratiques:
Essayez différents packages R: par exemple, ce package est réalisé par l'ancien étudiant diplômé de David Blei. Ou essayez même un autre environnement, comme celui-ci . Si vous obtenez des résultats similaires de tous ces packages stables, au moins, vous réduisez un peu le problème.
Essayez de jouer un peu sans supprimer les mots vides. La raison en est que ces mots vides jouent un rôle important dans la connexion des significations sémantiques dans un si petit corpus (par exemple, une centaine d'articles). Aussi, essayez de ne pas filtrer les choses.
Essayez de jouer un peu avec des hyper-paramètres, comme différents nombres de sujets.
Articles sur la cohérence des sujets:
http://www.aclweb.org/anthology-new/D/D12/D12-1087.pdf
http://people.cs.umass.edu/~wallach/publications/mimno11optimizing.pdf
la source
topicmodels
package dans R, qui est essentiellement une interface R avec l'algorithme original implémenté par Blei et ses collègues.