Использование NLTK, Gensim, Spacy и pyLDAvis для обнаружения говорящих моделей речи главных героев действия.

Приключенческие боевики уже много лет радуют публику. От захватывающей автомобильной погони в «Буллите» (1968) до ожесточенного боя Джона Уика 3 (2019), кинозрители снова и снова стекаются в кинотеатры, чтобы получить дозу адреналина.

Хотя жанр действительно приносит много удовольствия, есть несколько довольно очевидных проблем, на которые мне также было любопытно разобраться. Во-первых, в подавляющем большинстве боевиков и приключенческих фильмов изображен белый главный герой. Во-вторых, указанные главные герои часто относятся к женщинам и второстепенным персонажам как к объектам, которые нужно завоевать. Это сразу видно, скажем, в франшизе о Джеймсе Бонде, но я позволю резюмировать эту цитату из франшизы XXX с Вином Дизелем в главной роли:

«Позвольте мне упростить вам задачу. Надрать задницу, поймать девушку и попытаться выглядеть крутым, пока вы это делаете ».

Помня все это, я не обязательно стремился раскрыть то, что в итоге обнаружил в этом проекте. Фактически, я изначально пытался выделить личность через диалог, пытаясь сопоставить большую пятерку качеств устного слова с помощью уменьшения размерности. Хотя я не смог пролить свет на личностные черты, используя описанные ниже методы, я смог найти явные токсичные модели речи по нескольким темам. Итак ... давайте погрузимся!

Данные

Для этого проекта я использовал массивный корпус фильмов Калифорнийского университета в Санта-Круз. Корпус разбит по жанрам и содержит 960 сценариев фильмов, в которых диалог в фильме отделен от описания сцен. Здесь я решил обратить особое внимание на жанр боевиков и приключений, который включает 143 фильма, от Рэмбо до Крепкого орешка.

Недавно я завершил проект по распечатке профиля личности каждого главного героя фильма в корпусе, в котором я более подробно рассказываю о предварительной обработке текста, поэтому я сосредоточусь на некоторых более подробных методах НЛП и моделировании тем. в этом посте.

Достаточно сказать, что после моей первоначальной предварительной обработки у меня был фрейм данных pandas с двумя столбцами (персонаж и диалог) для каждого главного героя в корпусе и каждой строки их диалога в виде отдельных строк, в общей сложности 127K высказываний примерно на 150 символов.

Обработка естественного языка

Когда данные были готовы к работе, пришло время использовать инструментарий естественного языка и подготовить корпус для тематического моделирования.

Самое интересное в НЛП (обработка естественного языка) заключается в том, что здесь нет жестких и установленных правил в отношении процессов или инструментов. Обычно после предварительной обработки / нормализации идет токенизация, стемминг / лемминг, векторизация, уменьшение размерности и визуализация. Однако шаги и нюансы значительно различаются в зависимости от контекста. Например, в одной ситуации может иметь смысл использовать биграммы с векторизатором счетчика и LSA, в то время как в другой имеет смысл использовать триграммы с TFIDF и NMF. Вы можете думать об этом как о художнике в студии, экспериментирующем с моделями и лепке, пока не получится что-то красивое.

Для целей этой статьи я не буду повторять множество итераций (и неудач) в этом проекте, а вместо этого рассмотрю шаги и модель, которые дали наилучшие результаты.

Сначала я преобразовал каждое предложение в список слов, удалив знаки препинания и ненужные символы с помощью функции Gensim simple_preprocess (), как показано в приведенном ниже коде:

Затем я определил биграммы и триграммы. По сути, это захватывает два слова рядом друг с другом и гарантирует, что слова, которые должны быть вместе, такие как «Сан-Франциско», останутся одним целым. Другими словами: биграммы - это два слова, часто встречающиеся в документе вместе. Триграммы - это 3 часто встречающихся слова.

Модель Gensim Phrases может создавать и реализовывать биграммы, триграммы, квадграммы и многое другое. Два важных аргумента Phrases - это min_count и threshold. Чем выше значения этого параметра, тем сложнее объединить слова в биграммы. Код для этого также ниже:

Затем я определил несколько функций. А именно, я лемматизировал слова и убирал стоп-слова. Лемматизация - это не что иное, как преобразование слова в его корневое слово. Например: лемма слова «деревья» - это «дерево». Точно так же «говорящий» - ›« разговор »,« гуси »-› «гусь» и т. Д. Стоп-слова - это, по сути, очень распространенные слова в английском языке, которые мы не хотим включать в наш анализ. Такие слова, как "the" и "for" и т. Д. Для кода ниже я импортировал стоп-слова и лемматизацию с помощью Spacy.

От слов к словарю / корпуса к LDA

Теперь, когда я приближался к возможности разделить эти многомерные данные на темы, я затем преобразовал свой список слов в словарь, используя id2word, а также в корпус. Причина этого в том, что двумя основными входами в тематическую модель LDA являются (как вы уже догадались!) Словарь (id2word) и корпус:

Это приблизило меня к тому, чтобы быть готовым к моделированию! Последней частью головоломки было определить, сколько тем я хотел бы изучить. Здесь есть несколько техник, включая метод силуэта, но я решил создать так называемый график локтя: по сути, эвристика, помогающая найти подходящее количество кластеров для запуска модели. Этот метод рассматривает процент дисперсии, объясненный как функцию количества кластеров: следует выбрать количество кластеров, чтобы добавление еще одного кластера не давало лучшего моделирования данных. На сюжете это обычно точка, похожая на локоть.

В этом случае у меня не было сильного «локтя» для визуализации. Возможно, на 3 или 4, но ничего определенного. Это должен был быть еще один случай, когда я попробовал несколько вещей и оценил качество результата.

Итак, наконец, к модели! Затем я поместил и словарь, и корпус в свою модель LDA вместе с количеством тем, которые хотел изучить. Я нашел наиболее внятные результаты по 4 темам. Помимо количества тем, alpha и eta являются гиперпараметрами, влияющими на разреженность тем. Согласно документации Gensim, оба значения по умолчанию - 1.0 / num_topics ранее.

chunksize - количество документов, которые будут использоваться в каждом обучающем блоке. update_every определяет, как часто следует обновлять параметры модели, а passes - общее количество проходов обучения. Вот код модели:

Большой. Теперь визуализируем некоторые результаты. Хотя допустимо просто распечатать темы модели, существует гораздо более наглядный и интерактивный способ отображения результатов: pyLDAvis. Каждый кружок на левом графике представляет тему. Чем больше пузырь, тем более распространена эта тема. С 4 темами я смог получить довольно дифференцированные (не перекрывающиеся) пузыри со значимыми результатами, как показано ниже:

Выводы + заключительные мысли

По всем четырем темам в корпусе я видел свидетельства командных и женоненавистнических слов. На более `` ручной '' стороне были слова действия, такие как `` иди '' получить '' хочу '' взять ', вплоть до того, что можно описать только как `` менее ручные' 'слова, такие как `` ебать' ', детка' ', убить' ' и т.п.

Конечно, есть много фильмов, в которых главному герою нужно просто…

… Но неоднократно такие слова, как «получить», по всей видимости, подразумевают одержимость и решительное командование другими, а не просто потребность куда-то добраться. Помимо юмора, эта визуализация показывает, что существует реальная проблема с написанием главных героев боевиков с 60-х годов до настоящего времени, и если бы мне пришлось назвать темы в моем визуальном изображении, я бы сказал, что они сводятся к следующему:

  • Команды и принудительные запросы
  • Угрозы
  • Женщины как объекты
  • Вооружение

Мы надеемся, что эта тенденция изменится в будущем, и мы увидим не только более разнообразное представление ведущих мужчин и женщин в жанре боевиков, но и большее сочувствие в их словах и поступках.

Это все для этого проекта, но в будущем мне интересно провести тот же процесс для других жанров, представленных в корпусе. А пока, если вы хотите глубже погрузиться в код, не стесняйтесь проверить мое репозиторий проекта.

Приложение

Github, LinkedIn, Портфолио