Я работаю над проектом, в котором я хочу извлечь некоторую информацию о содержании серии открытых эссе. В этом конкретном проекте 148 человек написали эссе о гипотетической организации студентов в рамках более крупного эксперимента. Хотя в моей области (социальная психология) типичным способом анализа этих данных было бы ручное кодирование эссе, я хотел бы сделать это количественно, поскольку ручное кодирование является трудоемким и слишком субъективным для моего вкус.
Во время моих исследований о способах количественного анализа данных о свободном ответе я наткнулся на подход, называемый тематическим моделированием (или скрытое распределение Дирихле, или LDA). Моделирование тем берет представление ваших данных в виде пакета слов (матрица терминов и документов) и использует информацию о совпадениях слов для извлечения скрытых тем данных. Этот подход кажется идеальным для моего приложения.
К сожалению, когда я применил тематическое моделирование к своим данным, я обнаружил две проблемы:
- Темы, раскрытые при моделировании тем, иногда трудно интерпретировать
- Когда я повторно запускаю свои тематические модели с другим случайным начальным числом, темы, кажется, резко меняются
Вопрос 2, в частности, касается меня. Поэтому у меня есть два связанных вопроса:
- Могу ли я что-нибудь сделать в процедуре LDA, чтобы оптимизировать процедуру подбора модели для интерпретации и стабильности? Лично меня не очень заботит поиск модели с наименьшим недоумением и / или наилучшим соответствием модели - я в основном хочу использовать эту процедуру, чтобы помочь мне понять и охарактеризовать то, что участники этого исследования написали в своих эссе. Однако я, конечно, не хочу, чтобы мои результаты были артефактом случайного семени!
- В связи с вышеупомянутым вопросом, есть ли какие-либо стандарты для того, сколько данных вам нужно для LDA? В большинстве работ, которые я видел, которые использовали этот метод, анализируются крупные корпорации (например, архив всех научных работ за последние 20 лет), но, поскольку я использую экспериментальные данные, мой объем документов намного меньше.
Я разместил здесь данные эссе для всех, кто хочет испачкать свои руки, и я вставил код R, который я использую ниже.
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))
Редактировать:
Я попытался изменить, nstart
как предложено Flounderer в комментариях. К сожалению, как показано ниже, даже установка nstart
1000 приводит к темам, которые довольно сильно варьируются от случайного семени до случайного семени. Еще раз подчеркну: единственное, что я изменяю в оценке двух моделей ниже, - это случайное начальное число, используемое для начала оценки модели, и, тем не менее, в этих двух прогонах темы, похоже, совсем не согласуются.
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
и просмотреть веб-сайт курса, чтобы увидеть, принесет ли что-нибудь из этого что-нибудь полезное. (Кстати, если вы добавите свои комментарии в ответ, я проголосую за него. Я хотел бы узнать, есть ли у кого-нибудь еще совет, прежде чем я что-либо приму, но я думаю, что ваши комментарии более чем достаточны для того, чтобы считаться ответом).
LDA
функции изtopicmodels
пакета. В частности, вы можете попробовать сделатьnstart
больше. Это гарантированно сделает ваши результаты более стабильными, потому что функция LDA будет просто запускаться снова и снова с различными случайными начальными значениями, а затем возвращать лучший результат. К сожалению, увеличениеnstart
до, скажем, 1000 заставит алгоритм выполнять в 1000 раз больше работы (продолжение)