Синтаксический анализ текстов с помощью SyntaxNet

МЕНЮ


Новости ИИ
Поиск

ТЕМЫ


Внедрение ИИНовости ИИРобототехника, БПЛАТрансгуманизмЛингвистика, рбработка текстаБиология, теория эволюцииВиртулаьная и дополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информации

АРХИВ


Июнь 2017
Май 2017
Апрель 2017
Март 2017
Февраль 2017
Январь 2017
Декабрь 2016
Ноябрь 2016
Октябрь 2016
Сентябрь 2016
Август 2016
Июль 2016
Июнь 2016
Май 2016
Апрель 2016
Март 2016
Февраль 2016
Январь 2016
0000

RSS


RSS новости
птичий грипп

Новостная лента форума ailab.ru

2016-12-14 19:10

Для одной из задач мне понадобился синтаксический анализатор русскоязычных текстов. Что это такое. Например, у нас есть предложение «Мама мыла раму». Нам нужно получить связи слов в этом предложении в виде дерева:

image
Из этого дерева понятно, что связаны слова «мама» и «мыла», а также «мыла» и «раму», а слова «мама» и «раму» напрямую не связаны.

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

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

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

Есть и другие варианты, среди которых SyntaxNet. На Хабре я не нашел ничего про SyntaxNet, поэтому восполняю пробел.

Что такое SyntaxNet

По сути SyntaxNet — это основанная на TensorFlow библиотека определения синтаксических связей, использует нейронную сеть. В настоящий момент поддерживается 40 языков, в том числе и Русский.

Установка SyntaxNet

Весь процесс установки описан в официальной документации. Дублировать инструкцию здесь смысла не вижу, отмечу лишь один момент. Для сборки используется Bazel. Я попробовал собрать проект с его помощью у себя на виртуалке с Ubuntu 16.04 x64 Server с выделенными 4-мя процессорами и 8 ГБ оперативной памяти и это не увенчалось успехом — вся память съедается и задействуется своп. После нескольких часов я прервал процесс установки, и повторил всё, выделив уже 12 ГБ оперативной памяти. В этом случае все прошло гладко, в пике задействовался своп только на 20 МБ.

Возможно есть какие-то настройки, с помощью которых можно поставить систему в окружении с меньшим объемом оперативной памяти. Возможно сборка выполняется в нескольких параллельных процессах и стоило выделять виртуальной машине только 1 процессор. Если вы знаете, напишите в комментариях.

После завершения установки я оставил для этой виртуальной машины 1ГБ памяти и этого хватает с запасом для того, чтобы успешно парсить тексты.

В качестве размеченного корпуса я выбрал Russian-SynTagRus, он более объемный по сравнению с Russian и с ним точность должна получаться выше.

Использование SyntaxNet

Чтобы распарсить предложение, переходим в каталог tensorflow/models/syntaxnet и запускаем (путь к модели — абсолютный):

echo "Мама мыла раму" | syntaxnet/models/parsey_universal/parse.sh /home/tensor/tensorflow/Russian-SynTagRus > result.txt

В файле result.txt получаем примерно такой вывод, я заменил данные в 6-й колонке на "_", чтобы тут не переносились строки, иначе неудобно читать:

cat result.txt 1	Мама	_	NOUN	_	_	2	nsubj	__ 2	мыла	_	VERB	_	_	0	ROOT	_	_ 3	раму	_	NOUN	_	_	2	dobj	__

Данные представлены в формате CoNLL-U. Тут наибольший интерес представляют следующие колонки:

1. порядковый номер слова в предложении,
2. слово (или символ пунктуации),
4. часть речи, тут можно посмотреть описание частей речи,
7. номер родительского слова (или 0 для корня).

То есть мы имеем дерево, в которм слово «мыла» — корень, потому что оно находится в той строке, где колонка номер 7 содержит «0». У слова «мыла» порядковый номер 2. Ищем все строки, в которых колонка номер 7 содержит «2», это дочерние элементы к слову «мыла». Итого, получаем:

image
Кстати, если разобраться подробнее, то дерево не всегда удачно представляется все зависимости. В ABBYY Compreno, например, в дерево добавляют дополнительные связи, которые указывают на связь элементов, находящихся в разных ветках дерева. В нашем случае таких связей мы не получим.

Интерфейс

Если вам критична скорость парсинга текстов, то можно попробовать разобраться с TensorFlow Serving, с помощью него можно загружать модель в память один раз и далее получать ответы существенно быстрее. К сожалению, наладить работу через TensorFlow Serving оказалось не так просто, как казалось изначально. Но в целом это возможно. Вот пример, как это удалось сделать для корейского языка. Если у вас есть пример как это сделать для русского языка, напишите в комментариях.

В моем случае скорость парсинга не была сильно критичной, поэтому я не стал добивать тему с TensorFlow Serving и написал простое API для работы с SyntaxNet, чтобы можно было держать SyntaxNet на отдельном сервере и обращаться к нему по HTTP.

В этом репозитории есть и веб интерфейс, который удобно использовать для отладки, чтобы посмотреть как именно распарсилось предложение.

image image Чтобы получить результат в JSON, делаем такой запрос:

curl -d text="Мама мыла раму." -d format="JSON" http://<host where syntax-tree installed>

Получаем такой ответ:

[{   number: "2",   text: "мыла",   pos: "VERB",   children: [     {       number: "1",       text: "мама",       pos: "NOUN",       children: [ ]     },     {       number: "3",       text: "раму",       pos: "NOUN",       children: [ ]     }   ] }]

Уточню один момент. Bazel интересным образом устанавливает пакеты, так, что часть бинарников хранится в ~/.cache/bazel. Чтобы получить доступ к их исполнению из PHP, я на локальной машине добавил права на этот каталог для пользователя веб сервера. Наверное той же цели можно добиться более культурным путем, но для экспериментов этого достаточно.

Что еще

Еще есть MaltParser, о котором я упомянул вначале. Позже я обнаружил, что тут можно скачать размеченный корпус SynTagRus и даже успешно обучил на нем свежую версию MaltParser, но не нашел пока времени довести дело до конца и собрать MaltParser целиком, чтобы получать результат парсинга. Эта система немного иначе строит дерево и мне для своей задачи интересно сравнить результаты, получаемые с помощью SyntaxNet и MaltParser. Возможно в следующий раз удастся написать об этом.

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

Источник: habrahabr.ru