Семантический разбор с NLTK

Я пытаюсь использовать NLTK для семантического разбора голосовых команд навигации, таких как "поехать в Сан-Франциско", "указать мне дорогу до главной улицы 123" и т. Д.

Это можно сделать с помощью довольно простой грамматики CFG, такой как

S -> COMMAND LOCATION
COMMAND -> "go to" | "give me directions to" | ...
LOCATION -> CITY | STREET | ...

Проблема заключается в том, что это включает неатомарные (более одного слова) литералы, такие как "go to", для которых NLTK, похоже, не настроен (поправьте меня, если я ошибаюсь). Задача синтаксического анализа имеет тегирование как предварительное условие, и все тегеры, кажется, всегда тегируют отдельные слова. Итак, мои варианты выглядят так:

a) Определите пользовательский тегер, который может назначать несинтаксические теги для последовательностей слов, а не для отдельных слов (например, "go to": "COMMAND"). б) Используйте функции для расширения грамматики, например, что-то вроде:

COMMAND -> VB[sem='go'] P[sem='to'] | ...

c) Используйте чанкер для извлечения подструктур, таких как COMMAND, затем примените анализатор к результату. Разрешает ли NLTK каскадирование chunker->parser?

Некоторые из этих вариантов кажутся запутанными (хаки). Есть ли хороший способ?

3 ответа

Кажется, вы хотите определить императивы.

Этот ответ изучил этот вопрос и содержит решение, аналогичное вашему варианту (а), но немного отличающееся, поскольку оно позволяет тэггеру выполнять большую часть работы. (б) на самом деле кажется немного хакерским... но вы создаете довольно нестандартное приложение, чтобы оно могло работать! Я бы сделал (с) наоборот - разбор и затем разбивку на основе CFG в (а).

Однако в целом, как объясняется в другом ответе, пока еще нет идеального способа сделать это.

Вы также можете посмотреть на pattern.en. Их

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

Я бы посоветовал вам использовать «сопоставление на основе правил», доступное в spacy , которое предоставляет такие параметры, как сопоставление токенов, сопоставление фраз, линейка сущностей. Я использовал Token Matcher, указав шаблон (перейти + в + место), и он работал очень хорошо.

      token_pattern = [{"LEMMA": "go"}, {"POS": "ADP"}, {"POS": "PROPN"}]

Этот образец найдет «поехать в Нью-Йорк» или «поехать в Нью-Йорк», или «поехать с Мэри» и т. Д.

Кроме того, если вы пытаетесь извлечь только существительные, как в вашем примере «Сан-Франциско», «123 Main Street», может помочь NER (распознавание именованных сущностей).

Для связанной задачи (репликация семантического анализатора коммерческих транзакций, я ранее делал что-то вроде (c). Самое большое преимущество рабочих процессов каскадного синтаксического анализатора заключается в том, что грамматики могут оставаться относительно простыми (и быстрыми), потому что им не нужно Я думаю, это наименее хакерский подход, потому что это действительно действенная стратегия для разработки рабочих процессов парсера.

Что касается (а), для настраиваемого теггера потребуются какие-то обучающие данные. Если вы можете создать или настроить его, это было бы наиболее естественным решением. Для создания аннотаций диапазона с помощью теггера рассмотрите возможность использования схемы BIO (IOBES), которая обычно используется для аннотаций именованных сущностей, т. Е. You/B-COMMAND shall/I-COMMAND not/I-COMMAND pass/E-COMMAND !/O.

Другие вопросы по тегам