Estoy trabajando en un proyecto donde quiero extraer información sobre el contenido de una serie de ensayos abiertos. En este proyecto en particular, 148 personas escribieron ensayos sobre una organización estudiantil hipotética como parte de un experimento más amplio. Aunque en mi campo (psicología social), la forma típica de analizar estos datos sería codificar los ensayos a mano, me gustaría hacerlo cuantitativamente, ya que la codificación manual requiere mucho trabajo y es demasiado subjetiva para mi gusto.
Durante mis investigaciones sobre formas de analizar cuantitativamente los datos de respuesta libre, me topé con un enfoque llamado modelado de temas (o Asignación de Dirichlet Latente, o LDA). El modelado de temas toma una representación de bolsa de palabras de sus datos (una matriz de documentos de términos) y utiliza información sobre las coincidencias de palabras para extraer los temas latentes de los datos. Este enfoque parece perfecto para mi aplicación.
Desafortunadamente, cuando apliqué el modelado de temas a mis datos, descubrí dos problemas:
- Los temas descubiertos por el modelado de temas a veces son difíciles de interpretar
- Cuando vuelvo a ejecutar mis modelos de tema con una semilla aleatoria diferente, los temas parecen cambiar dramáticamente
El tema 2 en particular me preocupa. Por lo tanto, tengo dos preguntas relacionadas:
- ¿Hay algo que pueda hacer en el procedimiento de LDA para optimizar el procedimiento de ajuste de mi modelo para la interpretación y la estabilidad? Personalmente, no me importa tanto encontrar el modelo con la perplejidad más baja y / o el mejor ajuste del modelo; principalmente quiero usar este procedimiento para ayudarme a comprender y caracterizar lo que escribieron los participantes en este estudio en sus ensayos. Sin embargo, ¡ciertamente no quiero que mis resultados sean un artefacto de la semilla aleatoria!
- En relación con la pregunta anterior, ¿hay algún estándar para la cantidad de datos que necesita para hacer una LDA? La mayoría de los documentos que he visto que han utilizado este método analizan grandes corpus (p. Ej., Un archivo de todos los artículos de Science de los últimos 20 años), pero, dado que estoy usando datos experimentales, mi corpus de documentos es mucho más pequeño.
He publicado los datos del ensayo aquí para cualquier persona que quiera ensuciarse las manos, y he pegado el código R que estoy usando a continuación.
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))
Editar:
Intenté modificar nstart
según lo sugerido por Flounderer en los comentarios. Desafortunadamente, como se muestra a continuación, incluso establecer nstart
1000 resultados en temas que varían dramáticamente de semilla aleatoria a semilla aleatoria. Solo para enfatizar nuevamente, lo único que estoy cambiando en la estimación de los dos modelos a continuación es la semilla aleatoria utilizada para comenzar la estimación del modelo, y sin embargo, los temas no parecen ser consistentes en estas dos ejecuciones.
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
y mirar el sitio web del curso para ver si alguno de ellos produce algo útil. (Por cierto, si inserta sus comentarios en una respuesta, lo votaré. Me gustaría ver si alguien más me aconseja antes de aceptar algo, pero creo que sus comentarios son más que suficientes para contar como respuesta).
LDA
función deltopicmodels
paquete. En particular, podrías intentar hacernstart
más grande. Esto garantiza que sus resultados sean más estables, porque la función LDA simplemente se ejecutará una y otra vez con diferentes semillas aleatorias y luego devolverá el mejor resultado. Desafortunadamente, aumentarnstart
a, digamos, 1000 hará que el algoritmo trabaje 1000 veces más (continuación)