Pull to refresh

Разбор естественного языка: грамматическая нотация

Reading time6 min
Views16K


Я уже довольно давно интересуюсь ИИ, особенно областью, связанной с пониманием машиной текстов, написанных на естественном языке. Как известно, классическая теория анализа текста разделяет этот процесс на три этапа:

  • Морфологический — анализ словоформ и их характеристик (число, падеж, и т.д.);
  • Синтаксический — выделение структуры предложения (отношения между словами);
  • Семантический — выделение смысла исходя из «модели мира»;

Первый этап в целом решён. Мы имеем подробные морфологические словари, покрывающие львиную долю слов, встречающихся в большинстве текстов. Кроме того, для распространённых языков существуют правила, позволяющие с достаточной точностью классифицировать неизвестные словоформы.

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

Из-за отсутствия у меня глубоких знаний в области нейронных сетей я решил следовать более проторенной тропой, а именно разработать BNF-подобную грамматическую нотацию и реализовать анализатор, использующий грамматические правила, описанные с её помощью. С этой точки зрения при разработке практически полезного анализатора основная работа заключается именно в построении достаточной системы правил (что у меня далеко до завершения). В следующем посте я опишу устройство реализованного анализатора, а пока хочу сфокусироваться на разработанной грамматической нотации.

Основы грамматической нотации


Я решил начать свои изыскания, рассматривая конкретный текст. Я выбрал «Палату №6» — известную повесть А. С. Чехова, написанную им в 1892 году. Как оказалось, уже начиная с первого предложения я столкнулся с весьма существенными трудностями, связанными со сложностью чеховских предложений. Перед тем, как рассматривать конкретные примеры синтаксического разбора должен предупредить, что я не являюсь профессиональным лингвистом или филологом, и поэтому мой анализ может оказаться неверным с академической точки зрения. Моей целью будет выявить общую структуру предложения, а не подготовить разбор, соответствующий школьной программе.

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

Это простое предложение, состоящее из подлежащего (флигель), относящихся к нему определения (небольшой) и причастного оборота (окруженный целым лесом репейника, крапивы и дикой конопли), а также сказуемого (стоит) и относящегося к нему обстоятельства места (в больничном дворе).

Давайте разделим это предложение на две большие части:
  • Первую назовём «predicate_group». В неё войдёт сказуемое и относящееся к нему обстоятельство.
  • Вторую назовём «subject_group». В неё войдёт подлежащее и относящиеся к нему определение и причастный оборот.

Теперь мы уже можем набросать несколько правил грамматики, успешно разбирающей первое предложение:

sentence:
- "{predicate_group} {subject_group}."

predicate_group:
- "{adverbial_modifier} {predicate}"

subject_group:
- "{attribute} {subject}, {participial_phrase}"

Грамматика описана в формате YAML. Этот формат удобен для редактирования правил и используется в моём анализаторе. Определения нетерминалов начинаются с названия, завершающегося двоеточием. Далее следуют одно или несколько правил, соответствующих данному нетерминалу. Правило представляет собой последовательность терминалов и нетерминалов. Нетерминал внутри правила обозначается как "{имя-нетерминала}". К примеру, единственное правило нетерминала «sentence» состоит из последовательности: нетерминал «predical_group», терминал " ", нетерминал «subject_group» и терминал ".".

Наша грамматика кроме того, что не определяет многие используемые нетерминалы, ещё и не учитывает важнейшие синтаксические ограничения. Вот, к примеру, совершенно некорректное предложение, не противоречащее данной грамматике:

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

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

sentence:
- "{predicate_group number=@1 gender=@2} {subject_group number=@1 gender=@2}."

predicate_group:
- "{adverbial_modifier} {predicate !number !gender !tense}"

subject_group:
- "{attribute} {subject case=nomn !number=@1 !gender=@2}, {participial_phrase number=@1 gender=@2}"

В приведённой нотации некоторые нетерминалы имеют атрибуты. Атрибут может иметь непосредственно заданное значение, как, например, атрибут «case» (падеж) нетерминала «predicate_group» в правиле «sentence» должен быть «nomn» (nominative, именительный).

Название атрибута может начинаться с восклицательного знака. Значение такого атрибута экспортируется из соответствующего нетерминала во внешний нетерминал, правило которого мы рассматриваем. Например, «predicate_group» должен экспортировать атрибуты «number» (число), «gender» (род) и «tense» (время) для правила из «sentence», но их значения не могут быть определены на этом уровне, поэтому он импортирует их значения из нетерминала «predicate».

Иногда необходимо, чтобы атрибуты в разных нетерминалах правила имели одинаковые значения вне зависимости от самих этих значений (которые часто не могут быть определены на данном уровне). В этих случаях используется специальные значения, предваряемые символом "@". Например, в правиле «sentence» нетерминалы «predicate_group» и «subject_group» должны иметь одинаковое число и род. Кроме того, атрибут со специальным значением может ещё и экспортироваться (имя предваряется восклицательным знаком).

Нестрогость ограничения атрибутов


В русском языке форма глагола зависит от рода соответствующего ему существительного, будучи в прошедшем времени («кот ел», «кошка ела»), но не зависит, будучи в настоящем или будущем времени («кот ест», «кошка ест»). Мы могли бы описать этот закон, создавая под каждое время отдельное правило, однако проще воспользоваться нестрогостью ограничения атрибутов: ограничение на атрибут игнорируется в случае, когда этот атрибут не определён в одном из соответствующих нетерминалов.

Приведу пример, демонстрирующий это правило. Для разбора фраз типа «кот ел», «кошка ела», «кот ест», «кошка ест» будем использовать следующее правило:

- "{noun case=nomn number=@1 gender=@2} {verb number=@1 gender=@2}"

В случае настоящего времени глагольная форма («ест») не будет иметь атрибута рода, поэтому из-за нестрогости ограничения атрибутов ограничение по роду будет проигнорировано. Этот приём также поможет и с атрибутом числа: нам не нужно добавлять отдельное правило для множественного числа (род глагола не определён для множественного числа, поэтому соответсвующее ограничение будет проигнорировано). На практике такой подход позволяет существенно уменьшить размер и сложность грамматики.

Присвоение значений атрибутам


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

- "@{number=plur}{noun} и {noun}"

Данное правило устанавливает множественное число (plural) для перечисления двух существительных («слон и моська»). Присвоение значений атрибутов находится в самом начале правила, предваряется символом "@" и содержит перечисление атрибутов с соответствующими непосредственными значениями.

Лексические терминалы


Нетерминалы самого нижнего уровня могли бы определяться следующим образом:

predicate:
...
- "@{number=sing gender=femin tense=past}ела"
- "@{number=sing gender=masc tense=past}ел"
- "@{number=plur tense=past}ели"
...

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

predicate:
- "{pos=verb !number !gender !tense}"

Как видно, такая нотация похожа на присвоение значений атрибутам, только в отличие от последнего не начинается с символа "@" и может быть в любой части правила. Вышеприведённое правило соответствует лексическому терминалу (словоформе) у которого атрибут «pos» (part of speech, часть речи) имеет значение «verb» (глагол).
Tags:
Hubs:
+19
Comments13

Articles

Change theme settings