Изучаем граф-ориентированную СУБД Neo4j на примере лексической базы Wordnet
СУБД Neo4j — это NoSQL база данных, ориентированная на хранение графов. Изюминкой продукта является декларативный язык запросов Cypher.
Cypher позаимствовал ключевые слова типа WHERE, ORDER BY из SQL; синтаксис из таких разных языков как Python, Haskell, SPARQL; и в результате появился язык, позволяющий делать запросы к графам в визуальной форме наподобие ASCII art. Например, заголовок данной статьи я бы представил в виде графа (Neo4j) — [изучаем] -> (Wordnet). И это почти готовый запрос к базе данных!
Для изучения граф-ориентированной базы данных нужен какой-нибудь граф. Это может быть социальная сеть, дамп википедии или схема железных дорог. Мы пойдём простым путём и воспользуемся огромным общедоступным графом лексической базы Wordnet. Лингвисты из Принстона проделали гигантскую работу по систематизации словарного запаса английского языка, а энтузиасты перевели базу данных на многие языки, включая русский. Например, в этой базе свыше 80 тысяч существительных, связанных между собой лексическими отношениями, такими как «синоним», «часть большего», «материал для» и т. п. Эта база является естественным графом, и мы её импортируем в Neo4j.
Установка Neo4j
Процесс установки для разных ОС описан на сайте. Всё описываемое здесь ПО платформенно-независимое, но для определенности все инструкции будут для Debian/Ubuntu.
1. Добавить репозиторий 2. Установить Neo4j (community edition)Эта команда установит ПО в вашу домашнюю директорию и запустит сервис, который будет работать от имени пользователя neo4j.
3. Разрешить удалённый доступЕсли вы установили Neo4j на свой компьютер, этот шаг пропустите. Если же требуется доступ к серверу с других компьютеров в локальной сети, отредактируйте файл /var/lib/neo4j/conf/neo4j-server.properties
Для доступа с любого компьютера локальной сети установите параметры:
По умолчанию используется порт 7474, изменить порт можно, добавив строку в тот же файл:
Обратите внимание, что мы не настроили безопасность СУБД! Более подробно читайте инструкцию.
Проверить установку можно, набрав в браузере адрес и порт сервера. Neo4j реализует роскошную графическую консоль через браузер. Через этот же порт идут REST-запросы к базе от клиентского программного обеспечения, которое мы установим на следующем шаге.
Установка клиента (Python)
Для того, чтобы импортировать базу Wordnet в Neo4j, воспользуемся скриптом на Питоне.
1. Сначала нужно установить библиотеку py2neo 2. Скачайте с гитхаба мой скриптСкрипт вряд-ли претендует на промышленное качество кода, но если вы захотите поэкспериментировать с Neo4j из Питона, то просмотрите код, это поможет вам быстрее начать программировать.
Получение лексической базы данных Wordnet
На странице Download проекта Wordnet предлагается скачать базу вместе с программным обеспечением для её просмотра. Но мы-то хотим использовать для просмотра Neo4j! Поэтому достаточно скачать только файлы с данными:
- Самая свежая версия англоязычной базы Wordnet доступна по ссылке
- Предыдущие версии (например для совместимости с ImageNet)
- Я предлагаю скачать русскую версию с сайта wordnet.ru
Импорт данных в Neo4j
Лексические данные в Wordnet лежат в файлах по частям речи. Например, существительные находятся в файле data.noun; глаголы — в data.verb; а с другими частями речи я и не пробовал.
1. Импорт существительныхДля импорта существительных перейдите в директорию, куда поместили мои скрипты (мы ее назвали просто habrawordnet2neo4j) и выполните команду в консоли:
Давайте разберём параметры поподробнее.
2. Импорт глаголовДля импорта глаголов выполните команду в консоли:
Импортировать глаголы необязательно, хотя некоторые из них связаны с существительными, и это интересно поизучать.
3. Убедитесь, что данные импортированыДля этого откройте в браузере консоль Neo4j (введите адрес и порт сервера СУБД) и введите следующий запрос:
Если получили в экране изображение графа, то все прошло успешно.
Выполняем простые запросы
Все дальнейшие действия будем выполнять в браузере, в консоли Neo4j. Я буду считать, что в качестве меток узлов вы использовали Ruswordnet, а в качестве типа рёбер Pointer (как указано в предыдущем разделе). И что вы импортировали именно русскую базу Wordnet целиком.
1. Hello WorldКак указано на сайте русской базы Wordnet, переведены около половины смысловых единиц, содержащих самые общеупотребимые слова. Поэтому попробуем найти в базе первое, что пришло в голову:
Выполните запрос, убедитесь, что это понятие найдено, значит, по мнению российских лингвистов, оно входит в число самых общеупотребимых. Давайте разберём этот простой запрос.
Ключевое слово MATCH означает примерно то же самое, что SELECT в SQL. Грубо говоря, «найти подходящие к шаблону элементы графа».
Круглыми скобками обозначаются узлы графа. Шаблон (n:Ruswordnet) обозначал бы, что мы хотим найти все узлы с меткой «Ruswordnet». Здесь n — идентификатор, можно сказать «переменная».
Узлы графа (и рёбра тоже) можно снабжать произвольными атрибутами. Чтобы найти конкретный узел, мы задали в запросе условие на атрибуты в формате, похожем на JSON: . Таким образом, фраза
означает, что из всего графа будут выбраны все узлы с меткой Ruswordnet и атрибутом name равным указанному там понятию.
Ключевое слово RETURN говорит нам, какие переменные нас интересуют. В данном случае мы хотели просто увидеть узел (узлы), соответствующие заданным условиям, поэтому пишем RETURN n. Важно понимать, что n — это коллекция узлов, удовлетворяющих запросу. Чтобы убедиться в этом, просто замените понятие в запросе:
Если вы импортировали базу Wordnet целиком, вы увидите шесть узлов понятий «лев». Давайте разберёмся, почему.
2. Переменные = коллекцииВыполним такой запрос:
Здесь мы задали уже более сложный шаблон для поиска. Мы хотим найти все узлы (n), соответствующие понятию «лев», а также все узлы (m), связанные с львами. Связь, т. е. ребро графа обозначается двумя дефисами. Можно в явном виде указывать интересующее нас направление символом --> (это я и называл ASCII art).
Если у вас не отображаются имена смысловых единиц, нажмите на кнопку Ruswordnet(23) в левом верхнем углу графа, и в строке состояния внизу консоли выберите «name» в поле Caption. Так будет нагляднее.
Теперь мы поняли, что лев это, оказывается не только болгарская валюта (bulgarian_money), копейкой для которой является стотинка, но и большая кошка, и созвездие, астрологический знак, и что-то, связанное с гордостью.
3. Подключаем рёбраКвадратными скобками обозначаются спецификации рёбер. В этом запросе мы хотим найти рёбра типа Pointer, атрибут которых pointer_symbol равен «@» т. е. символу обобщения. Кстати, противоположный обобщению символ уточнения «
Теперь понятно, что обобщение для льва это кот, а также человек. Конечно, речь идет о разных смысловых единицах: лев (кот) это один узел графа, а лев (человек) — другой узел, соответствующий знаку зодиака. Лев (известность) — это результат плохого перевода на русский; имеется в виду лев (celebrity), т. е. знаменитость, светский лев.
Давайте разберемся, что такое part holonym:
А, теперь понятно: лев входит в зодиак в качестве составной части, значит зодиак является part holonym для льва.
Из таблицы видно, что Wordnet содержит много интересных отношений, например, из каких веществ что сделано. К сожалению, нет информации, что лев сделан из мяса, поэтому поставим вопрос по другому: найти такие узлы графа, которые связаны отношением «из какого вещества сделано».
В этом запросе мы не накладываем никаких условий на узлы (n) и (m). Мы только хотим, чтобы их связывали рёбра с атрибутом «#s». Обратите внимание, появилось ключевое слово LIMIT, знакомое нам из SQL. Если бы его здесь не было, сервер вернул бы нам очень много результатов, и плохо было бы нашему браузеру.
В результате запроса мы узнали, что сигареты состоят из марихуаны, а суп из воловьих хвостов — из воловьих хвостов.
4. Цепочки произвольной длиныВ детстве все играли в такую игру: превратить муху в слона. Для этого нужно было менять по одной букве в слове, пока слово МУХА не превратилось в слово СЛОН. Давайте узнаем в лексическом графе, связаны ли между собой ЛЕВ и ОВЦА.
Конструкция [p:Pointer*1..3] говорит, что требуется найти цепочку рёбер типа Pointer длиной от одного до трех, связывающую узел «лев» с узлом «овца».
Это отличается от классической детской игры, но тоже интересно: ОВЦА — ПРОСТАК — ЧЕЛОВЕК — ЛЕВ… это звучит гордо. Кстати, можно попытаться найти связь и между мухой и слоном, только немного увеличить предельную длину цепочки. Я использовал значение 6. Кстати, не пытайтесь сразу поставить 100 — процесс поиска скорее всего сорвется т. к. число вариантов для перебора путей в графе будет слишком велико. Итак, вот как связаны слон и муха лексически:
Думаю, на этом этапе вы многое поняли о базе данных Neo4j, и способны самостоятельно открыть много интересного в базе данных Wordnet, а может применить Neo4j в своих проектах. Мы применяем связку Neo4j c Wordnet в системе поиска по киноархивам. Если вы хотите заниматься исследованиями в области машинного обучения, приглашаю на стажировку или на постоянную работу в НИКФИ — научно-исследовательский кинофотоинститут.