NLP в Neo4j с Cypher: простой пример

Автор Категория ,
NLP в Neo4j с Cypher: простой пример

Недавно мы писали про рекомендательную систему американской медиа-компании Meredith Corporation на основе графовой СУБД Neo4j и алгоритма непересекающихся множеств (Union-Find). Продолжая эту тему в рамках нашего нового курса по графовой аналитике больших данных в бизнес-приложениях, сегодня рассмотрим, как построить простой рекомендательный движок с помощью выражений и операторов языка запросов Cypher в Neo4j.

Обработка естественного языка с помощью графового анализа

Neo4j, как и другие графовые СУБД, отлично подходят для движков рекомендательных систем. Они позволяют исследовать большой контекст, потенциально включающий различные источники данных. Мощная модель хранения данных идеальна для приложений, где нужно анализировать непосредственное окружение каждого узла. По умолчанию Neo4j предлагает мощные возможности запросов для структурированных данных с помощью методов NLP, которые могут извлечь скрытую структуру в документах. Эта структура может быть как простой в виде узлов графа, представляющих токены в предложении, так и сложной, когда узлы, представляющие сущности, извлечены с использованием алгоритма распознавания именованных сущностей.

Рассмотрим, как реализовать простой механизм рекомендаций непосредственно в Neo4j, используя только ее язык запросов Cypher. Подход основан на базовых методах NLP и простых условных вероятностях для поиска наиболее подходящего элемента. Реализация может быть выполнена в нескольких строках код в одном запросе, который запускается в режиме реального времени, когда пользователь взаимодействует с приложением. В качестве примера рассмотрим приложение для планирования личного времени, которое позволяет пользователям создавать планы на день, состоящие из задач и событий. Основным свойством задач и событий является их заголовок в виде короткой строки. Организовать хранение задач и событий в виде связанных объектом можно, распределив их по областям жизни и проектам.

Область — это более крупная и постоянная тема, такая как работа, отдых, спорт, семья, быт и пр. Проекты привязаны ко времени, например, митап по Apache Spark или курс по анализу данных. Сами проекты могут быть назначены области, например, вебинар по Kafka относится к работе. Таким образом, постановка решаемой проблемы сводится к формированию рекомендаций по областям, когда пользователь начинает вносить задачу в свое расписание. Например, «оплатить детский сад» может относиться к бытовым задачам (область «быт»), а «подготовить презентацию к новому курсу» – к рабочим задачам (область «работа»). В Data Science подобные проблемы анализа и классификации слов относятся к обработке естественного языка (NLP, Natural Language Processing). Как это реализовать средствами Neo4j, мы рассмотрим далее.

Токенизация и стемминг: NLP в Neo4j с Cypher

Основным свойством, которое маркирует принадлежность задачи области, является свойство заголовка (title). Чтобы проанализировать этот текст, необходимо обработать каждую входную строку, когда пользователь создает новые задачи и события, и сохранить их. А затем представить эти участки текста (токены) в виде отношений на графе, чтобы найти наиболее вероятное назначение области для набора слов, которые вводит пользователь. По сути, требуется найти область, в которой условная вероятность P(A|T) наибольшая, т.е. по заданному токену T следует найти область A, которая с наибольшей вероятностью P содержит это слово.

Задачи и события находятся между областями и токеном и формируют их назначения. По мере создания новых задач и событий, состоящих из токенов, и их связывания с областями, отношений будет все больше. Именно эти косвенные отношения требуется проанализировать, чтобы найти подходящие рекомендации. Имея граф, можно построить матрицу назначения между областями и токеном, а также рассчитать условную вероятность для P(A|T) = P(A & T) / P(T).

При этом каждая задача и событие могут состоять из нескольких токенов. Например, нужно найти область для задачи «Подготовить вебинар по Neo4j», т.е. определить условную вероятность P (A | «Neo4j» и «вебинар»). Это аналогично вычислению вероятностей P (A и «Neo4j» и «вебинар») и P («Neo4j» и «вебинар»). Так рекомендательный Cypher-запрос в Neo4j прост, как и уточнение количества заданий в каждой области:

MATCH (token:AnnotatedToken)<-[:HAS_TAG]-(i:Information)
  WHERE token.lemma IN $tags
WITH count(i) as total_tf
MATCH (token:AnnotatedToken)<-[:HAS_TAG]-(i:Information)
  WHERE token.lemma IN $tags
OPTIONAL MATCH (i)<-[:IS_ASSIGNED_TO*0..2]-()-[:IS_CONTAINED_IN*0..1]->()-[:RELATES_TO*0..1]->()-[:BELONGS_TO]->(area:Area)
WITH area, count(i) AS intersection, total_tf
RETURN area, intersection * 1.0 / total_tf AS p
ORDER BY p DESC;

Хотя этот пример ограничен только одним пользователем, он отлично иллюстрирует простой статистический или вероятностный подход к рекомендациям. Его очень легко и просто реализовать в простом Cypher, и он работает непосредственно в бэкэнде Neo4j. Нет накладных расходов на добавление внешних систем, нет циклов обучения или моделей, которыми нужно управлять. Дополнительным плюсом является низкая стоимость накладных расходов на поддержку кода. На практике можно  запрашивать результаты в режиме реального времени без необходимости какой-либо предварительной подготовки результатов. Хотя рассмотренный подход намного проще глубоких нейросетей с word2vec-эмбедингами, он дает аналогичные по качеству результаты.

Однако, основным недостатком этого подхода является то, что он ограничен простым набором фич. При внедрении дополнительных фич в предлагаемые рекомендации их придется явно моделировать их в Cypher-запросе, что повысит его сложность в понимании и обслуживании. Также увеличится трудоемкость самого процесса разработки, включая поиск правильного способа объединения нескольких фич в приемлемый результат.

Тем не менее, язык запросов Cypher в Neo4j позволяет создавать мощные рекомендации прямо в графовой базе данных, избавляя от большого объема работы по настройке, обучению и мониторингу дополнительных систем. Чтобы снять ограничения этого намеренно упрощенного решения, можно воспользоваться более сложными алгоритмами, в т.ч. теми, что есть в библиотеке Graph Data Science в Neo4j. Как NLP-алгоритмы на графах могут еще пригодиться на практике, читайте в нашей новой статье про выявление рецидивистов, незаконно ввозящих контрафактные товары с помощью Neo4j. 

Наконец, отметим, что подобную идею можно реализовать и с помощью других технологий, например, воспользовавшись средствами графовой аналитики в Apache Spark для обработки данных из реляционных и NoSQL-источников данных.

Больше реальных примеров применения Neo4j и других инструментов графовой аналитики больших данных для практических бизнес-задач вы узнаете на специализированных курсах в нашем лицензированном учебном центре обучения и повышения квалификации для разработчиков, менеджеров, архитекторов, инженеров, администраторов, Data Scientist’ов и аналитиков больших данных в Москве:

Источники

  1. https://towardsdatascience.com/building-a-simple-recommendation-engine-in-neo4j-45770d8747eb
  2. https://neo4j.com/developer/graph-data-science/nlp/