Предыстория
Которую вы можете пропустить, но не станете, верно?
Дело было за последней прочитанной мной книгой Стивена Кинга - "Томминокеры". В очередной раз скользнув по "еще одному американскому имени не очень-то главного героя", я вдруг задумалась: "А что, если имя, которое я даже толком не прочитала, было важным? Что, если это имя персонажа другой уже прочитанной мной истории? Что, если из-за того что я, среднестатистический человек в пятницу вечером, не держу в голове целый город (или даже штат) имен всех персонажей, я упускаю детали мира дядюшки Кинга?" Стало немного-невыносимо больно за возможные утраченные пасхалки.
Не желая с этим мириться, я стала думать: "Как это можно исправить?". Гуглить каждое имя в книге - опасно, в первую очередь для пока еще свободного вечера пятницы. Более того, можно нарваться на спойлеры. Посмотреть уже созданные кем-то "карты" связей романов - можно, но эти карты создаются людьми, такими же, как мы с вами, а значит а) что-то могло быть упущено, б) снова могут быть спойлеры. Перечитывать книги (также, как я пересматривала сериал "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.
Как сделали:
-
Отдали текст романа модели, чтобы распознать все возможные сущности.
-
Извлекли только те, что имеют тип "PERSON".
-
Убрали принадлежность в виде " 's" (можно назвать примитивным стеммингом)
-
Также убрали Mrs, Mr, Ms, но решили не убирать Dr.
-
Оставили только имена состоящие не менее, чем из двух слов (например, Бобби Андерсон или Джим Гарденер), т.к. по отдельной извлеченной фамилии или имени точно определить персонажа не представляется возможным: а вдруг брат/сестра/тезка.
-
Интереса ради: посчитали частоту упоминаний каждого имени.
Что получилось:
Оказалось, что главный герой "Томминокеров" все-таки Бобби Андерсон, а Джим даже не на втором месте. Прости, Джим.
Однако, чтобы результаты были совсем честными, при подсчете стоило учитывать отдельно упоминаемые фамилии и имена, которые мы выкинули, и объединять их разные формы в одну (Джим Гарденер, Джеймс Гарденер и т.д.). Это все можно сделать, например, разбив на имя и фамилию или использовав NEL алгоритмы (связывание сущностей), но для первоначальной идеи поиска пасхалок нам это не требовалось.
Все персонажи
и не только они!
Настал момент истины: повторим проделанное с "Томминокерами" для всех имеющихся романов и посмотрим, кто из "уважаемых" встречался в нескольких книгах и каких.
"И что получилось?" - 117 "человек", которые встречаются в 2 и более книгах. И если не знать американскую культуру 70-80-х (что вполне простительно), то можно строчка за строчкой просматривать имена и удивляться насколько хорошо мы с вами сработали. И даже такие попадания, как "Mike Mike" (простое дублирование имени) или "Roland Eddie" (сочетание имен героев) не омрачают наше счастье. Но длится оно все-таки недолго:
-
На 10-й строчке вы встречаете Silva Compass - и нет, это не кличка очередного ребенка, а компания производящая... компасы.
-
На 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) как раз то, к чему мы все это время шли: неочевидные отсылки, которые можно упустить, если не выписывать себе все имена.
Так, можно упустить, что один из главных героев книги "Салемов удел", отец Каллагэн - второстепенный герой цикла «Темная Башня» (части: "Волки Кальи", "Песнь Сюзанны" и "Темная башня"). А "Черный дом" тесно связан с "Темной башней" другим персонажем, но упоминать и раскрывать детали я не буду во избежание спойлеров.
Что дальше
и как обнаружить больше пасхалок?
-
Можно посмотреть на локации, т.к. любой фанат Кинга может с лету назвать список городов и других мест "нежелательных для посещения" в силу происходящих там страстей: от Дерри до Хевена, через Оверлук и обратно. Действие некоторых романов и рассказов происходят в одной и той же местности (например, "Оно" или "Ловец Снов"), в других же просто может содержаться указатель на эти популярные места (например, дорожный знак «На Салимов Удел» упоминается в «Оно», «Кладбище домашних животных», «Ловец снов» и «Волки Кальи»).
-
Можно попробовать зайти с дат (если уж мы идем по именованным сущностям), т.к. действительно интересно, могли ли события в разных книгах совпадать по времени. Однако извлечь полную дату из текста (день, месяц, год) будет тем еще испытанием.
-
Повышая уровень сложности, можно взглянуть на совпадения во фразах/присказках/пословицах. Эта идея пришла ко мне, когда я пыталась объяснить связь "Салемова Удела" с другими книгами и натолкнулась на интересный факт, что в «Оно» главный герой повторяет для самоконцентрации ту же поговорку, что и Марк Петри в «Салемов Удел».
-
Самое сложное: описание непосредственно событий. Читатели разных серий наверняка испытывали недюжее удовольствие, когда в упомянутой, казалось бы, вскользь истории распознавали отсылку на сюжет той или иной книги. У Кинга так же, вот только, как научить машину видеть такие неформализованные отсылки - очень интересный вопрос.
Признаюсь, что собираюсь двигаться дальше по описанному плану: искать географические, временные и другие отсылки, не зависимо от того, зайдет эта статья или нет. Но скорость моего "домашнего анализа", а тем более публикаций скорее всего будет коррелировать с чьим-то кроме моего интереса. Если у вас есть идеи, дополнения, комментарии, как и что можно сделать лучше/быстрее/просто сделать - делитесь, будет интересно посмотреть на это вместе коллективными глазами и разумом.
Для тех, кому интересна реализация (главное, верить в себя), я залила весь код в специальный репозиторий.
P.S. Имена ... самих книг
ведь это тоже имена!
Я не стала выносить это в отдельную часть, ведь названия романов - это тоже своего рода имена, да и к тому же никакой магии анализа в этом нет: Ctrl+F и никакого мошенничества. Эту идею я взяла из самих "Томминокеров", где Кинг, не стесняясь, дает ссылку на "Сияние", хоть и экранизированное: "Grab Bobbi's ax and make like Jack Nicholson in The Shining?".
Смотрим, что вышло:
Вышел неожиданный, но интересный граф! Из него видно, что сами романы упоминаются в других книгах чаще, чем их герои. Конечно, получившаяся паутинка не идеальна: название романа "Стрелок" и "кличка" Роланда из Темной башни будут идентичны (the Gunslinger), Misery может быть как названием романа, так и простым отчаянием с большой буквы и т.д.
"И что же делать?" - Только с упоением читать романы и проверять самостоятельно, ведь этот анализ всего лишь прелюдия к главному удовольствию: чтению старой доброй страшной истории на ночь.
"Если вам кажется, что я вас обманываю, значит, вы невнимательно слушали вечерние новости". Стивен Кинг
Автор: Vladacry