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"
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).
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)