Для лабораторной работы по тематическому моделированию мне стало интересно проанализировать тематику произведений моего любимого писателя - Леонида Андреева. Для этого я вручную собрала тексты его рассказов, используя расширение для Гугл Хрома Web Scraper. В итоговом датасете получилось недостаточное количество слов, поэтому я так же приняла решение разбавить его тексты произведениями другого писателя - Александра Куприна.
Я выбрала именно его по той причине, что они современники и писали практически в одно время. Годы творчества Андреева - 1889-1919, Куприна - 1889-1934, но я взяла рассказы второго писателя только до 1919 для лучшей сопоставимости.
Итоговое количество произведений от каждого автора:
andreev %>% group_by(author) %>% summarize(count = n_distinct(name))
Количество наблюдений в датасете больше этой суммы и равняется 267, потому что некоторые произведения располагались на разных страницах и поэтому поделены на части.
Операции, которые я провела с данными:
- Приведение к нижнему регистру;
- Удаление всей пунктуации;
- Удаление чисел;
- Лемматизация с помощью MyStem.
На этом этапе я не удаляла стоп-слова, но сделаю это во время применения алгоритма выделения тем. В список войдут стандарные стоп-слова из пакета stopwords, несколько слишком частотных слов (‘это’, ‘который’) и имена героев.
head(a_words)
a_words$fragment = rep(1:ceiling(nrow(a_words)/500), each = 500)[1:nrow(a_words)]
a_texts <- a_words %>% group_by(author,name, fragment) %>%
summarize(text = paste(lem, collapse=" "))
После токенизации у меня получилось 830354 слова. Средняя длина рассказов равняется 3110 слов, что слишком много, поэтому я делю тексты на части по 500 слов (значение выбрано экспериментальным путём) и соединяю их, после чего у меня остаётся 1846 фрагментов.
Для поставленной задачи я решила выбрать алгоритм LDA через пакет mallet.
Выбранное количество тем = 25. С меньшим количеством тем они были слишком абстрактные и не показывали ничего конкретного, а с большим почти все темы скорее отражали отдельные рассказы, чем общие для разных произведений.
Так выглядит наш частотный список после того, как мы убрали самые распространенные слова:
mallet.instances <- mallet.import(id.array=as.character(a_texts$fragment),
text.array=a_texts$text,
stoplist="stopwords.txt")
topic.model <- MalletLDA(num.topics=25)
topic.model$loadDocuments(mallet.instances)
topic.model$setAlphaOptimization(20, 50)
vocabulary <- topic.model$getVocabulary()
word.freqs <- mallet.word.freqs(topic.model)
word.freqs %>% arrange(desc(doc.freq)) %>% head(10)
Теперь я запускаю модель с 800 итерациями (при меньшем количестве темы показались мне слишком зашумлёнными).
По этой визуализации видно, что темы довольно несбалансированные - они либо очень большие, либо очень маленькие, что, как мне кажется, не очень хорошо, но с другим количеством тем получалась похожая ситуация, поэтому мы рассмотрим эти темы.
Значение relevance metric я выставила на 0.5, чтобы посмотреть frequent and exclusive terms.
Тема 1: шум (18.8%)
Тема 1 является самой большой и в неё входят очень частотные слова. Тут довольно много слов для описания людей (рука, глаз, лицо, голова, голос, тело), но всё же слишком много сторонних слов, чтобы выделить конкретно эту тему.
Тема 2: Диалог (14.1%)
Эта тема состоит из слов (по большей части глаголов) для описания диалогов между персонажами - говорить, слово, понимать, слышать, рассказывать. Тема очень большая и это неудивительно, ведь диалоги характерны для художественной литературы.
Тема 3: неразборчиво (11.3%)
Тема 4: неразборчиво (10.6%)
Тема 5: Окружение (10.2%)
Здесь много терминов для описания местности и обстановки (земля, стена, город, улица, свет, небо) и много прилагательных (черный, белый, темный, огромный).
Тема 6: Смерть/страдания (9.3%)
Тема номер 6 очень грустная :(
Тут много слов, связанных со смертью (смерть, умирать, мертвый, убивать)
и в целом негативно окрашенных слов (ужас, слеза, плакать, страшный).
Большой размер темы указывает на то, что выбранные мною писатели любят
писать про грусть и тяжесть жизни.
Тема 7: Любовь (3.6%)
К счастью, после грустной шестой темы нам встречается седьмая, которая описывает что-то вроде отношений между мужчиной и женщиной и влюблённости (любовь, сладкий, красивый, цветок). Эта тема почти в три раза меньше предыдущей, то есть тема любви менее популярна у этих писателей, чем тема боли, но всё ещё кажется довольно распространённой.
Тема 8: Писательство (2.3%)
Неудивительно, что в рассказах писателей большое
значение уделяется теме письма. Эта тема мне кажется очень хорошей и
практически без шума, тут мы видим такие слова как письмо, бумага,
рассказ, листок, писатель, почерк, возможно, что это из
автобиографических рассказов про самих авторов.
Тема 9: Трактир (2.1%)
Здесь чётко выделяются темы алкоголя (водка, пьяный, рюмка) и еды (хлеб, кусок, обед, сахар), кажется, что это про посещение трактиров и подобных заведений.
Тема 10: неразборчиво (1.8%)
Тема 11: неразборчиво (1.6%)
Тема 12: Театр (1.8%)
Здесь очень явно выделяется лексика, связанная с театром и выступлениями (сцена, актер, публика, артист).
Тема 13: Война (1.3%)
Эта тема связана с войной (война, лазарет,
немец, русский), что вполне ожидаемо, ведь время творчества этих
писателей выпало как раз на Первую мировую войну, а Куприн даже был на
неё мобилизован.
Тема 14: Армия (1.2%)
Тема армии довольно тесно связана с темой войны, поэтому её появление тоже неудивительно. Здесь преобладает описание структуры армии (полк, рота, батальон) и должностей (капитан, солдат, офицер).
Тема 15: Церковь (1.2%)
Здесь тоже тема выделяется довольно чётко и это церковь (дьякон, поп, священник) и вера (вера, бог, молиться). Интересный факт заключается в том, что Куприн был человеком верующим и много про это писал, а Андреев наоборот отрицал церковь. Тут у меня появилась гипотеза, что при интерпретации разницы в темах у этой будет большой перевес в одну сторону.
Тема 16: неразборчиво (1.2%)
Тема 17: Семья (1.1%)
Здесь много терминов, связанных с родственными
отношениями (отец, мама, дядя, тетка, ребенок), но качество темы
оставляет желать лучшего, потому что здесь много шума.
Тема 18: неразборчиво (1.1%)
Тема 19: неразборчиво (1%)
Тема 20: перемешана (Суд и больница) (1%)
К сожалению, эта тема сильно intruded и тут
выделяются два топика - суд (пристав, присяжный, прокурор) и больница
(доктор, больной, палата, пациент).
Тема 21: передвижение (0.9%)
Тема 21 связана с путешествиями, на поезде в частности (вагон, станция, платформа).
Тема 22: неразборчиво (0.9%)
Тема 23: море (0.8%)
Здесь тоже весьма отчётливо выделяется тема
мореплавания (пароход, палуба, море), хотя сюда и затесался некоторый
шум.
Тема 24 и 25: неразборчиво (по 0.6%)
И наконец я хочу сравнить присутствие тем в текстах двух писателей.
Для этого я беру матрицу doc.topics и делю её на две части
по отрывкам, принадлежащим Андрееву и Куприну, считаю среднее
присутствие каждой темы для каждого писателя и соединяю это в
датафрейм.
(наверняка есть более эффективный способ с присоединением метаданных, но
я смогла придумать только такой)
#1043
names(a_texts)[3] <- 'document'
diff <- as.data.frame(doc.topics)
and <- subset(diff, rownames(diff) %in% seq(1:1042))
kup <- subset(diff, rownames(diff) %in% seq(1043:1846))
and_mean <- colMeans(and)
kup_mean <- colMeans(kup)
difference <- data.frame(and_mean, kup_mean)
Затем я считаю разницу для двух колонок и даю названия темам, убираю неразборчивые темы и получаю такую таблицу.
difference$diff <- difference$and_mean - difference$kup_mean
difference <- difference %>% arrange(desc(difference$diff)) %>% tibble::rownames_to_column("topic")
difference <- difference %>% mutate(Topic = case_when(topic == "V1" ~ "неразборчиво",
topic == "V2" ~ "неразборчиво",
topic == "V3" ~ "Театр",
topic == "V4" ~ "Страдания",
topic == "V5" ~ "Любовь",
topic == "V6" ~ "Писательство",
topic == "V7" ~ "неразборчиво",
topic == "V8" ~ "Трактир",
topic == "V9" ~ "Суд и больница",
topic == "V10" ~ "Перемещение",
topic == "V11" ~ "Окружение",
topic == "V12" ~ "неразборчиво",
topic == "V13" ~ "неразборчиво",
topic == "V14" ~ "Церковь",
topic == "V15" ~ "Война",
topic == "V16" ~ "неразборчиво",
topic == "V17" ~ "неразборчиво",
topic == "V18" ~ "Семья",
topic == "V19" ~ "неразборчиво",
topic == "V21" ~ "Диалог",
topic == "V22" ~ "неразборчиво",
topic == "V23" ~ "Мореплавание",
topic == "V24" ~ "неразборчиво",
topic == "V25" ~ "Армия"))
difference <- difference %>% select(-topic) %>% filter(Topic != 'неразборчиво')
Результаты получились довольно интересными!
Как можно увидеть, Андреев чаще пишет про семью, описывает диалоги и окружения, упоминает суды и больницы. Не уверена, чем это можно объяснить, но характерные для Куприна темы более понятны. Как я и предполагала ранее, он чаще пишет про церковь, что, опять-таки, объясняется его верой в бога и отрицанием Андреевым церкви. Более частое упоминание войны тоже имеет смысл, ведь он успел побывать на Первой мировой войне. А вот более частые упоминания им страданий меня очень удивили, я ожидала сильного перевеса в сторону Андреева, потому что он известен своим пессимизмом, но Куприн смог его в этом обойти.