О

Эта статья представляет собой введение в библиотеку POTATO. POTATO — это независимая от языка среда XAI (объяснимый искусственный интеллект) для извлечения и оценки интерпретируемых функций графа для любой задачи классификации в обработке естественного языка (NLP).

Статья включает в себя:

  • Краткое введение в основанные на правилах методы классификации текста
  • Введение в определение шаблонов графов в POTATO
  • Автоматическое изучение шаблонов
  • Структура «человек в контуре» (HITL)

Введение

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

Интерпретируемые модели среди прочего обладают следующими чертами [1]:

  • Справедливостьбеспристрастные прогнозы.
  • Конфиденциальность — меньше утечки информации
  • Надежностьнебольшие изменения на входе не сильно влияют на результат
  • Доверие, возможность аудита — мы знаем, чем вызваны прогнозы.
  • Отладка: если в производственной среде возникает ошибка, мы можем изменить модель.

Недавние решения NLP, достигшие самых современных результатов в общедоступных тестах, основаны на моделях глубокого обучения (DL) с миллионами параметров (например, BERT [2]). Эти модели требуют больших объемов обучающих данных, и их решения трудно объяснить [3]. Кроме того, модели глубокого обучения создают риск непреднамеренной систематической ошибки в наборах данных [4]. Системы, основанные на правилах, могут предоставлять точные и прозрачные решения, но могут быть сложными и трудоемкими для создания и обслуживания. POTATO — это платформа быстрого прототипирования, поддерживающая создание классификаторов текста на основе правил. В POTATO вместо использования моделей машинного обучения для непосредственного изучения задачи мы вместо этого изучаем системы правил. При использовании этого метода конечная модель остается полностью прозрачной.

Системы на основе правил

Плюсы

  • Системы, основанные на правилах, интерпретируемы и объяснимы по своей структуре.
  • Популярны в «реальных» приложениях, и нет необходимости в крупных первоначальных вложениях (нет необходимости в графических процессорах).
  • Полностью настраиваемый и может быть отлажен

Минусы

  • Трудно поддерживать
  • Хуже производительность на бенчмарках (в бенчмарках преобладают методы глубокого обучения)
  • Нужна экспертиза домена
  • Отнимает много времени на поддержание и развитие

В POTATO мы пытаемся устранить некоторые недостатки моделей, основанных на правилах, путем объединения машинного обучения и систем правил: изучайте правила!

Чтобы продемонстрировать системы правил, мы будем использовать пример из набора данных Semeval 2010 Relation Extraction. Извлечение отношений (RE) — это задача извлечения семантических отношений между сущностями из текста. Обычно определяется между двумя объектами. Отношения имеют семантические категории (например, Назначение, Компонент, Кем используется, Кем основан и т. д.), и задача состоит в том, чтобы отнести отношение к правильной категории.

Мы будем использовать только метку Entity-Destination. Пример для класса:

  • Бриллиантовое кольцо(entity1)было брошено в сумку кондитера(entity2).

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

r”entity1 .* dropped into .* entity2"

Но использование только регулярных выражений — наивный метод, так как мы ничего не знаем о структуре текста (токены, грамматические категории и т. д.). Мы могли бы использовать более продвинутые пакеты Python, такие как SpaCy’s TokenMatcher или Holmes Extractor. С ними мы могли бы определить более сложное правило, учитывающее теги части речи (POS) (грамматическая категория слов):

pattern = [{‘POS’: ‘VERB’},
{‘LOWER’: ‘into’},
{‘TEXT’: {‘REGEX’: ‘.*’}},
{‘LOWER’: ‘entity2’}]

Но вместо того, чтобы писать правила для токенов текста, мы можем написать правила для графов, которые могли бы использовать базовую графовую структуру текстов. В POTATO мы используем пакет python networkx для представления графиков. С помощью networkx мы предоставляем унифицированный интерфейс для представления графов, и пользователи могут создавать шаблоны графов на произвольных графах. В настоящее время в POTATO поддерживаются три типа графов: AMR[5], UD(с использованием пакета stanza [6]) и 4lang [7]. ]. Пример шаблона можно увидеть на рисунке 1, а на рисунке 2 мы видим график 4lang примера, который мы определили выше (бриллиантовое кольцо было переброшено в сумка от кондитера) и нанесенный рисунок.

В отличие от простых шаблонов регулярных выражений, этот шаблон также будет соответствовать следующим примерам:

The man placed the entity1 into the entity2.
Industries have pushed entity1 into fragile marine entity2.
I am putting the entity1 into a MySQL entity2.
The entity1 were released into the entity2.

Использование и настройка

POTATO — это XAI-фреймворк, написанный на python и обеспечивающий:

  • единый сетевой интерфейс для нескольких графических библиотек (4lang, stanza, AMR)
  • пакет python для изучения и оценки интерпретируемых функций графа как правил
  • инфраструктура пользовательского интерфейса человек в цикле (HITL), встроенная в streamlit
  • REST-API для использования извлеченных функций для логического вывода в производственном режиме

Все наши компоненты имеют открытый исходный код под лицензией MIT и могут быть установлены с помощью pip.

Инструмент сильно зависит от репозитория tuw-nlp для построения графиков и сопоставления функций. Вы можете установить tuw-nlp с помощью pip:

pip install tuw-nlp

Затем следуйте инструкциям по установке пакета.

Затем установите POTATO из pip:

pip install xpotato

Первые импортные упаковки из картофеля:

from xpotato.dataset.dataset import Dataset
from xpotato.models.trainer import GraphTrainer

Мы продемонстрируем возможности POTATO на нескольких предложениях, выбранных вручную из набора данных Semeval [8].

Обратите внимание, что мы заменили два рассматриваемых объекта на XXX и YYY.

Затем следующим шагом является инициализация набора данных, а также предоставление кодировки метки. Затем разберите предложения на графики, для этого мы можем использовать метод parse_graphs() (также необходимо выбрать формат графика). В настоящее время мы предоставляем три типа графиков: ud, fourlang, amr. Также вы указываете язык, который хотите анализировать. В настоящее время мы поддерживаем английский (en) и немецкий (de).

Мы будем использовать пример из таблицы 1 (мы будем ссылаться на образцы с их идентификаторами, указанными в первом столбце). Примеры, инициализированные в python, можно выполнить с помощью следующего кода:

dataset = Dataset(sentences, label_vocab={"Other":0, "Entity-Destination(e1,e2)": 1})
dataset.set_graphs(dataset.parse_graphs(graph_format="fourlang"))

Проверьте набор данных:

df = dataset.to_dataframe()

Мы также можем проверить любой из проанализированных графов

from xpotato.models.utils import to_dot
from graphviz import Source
Source(to_dot(dataset.graphs[0]))

Написание правил с POTATO

Если набор данных подготовлен и графики проанализированы, мы можем написать правила для сопоставления меток. Мы можем писать правила либо вручную, либо извлекать их автоматически (POTATO также предоставляет интерфейс, который делает и то, и другое).

Простейшим правилом будет просто узел в графе (в данном случае into):

# The syntax of the rules
# List[List[rules that we want to match]
# List[rules that shouldn't be in the matched graphs]
# Label of the rule
rule_to_match = [[["(u_1 / into)"], [], "Entity-Destination(e1,e2)"]]

Запустите средство сопоставления правил:

from xpotato.graph_extractor.extract import FeatureEvaluator
evaluator = FeatureEvaluator()

Сопоставьте правила в наборе данных:

# The function will return a dataframe with the matched instances:
evaluator.match_features(df, rule_to_match)

Функция вернет кадр данных с совпавшими примерами. Это правило будет соответствовать любому предложению, в котором есть узел в. В нашем случае мы сопоставили бы примеры с номерами 0, 1, 2, 3, 4, 5, 6, 9, 14 из таблицы 1 (например, Ученые налили XXX в пинту YYY.)

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

Например. строка (u_1 / into :1 (u_3 / pour)) будет описывать граф с двумя узлами ("into" и "pour" ) и одно направленное ребро с меткой «1» между ними. Описание подграфа строкой (u_1 / into :1 (u_2 / pour) :2 (u_3 / YYY)) вернет только три примера вместо 9, когда у нас был только один узел в качестве особенность.

#match a simple graph feature
evaluator.match_features(df, [[[“(u_1 / into :1 (u_2 / pour) :2 (u_3 / YYY))”], [], “Entity-Destination(e1,e2)”]])

Эта функция будет соответствовать примерам 0, 1, 9.

Мы также можем добавить отрицательные функции, которые мы не хотим сопоставлять (это не будет соответствовать первой строке, где присутствует «pour»):

# match a simple graph feature with a negated feature. 
#The negated features go into the second parameter.
evaluator.match_features(df, [[[“(u_1 / into :2 (u_3 / YYY))”], [“(u_2 / pour)”], “Entity-Destination(e1,e2)”]])

Соответствие примерам 2, 3, 5, 6.

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

# regex can be used to match any node (this will match instances 
# where ‘into’ is connected to any node with ‘1’ edge)
evaluator.match_features(df, [[[“(u_1 / into :1 (u_2 / .*) :2 (u_3 / YYY))”], [], “Entity-Destination(e1,e2)”]])

Мы также можем уточнить правила регулярного выражения на основе обучающих данных, это автоматически заменит регулярное выражение ‘.*’ узлами с высокой точностью.

evaluator.train_feature("Entity-Destination(e1,e2)", "(u_1 / into :1 (u_2 / .*) :2 (u_3 / YYY))", df)

Это возвращает (u_1 / into :1 (u_2 / push|pour) :2 (u_3 / YYY)) (заменяет '.*' на push и налить)

Изучение правил «человек в цикле»

Идея POTATO:

  • Используйте подграфы в качестве признаков для обучения простых классификаторов (LogReg, Random Forest и т. д.)
  • Создавайте подграфы только до определенного числа ребер (чтобы избежать большого количества функций)
  • Предлагайте правила пользователям в зависимости от важности функции
  • С пользовательским интерфейсом пользователь может принимать, отклонять, редактировать, комбинировать шаблоны.
  • Подграфы могут иметь регулярные выражения в качестве меток узлов или ребер.
  • Недоопределенные подграфы могут быть уточнены

Чтобы автоматически извлекать правила из помеченного набора данных, обучите набор данных графическими функциями и ранжируйте их на основе релевантности:

from sklearn.model_selection import train_test_split
train, val = train_test_split(df, test_size=0.2, random_state=1234)
trainer = GraphTrainer(train)
features = trainer.prepare_and_train(min_edge=1)

Переменная features будет содержать автоматически извлеченные правила:

(u_15 / into :1 (u_26 / push))
(u_15 / into :1 (u_19 / pour :2 (u_0 / xxx)))
(u_15 / into :1 (u_19 / pour))
(u_19 / pour :2 (u_0 / xxx))
(u_15 / into :2 (u_3 / yyy))

Пользовательский интерфейс

Помимо серверной части, описанной в предыдущих разделах, POTATO также поставляется с пользовательским интерфейсом HITL, позволяющим пользователю извлекать правила из набора данных. Для запуска пользовательского интерфейса HITL нам нужно загрузить набор данных в виде набора помеченных или неразмеченных графиков. Любой ориентированный граф может быть загружен, кроме предустановленных форматов (ud, 4lang, amr). Для предложения и оценки правил требуются наземные метки истинности (с использованием метода изучения функций, описанного в предыдущем разделе). Если они недоступны, пользовательский интерфейс можно запустить в расширенном режиме для начальной загрузки и аннотирования меток с помощью правил. После загрузки набора данных можно запустить интерфейс HITL, и пользователю будет представлен интерфейс, показанный на рисунке 3, созданный с использованием библиотеки streamlit.

Внешний интерфейс, показанный на рис. 3, обеспечивает:

  • 1 — браузер набора данных, который позволяет пользователю просматривать текст, график и метки для всех строк набора данных. Вьювер визуализирует графики с помощью библиотеки graphviz, а также предоставляет нотацию PENMAN, которую пользователь может скопировать для быстрого редактирования правил.
  • 2 — пользователи могут выбирать класс для работы (небольшое количество, если речь идет о классификации с несколькими метками).
  • 3 —список правил, созданных для каждого класса, сохраняется в виде списка, и их можно изменять, удалять или добавлять новые функции.
  • 4 — правила можно просматривать и оценивать в наборах данных для обучения и проверки.
  • 5 –прогноз каждого правила можно проанализировать, просмотрев истинно положительные, ложноположительные или ложноотрицательные примеры.
  • 6 —Кнопка «Предложить новые правила» возвращает список предлагаемых графиков вместе с их эффективностью на обучающих данных, позволяя пользователю выбрать те, которые следует добавить в список правил, этот интерфейс показан на рисунке. 4. Для правил, содержащих регулярные выражения, кнопка Уточнить заменит регулярные выражения дизъюнкцией высокоточных меток. Эта функция реализуется методом, описанным в предыдущем разделе.

Как описано, внешний интерфейс — это приложение с потоковой подсветкой, мы можем начать его с наборов данных для обучения и проверки. Сначала сохраните их с помощью следующего кода:

train.to_pickle(“train_dataset.pickle”)
train.to_pickle(“val_dataset.pickle”)

Затем приложение Streamlit можно запустить с помощью одной строки команды:

streamlit run frontend/app.py -- -t train_dataset.pickle -v val_dataset.pickle

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

streamlit run frontend/app.py -- -t notebooks/train_dataset -v notebooks/val_dataset -hr features.json

Расширенный режим

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

Затем можно запустить интерфейс:

streamlit run frontend/app.py -- -t unsupervised_dataset -m advanced

Оценивать

Если у вас есть готовые функции и вы хотите оценить их на тестовом наборе, вы можете запустить:

python scripts/evaluate.py -d test_dataset.pickle -f features.json

Результатом будет файл csv с метками и соответствующими правилами.

Услуга

Если вы готовы использовать извлеченные функции и хотите использовать наш пакет в производстве для логического вывода (генерирования прогнозов для предложений), мы также предоставляем REST API, построенный на POTATO (на основе fastapi).

Сначала установите FastAPI и Uvicorn

pip install fastapi
pip install "uvicorn[standard]"

Чтобы запустить службу, вы должны установить язык, graph_type и функции для службы. Это можно сделать через переменные окружения.

Пример:

export FEATURE_PATH=/home/adaamko/projects/POTATO/features/semeval/test_features.json
export GRAPH_FORMAT=ud
export LANG=en

Затем запустите REST API:

python services/main.py

Он запустит службу, работающую на localhost через порт 8000 (а также инициализирует правильные модели).

Затем вы можете использовать любой клиент для отправки почтовых запросов:

curl -X POST localhost:8000 -H 'Content-Type: application/json' -d '{"text":"The suspect pushed the XXX into a deep YYY.\nSparky Anderson is making progress in his XXX from YYY and could return to managing the Detroit Tigers within a week."}'

Ответом будет список с предсказанными метками (если ни одно из правил не совпадает, будет возвращено «НЕТ»):

["Entity-Destination(e1,e2)","NONE"]

Интерфейс Streamlit также имеет режим вывода, в котором реализованная система правил может использоваться для вывода. Его можно начать с:

streamlit run frontend/app.py -- -hr features/semeval/test_features.json -m inference

Заключение

POTATO позволяет быстро создавать системы на основе правил и предоставляет прозрачное, объяснимое и проверяемое альтернативное решение для моделей глубокого обучения в задачах НЛП. Если вы хотите узнать больше о фреймворке или попробовать его, вы можете проверить следующие источники:

  • Вы можете ознакомиться с нашей статьей POTATO: объяснимая структура извлечения информации
  • Код фреймворка доступен на GitHub под лицензией MIT: https://github.com/adaamko/POTATO, вы также можете проверить репозиторий на наличие дополнительных примеров и готовых систем правил для нескольких задач.
  • Также доступны Слайды с семинара по фреймворку
  • Посмотрите наше короткое демонстрационное (~2 мин) видео об инструменте: https://youtu.be/PkQ71wUSeNU
  • Есть более длинная версия с подробным описанием метода и представленным фоновым исследованием (~1 час): https://youtu.be/6R_V1WfIjsU

Рекомендации

[1] Дошивелез и др., На пути к строгой науке интерпретируемого машинного обучения, (2019)

[2] Девлин и др., Предварительная подготовка глубоких двунаправленных преобразователей для понимания языка, (2019)

[3] Серрано и др., Интерпретируемо ли внимание?, (2019)

[4] Бендер и др., Об опасностях стохастических попугаев: могут ли языковые модели быть слишком большими?, (2021)

[5] Банареску и др., Абстрактное представление значения для Sembanking, (2013)

[6] Ци и др., Stanza: набор инструментов для обработки естественного языка Python для многих человеческих языков, (2020)

[7] Корнаи и др., Семантика (2019)

[8] Хендрикс и др., SemEval-2010 Задача 8: Многофакторная классификация семантических отношений между парами именных (2010)