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

Однако часто забывают, что вам нужны правильные данные для обучения вашей модели, и вам нужно их огромное количество. На самом деле правильным термином было бы «Информация», а не «Данные», но слово «Данные» в наши дни стало очень модным, поэтому я вынужден использовать его.

Что я имею в виду под «правильными данными»?

На этом этапе я сосредоточусь на языковой области (НЛП).

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

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

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

Реальность: Хорошо, вы дали кучу текста, что теперь делать? Какую модель следует изучить? Каковы результаты? Вы не можете просто дать что-то и ожидать, что ваша проблема будет решена волшебным образом.

Итак, если у вас есть предложение вроде:

В 2005 году Fake Co. объявили о банкротстве после того, как были обнаружены в схеме отмывания денег.

и вы хотите найти, что Fake Co. = Company вам нужно аннотировать данные.

В 2005 году ‹company›Fake Co.‹/company› объявили о банкротстве после того, как были обнаружены в схеме отмывания денег.

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

В сообществе машинного обучения ходит шутка, что ML обычно означает Mмашинный Lзаработок, хотя на самом деле чаще всего это M. сильный>ежегодный Lтруд.

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

Как сделать больше машинного обучения и меньше ручного труда

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

Итак, первый трюк, весьма гениальный, выглядит так:

  • Возьмите небольшую часть ваших данных
  • Тщательно аннотируйте его
  • Обучите на нем свою модель
  • Запустите свою модель на части остальных данных
  • Вручную исправить неправильные аннотации
  • Промыть и повторить

Хитрость в том, что с каждой итерацией модель становится все лучше и лучше, поэтому требуется меньше исправлений.

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

Вторым трюком будет создание языковых правил, которые будут аннотировать исходный набор данных. Но где? Как?

Популярный способ запуска языковых правил

Проще говоря, есть огромный, зрелый проект под названием Apache UIMA. А поскольку написание кода на Java может быть не для всех, существует DSL для генерации этих правил, который называется Apache UIMA RUTA (Забавный факт: Рута — довольно популярное литовское женское имя. На этот счет ходит много шуток) .

Проблемы?

  • Он основан на Java. В наши дни не так легко интегрировать с остальной частью конвейера машинного обучения.
  • Это довольно медленно
  • На самом деле запустить его сложнее, чем просто включить в проект какой-нибудь пакет Maven. Нужна обширная конфигурация. Не могу обойтись без какого-либо эталонного кода.
  • Нам было очень трудно развернуть его на AWS Lambda.

Новый способ запуска языковых правил

Из-за разочарования и необходимости выполнять работу я инициировал проект с открытым исходным кодом под названием Рита (забавный факт, это еще одно популярное литовское женское имя. Сделал это как небольшой намек на РУТА)

В целом он использует немного измененный, но очень похожий на RUTA синтаксис.

INEXPENSIVE = {"secondary", "cheap", "inexpensive"}
{IN_LIST(INEXPENSIVE), WORD("cell")?, WORD("phone")}->MARK("CHEAP_PHONE")
{WORD("good"), WORD("value")->MARK("CHEAP_PHONE")

Что случилось:

  • {...} символизирует последовательность. Это может быть последовательность слов, например INEXPENSIVE, или последовательность правил, определяющая шаблон поиска.
  • Сначала мы объявляем список предметов, который представляет собой разные слова, используемые для обозначения недорогих товаров.
  • Во-вторых, глядя на данные, мы видим, что одни говорят «сотовый телефон», другие просто «телефон». Итак, мы говорим, что слово «ячейка» является необязательным (отсюда и знак ?)
  • И, наконец, мы говорим, что хотим добавить метку «CHEAP_PHONE», если такой шаблон обнаружен.

Второй сценарий намного проще — если мы видим «хорошее соотношение цены и качества», мы предполагаем, что речь идет о дешевом телефоне.

Чем это лучше регулярного выражения?

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

Второй момент немного более нюансирован. На данный момент существует два механизма обработки правил — один на основе регулярных выражений (без дополнительных зависимостей) и один на основе spaCy.

Этот автономный движок на основе регулярных выражений должен быть быстрым и легким, в то время как spaCy значительно медленнее (см. результаты тестов здесь: LastResults.md), но он предоставляет все языковые утилиты под своим поясом.

Например, вы можете указать LEMMA("be") и слова: is, was, been, to be, be будут соответствовать одному правилу. Кроме того, вы можете использовать вещь под названием NER (Распознавание именованных сущностей), поэтому вы можете сказать ENTITY("PERSON") или ENTITY("ORGANIZATION") и автоматически сопоставлять эти случаи без создания сложного шаблона регулярного выражения. Вы получаете чрезвычайно мощные сопоставители и, таким образом, можете создавать сложные шаблоны.

Вывод

По моему собственному опыту, построение моделей на основе правил — довольно хрупкий и трудоемкий процесс. Заниматься глубоким обучением и всеми другими причудливыми вещами — это круто, но в основном это черный ящик, и вам нужна либо армия аннотаторов, либо неразумное количество времени и концентрации, чтобы аннотировать требуемый набор данных.

Что я предлагаю — объединить эти два подхода в один, используя сильные качества каждой стороны.