Pull to refresh

Извлечение троих: Как найти пасхалки в книгах Стивена Кинга с помощью NLP алгоритмов

Entertaining tasks Python *Algorithms *Reading room Lifehacks for geeks
Sandbox

Предыстория

Которую вы можете пропустить, но не станете, верно?

Дело было за последней прочитанной мной книгой Стивена Кинга - "Томминокеры". В очередной раз скользнув по "еще одному американскому имени не очень-то главного героя", я вдруг задумалась: "А что, если имя, которое я даже толком не прочитала, было важным? Что, если это имя персонажа другой уже прочитанной мной истории? Что, если из-за того что я, среднестатистический человек в пятницу вечером, не держу в голове целый город (или даже штат) имен всех персонажей, я упускаю детали мира дядюшки Кинга?" Стало немного-невыносимо больно за возможные утраченные пасхалки.

Не желая с этим мириться, я стала думать: "Как это можно исправить?". Гуглить каждое имя в книге - опасно, в первую очередь для пока еще свободного вечера пятницы. Более того, можно нарваться на спойлеры. Посмотреть уже созданные кем-то "карты" связей романов - можно, но эти карты создаются людьми, такими же, как мы с вами, а значит а) что-то могло быть упущено, б) снова могут быть спойлеры. Перечитывать книги (так же, как я пересматривала сериал "Lost") для того, чтобы записывать отсылки в блокнот и рисовать карту - опасно, но уже для ментального здоровья.

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

База

и данных, и методов.

Для начала необходимо было найти данные, а именно текст нескольких романов. Повезло, что подходящий датасет быстро нашелся на Kaggle : https://www.kaggle.com/ttalbitt/stephen-king-books. Архив содержит 16 романов на английском языке: часть цикла "Темной башни", "Кэрри", "Мизери", "Сияние" и др. Он стал основой, с одной единственной поправкой: к нему был добавлен текст "Томминокеров", ведь, как я говорила, это последняя прочитанная мной книга "короля ужасов", а потому проверять работу алгоритмов на ее примере мне было наиболее удобно.

Реализовывала я все на Python, а потому сразу подгрузила главные библиотеки, из интересного здесь:

  • zipfile - для работ с архивами, если вы, как и я, цените каждый свободный байт.

  • nltk - банально, но эффективно для работы с NLP задачами, особенно на английском языке.

  • spacy - еще одна NLP библиотека с акцентом на извлечение именованных сущностей.

  • regex (re) - с текстом работаем? - работаем, а значит, без регулярок не обойтись.

  • networkx - будем строить карты связей или графы.

Томминокеры

стучатся в дверь первыми.

Сначала, попробуем достать все необходимое (персонажи) хотя бы из одного романа: "Томминокеры". По ходу дела, заодно и узнаем, кто же все-таки главный герой романа (Бобби или Гард?). А если все сработает, то, повторив трюк с извлечением персонажей для всех, сможем соединить романы посредством совместно упоминаемых персонажей.

Но как заставить машину извлечь имена персонажей? Под это в NLP выделили отдельную область NER (Named Entity Recognition) или распознавание именованных сущностей. Методы NER позволяют вычленить из текста сущности (объекты) и присвоить им тип: Личность, Локация, Организация, Дата и т.д. Разные библиотеки имеют разный набор типов сущностей, разные алгоритмы их извлечения для разных языков.

Я остановилась на библиотеке SpaCy, на ее довольно точной модели для английского языка "en_core_web_lg". NLTK тоже неплохо справлялся, но SpaCy:
а) распознала чуть больше человеков,
б) была удобнее для обработки результатов: выдавала лист string-ов, а не tuple.

Как сделали:

  1. Отдали текст романа модели, чтобы распознать все возможные сущности.

  2. Извлекли только те, что имеют тип "PERSON".

  3. Убрали принадлежность в виде " 's" (можно назвать примитивным стеммингом)

  4. Также убрали Mrs, Mr, Ms, но решили не убирать Dr.

  5. Оставили только имена состоящие не менее, чем из двух слов (например, Бобби Андерсон или Джим Гарденер), т.к. по отдельной извлеченной фамилии или имени точно определить персонажа не представляется возможным: а вдруг брат/сестра/тезка.

  6. Интереса ради: посчитали частоту упоминаний каждого имени.

Что получилось:

Оказалось, что главный герой "Томминокеров" все-таки Бобби Андерсон, а Джим даже не на втором месте. Прости, Джим.

Топ-5 наиболее часто упоминаемых персонажей "Томминокеры"
Топ-5 наиболее часто упоминаемых персонажей "Томминокеры"

Однако, чтобы результаты были совсем честными, при подсчете стоило учитывать отдельно упоминаемые фамилии и имена, которые мы выкинули, и объединять их разные формы в одну (Джим Гарденер, Джеймс Гарденер и т.д.). Это все можно сделать, например, разбив на имя и фамилию или использовав NEL алгоритмы (связывание сущностей), но для первоначальной идеи поиска пасхалок нам это не требовалось.

Все персонажи

и не только они!

Настал момент истины: повторим проделанное с "Томминокерами" для всех имеющихся романов и посмотрим, кто из "уважаемых" встречался в нескольких книгах и каких.

"И что получилось?" - 117 "человек", которые встречаются в 2 и более книгах. И если не знать американскую культуру 70-80-х (что вполне простительно), то можно строчка за строчкой просматривать имена и удивляться насколько хорошо мы с вами сработали. И даже такие попадания, как "Mike Mike" (простое дублирование имени) или "Roland Eddie" (сочетание имен героев) не омрачают наше счастье. Но длится оно все-таки недолго:

  1. На 10-й строчке вы встречаете Silva Compass - и нет, это не кличка очередного ребенка, а компания производящая... компасы.

  2. На 13-й строчке фирменный хук с правой нашей логике дает Sherlock Holmes. "Элементарно!" - кричите вы и понимаете, что сюда попали и другие знаменитые люди и персонажи, и среди них:

    • Charlie the ChooChoo - 3 раза

    • Elvis Presley - 5 раз

    • Donald Duck - 3 раза

    • Jesus Christ - 11 раз

"Ну и что делать?" - Можно было бы: настроить автоматическое обращение куда-то сюда или спарсить оттуда же лист персонажей и последовательно проверять, кто из наших героев в него входит, а кто остается за рамками.

"А что в итоге сделали?" - Вручную (ну не только) отсмотрели все 117 имен и присвоили каждому наблюдению категорию. Распределение по категориям можно видеть ниже.

Категории "упоминаемых" и кол-во вошедших в ту или иную категорию
Категории "упоминаемых" и кол-во вошедших в ту или иную категорию

"Но почему?" - Потому что интересно! Интересно, кто такой Джон Дири, каких президентов любит/ненавидит, но упоминает Кинг, и какие в принципе люди/персонажи заслужили упоминания автора аж в нескольких книгах. Например, Джон Дири - вовсе не персонаж, а фирма выпускающая сельхоз технику: тракторы, ведь "Больше тракторов богу тракторов... или не тракторов (см. график ниже)" .

Самые "упоминаемые" и кол-во книг, в которых они встречаются
Самые "упоминаемые" и кол-во книг, в которых они встречаются

"А карты-то будут?" - Теперь точно будут. Когда мы знаем, кто есть кто, мы наконец можем взять только персонажей и извлечь книги, в которых они упомянуты. На основе этого для каждой книги мы можем получить следующее: книгу-соседа и силу связи (кол-во совместно упоминаемых персонажей), а значит построить и карту ниже.

Если со «Смиренными сёстрами Элурии» (The Little Sisters of Eluria), «Стрелком» (The Gunslinger), «Извлечением троих» (The Drawing of the Three), «Бесплодными землями» (The Waste Lands), «Колдуном и кристаллом» (Wizard and Glass), «Песней Сюзанны» (Song of Susannah) и самой «Тёмной башней» (The Dark Tower) все ясно и предсказуемо: все это книги цикла Темная башня, то связи с «Салимовым Уделом» (Salems Lot) и «Черным домом» (Black House) как раз то, к чему мы все это время шли: неочевидные отсылки, которые можно упустить, если не выписывать себе все имена.

Так, можно упустить, что один из главных героев книги "Салемов удел", отец Каллагэн - второстепенный герой цикла «Темная Башня» (части: "Волки Кальи", "Песнь Сюзанны" и "Темная башня"). А "Черный дом" тесно связан с "Темной башней" другим персонажем, но упоминать и раскрывать детали я не буду во избежание спойлеров.

Что дальше

и как обнаружить больше пасхалок?

  1. Можно посмотреть на локации, т.к. любой фанат Кинга может с лету назвать список городов и других мест "нежелательных для посещения" в силу происходящих там страстей: от Дерри до Хевена, через Оверлук и обратно. Действие некоторых романов и рассказов происходят в одной и той же местности (например, "Оно" или "Ловец Снов"), в других же просто может содержаться указатель на эти популярные места (например, дорожный знак «На Салимов Удел» упоминается в «Оно», «Кладбище домашних животных», «Ловец снов» и «Волки Кальи»).

  2. Можно попробовать зайти с дат (если уж мы идем по именованным сущностям), т.к. действительно интересно, могли ли события в разных книгах совпадать по времени. Однако извлечь полную дату из текста (день, месяц, год) будет тем еще испытанием.

  3. Повышая уровень сложности, можно взглянуть на совпадения во фразах/присказках/пословицах. Эта идея пришла ко мне, когда я пыталась объяснить связь "Салемова Удела" с другими книгами и натолкнулась на интересный факт, что в «Оно» главный герой повторяет для самоконцентрации ту же поговорку, что и Марк Петри в «Салемов Удел».

  4. Самое сложное: описание непосредственно событий. Читатели разных серий наверняка испытывали недюжее удовольствие, когда в упомянутой, казалось бы, вскользь истории распознавали отсылку на сюжет той или иной книги. У Кинга так же, вот только, как научить машину видеть такие неформализованные отсылки - очень интересный вопрос.

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

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

P.S. Имена ... самих книг

ведь это тоже имена!

Я не стала выносить это в отдельную часть, ведь названия романов - это тоже своего рода имена, да и к тому же никакой магии анализа в этом нет: Ctrl+F и никакого мошенничества. Эту идею я взяла из самих "Томминокеров", где Кинг, не стесняясь, дает ссылку на "Сияние", хоть и экранизированное: "Grab Bobbi's ax and make like Jack Nicholson in The Shining?".

Смотрим, что вышло:

Вышел неожиданный, но интересный граф! Из него видно, что сами романы упоминаются в других книгах чаще, чем их герои. Конечно, получившаяся паутинка не идеальна: название романа "Стрелок" и "кличка" Роланда из Темной башни будут идентичны (the Gunslinger), Misery может быть как названием романа, так и простым отчаянием с большой буквы и т.д.

"И что же делать?" - Только с упоением читать романы и проверять самостоятельно, ведь этот анализ всего лишь прелюдия к главному удовольствию: чтению старой доброй страшной истории на ночь.

"Если вам кажется, что я вас обманываю, значит, вы невнимательно слушали вечерние новости". Стивен Кинг

Tags: NLPСтивен Кингпасхалкимультивселеннаяpythonner
Hubs: Entertaining tasks Python Algorithms Reading room Lifehacks for geeks
Total votes 24: ↑22 and ↓2 +20
Comments 8
Comments Comments 8

Popular right now