Pracuję nad projektem, w którym chcę wyodrębnić trochę informacji o zawartości serii esejów otwartych. W tym konkretnym projekcie 148 osób napisało eseje o hipotetycznej organizacji studenckiej w ramach większego eksperymentu. Chociaż w mojej dziedzinie (psychologia społeczna) typowym sposobem analizy tych danych byłoby ręczne kodowanie esejów, chciałbym to zrobić ilościowo, ponieważ ręczne kodowanie jest zarówno pracochłonne, jak i zbyt subiektywne dla mojego smak.
Podczas moich badań nad sposobami ilościowej analizy danych dotyczących swobodnej odpowiedzi natknąłem się na podejście zwane modelowaniem tematów (lub Latent Dirichlet Allocation lub LDA). Modelowanie tematów polega na przedstawianiu danych w postaci worka słów (matrycy dokumentów-terminów) i wykorzystuje informacje o współwystępowaniu słów w celu wydobycia ukrytych tematów danych. To podejście wydaje się idealne dla mojej aplikacji.
Niestety, kiedy zastosowałem modelowanie tematów do moich danych, odkryłem dwa problemy:
- Tematy odkryte przez modelowanie tematów są czasami trudne do interpretacji
- Gdy ponownie uruchamiam modele tematów z innym losowym ziarnem, tematy wydają się dramatycznie zmieniać
Szczególnie dotyczy mnie problem 2. Dlatego mam dwa powiązane pytania:
- Czy jest coś, co mogę zrobić w procedurze LDA, aby zoptymalizować procedurę dopasowania modelu pod kątem interpretacji i stabilności? Osobiście nie dbam tak bardzo o znalezienie modelu o najmniejszym zakłopotaniu i / lub najlepszym dopasowaniu modelu - chcę przede wszystkim skorzystać z tej procedury, aby pomóc mi zrozumieć i scharakteryzować to, co napisali uczestnicy tego badania w swoich esejach. Jednak z pewnością nie chcę, aby moje wyniki były artefaktem losowego nasienia!
- Czy w związku z powyższym pytaniem istnieją jakieś standardy dotyczące ilości danych potrzebnych do wykonania LDA? Większość artykułów, które widziałem przy użyciu tej metody, analizuje duże ciała (np. Archiwum wszystkich artykułów naukowych z ostatnich 20 lat), ale ponieważ używam danych eksperymentalnych, mój zbiór dokumentów jest znacznie mniejszy.
Opublikowałem tutaj esej dla każdego, kto chce ubrudzić sobie ręce, i wkleiłem poniżej kod R, którego używam.
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))
Edytować:
Próbowałem modyfikować nstart
zgodnie z sugestią Flounderer w komentarzach. Niestety, jak pokazano poniżej, nawet ustawienie nstart
1000 powoduje, że tematy różnią się dość radykalnie od losowych nasion do losowych nasion. Żeby jeszcze raz podkreślić, jedyną rzeczą, którą zmieniam w estymacji dwóch poniższych modeli, jest losowe ziarno użyte do rozpoczęcia estymacji modelu, a jednak tematy nie wydają się wcale spójne w tych dwóch seriach.
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
stronę internetową kursu i sprawdzić, czy któraś z nich przynosi coś pożytecznego. (BTW, jeśli wstawisz swoje komentarze w odpowiedzi, zagłosuję za nią. Chciałbym sprawdzić, czy ktoś jeszcze ma porady, zanim cokolwiek zaakceptuję, ale myślę, że twoje komentarze są więcej niż wystarczające, aby uznać je za odpowiedź).
LDA
funkcji wtopicmodels
pakiecie. W szczególności możesz spróbowaćnstart
powiększyć. To jest gwarantowane , aby swoje wyniki bardziej stabilne, ponieważ funkcja LDA będzie po prostu uruchomić w kółko z różnych losowych nasion, a następnie powrót najlepszy wynik. Niestety, zwiększającnstart
do, powiedzmy, 1000 sprawi, że algorytm nie 1000 razy więcej pracy (ciąg dalszy)