Извлечение структурированной информации из текстов является одной из важнейших тем в NLP. Чаще всего для решения определенного класса задач требуется использовать специализированные решения, адаптировать которые под специфику конкретной задачи не так просто.
В вебинаре рассматривается методика построения моделей машинного обучения на основе систем переходов, которая позволяет описать многие задачи структурного предсказания в рамках единого фреймворка.
Мы разберем общие принципы построения моделей на основе систем переходов, их преимущества и недостатки по сравнению со специализированными решениями и рассмотрим кейсы решения конкретных задач структурного предсказания этими моделями.
Видео: https://youtu.be/Ok9w0Qv25IM
Презентация: https://drive.google.com/file/d/17qXEf1w3lDsDBsyHXHQh6jLqqe0a_Ilh/view?usp=share_link
(00:00:00) (Начало записи)
Николай Михайловский: Представляю нашего сегодняшнего докладчика – Егор Грибков, ТУСУР и TomskSoft. Егор нам сегодня будет рассказывать про структурное предсказание в обработке естественного языка. Пожалуйста, Егор, передаю слово.
Егор Грибков: Всем привет! Начнем сразу с того, какие предсказания умеют делать модели машинного обучения? Мы можем либо предсказать одно число, либо группу чисел. Тогда в первом случае мы с помощью одного числа можем получить два класса, с помощью группы чисел мы можем получить некоторый фиксированный набор классов из конечного набора значений. Обычно мы хотим предсказывать что-то, помимо простых чисел или векторов чисел. Мы хотим предсказывать какие-то сложные структуры, как, например, на слайде «Джон – директор сада», мы хотим понять, что в этом предложении у нас есть какие-то NER (Named-entity recognition). Простого способа решить это у нас нет, поэтому нам надо каким-то образом эту задачу декомпозировать и свести ее к одной из первых двух.
Для этого существует структура предсказания, которая занимается тем, что осуществляет предсказание множеств взаимосвязанных переменных. Структура предсказания отличается от других тем, что, во-первых, у этих моделей, как правило, нефиксированные выходы, они зависят от размеров входа и не сводятся тривиально к задачам классификации, потому что, если вы захотите в задаче, где вам нужно каждому слову назначить какую-то определенную метку, то для такой задачи вам придется сделать Мn возможных классов, где у вас N – это количество слов в вашем предложении и M – это количество классов. Понятно, что вы не можете позволить себе предсказывать такое большое количество классов обычной моделью.
Кроме того, это мы можем занумеровать последовательности. Мы можем придумать некоторые более сложные структуры. Мы даже не всегда можем их перечислить, поэтому поговорим о том, как мы можем декомпозировать процесс предсказания некоторых сложных структур.
Я сразу буду говорить о нейронных моделях, не буду рассматривать более простые ранние варианты. Так или иначе, всё сводится к тому, что наш вход, сегодня будем говорить только про тексты, которые представлен отдельными дискретными символами, словами, мы будем обрабатывать его локально, например, с помощью с помощью сверточных нейронных сетей либо с помощью рекуррентных нейронных сетей. Одной возможностью является делать простое локальное предсказание. Мы получили какие-то признаки с помощью нашей нейронной модели для каждого отдельного слова и попытаемся превратить вектор каких-то чисел для этого слова в вектор выходных чисел, которые будут говорить нам о категории, принадлежности этого класса.
В данном случае приведем пример из работы по аспектам реляционного анализа тональности, где у нас в приложении есть две сущности – tuna и wasabe potatoes, из которого мы хотим понять, что в этом предложении упомянули тунца и картофель. Мы можем это сделать с помощью получения признаков нейронной сетью и ее последующей классификации.
Можно развить эту идею дальше и пойти в сторону того, чтобы начать учитывать какие-то взаимные зависимости между отдельными элементами выхода уже вероятностного характера. Для этого придумали такую модель, как Conditional Random Fields. По-русски называется условные случайные поля, если не ошибаюсь. Тут идея в том, что, помимо того, что у нас есть набор чисел для каждого отдельного слова, который говорит о принадлежности этого слова к какому-то классу, у нас еще есть некоторая матрица с параметрами того, какова вероятность переключиться с одного класса на другой при просмотре слов в порядке слева направо. У нас есть некоторые специальные алгоритмы, которые нам позволяют, во-первых, считать эту матрицу параметром, который будет оптимизироваться в ходе обучения нейронной сети, и затем эффективно производить процедуру вывода, которая позволит нам достичь в некотором смысле глобально-оптимальной последовательности предсказаний.
(00:05:11)
Мы рассмотрели самый простой случай, когда мы хотим предсказать просто набор тегов для входного предложения, для каждого слова. Что, если мы дальше хотим услышать нашу задачу, или мы хотим уже не просто найти все упоминания, а мы хотим образовать некоторые связи между ними. Например, в задаче аспекты реляционного анализа мы хотим найти какие-то сущности, которые называются аспекты, которые обычно связаны с продуктом, с его характеристиками, с чем-либо еще, с какими-то элементами пользовательского опыта или взаимодействия с сервисом, с товаром. И некоторые слова или фразы, которые указывают на итоговый опыт этого взаимодействия. Грубо говоря, тунец хороший. Мы можем поставить такую задачу, что мы хотим узнать, у нас одна модель определила, что у нас есть две сущности в этом предложении.
Теперь мы хотим узнать, относится ли слово excellent к слову tuna. В данном случае мы можем пойти по простому пути и сделать еще одну модель, которая просто будет принимать какой-то выход от предыдущей модели, и используя какие-то новые наборы признаков, в данном случае это частеречная разметка, оппозиционные признаки и выход рекуррентной нейронной сети. После чего мы просто проведем классификацию.
Таким образом у нас получается некоторая каскадная модель, состоящая из двух отдельных компонентов. Первый компонент у нас предсказывает теги для отдельных слов или фраз. Вторая модель уже работает поверх выхода этой модели и пытается найти связи между отдельными сущностями. Этот подход называется pipelining. У него есть две проблемы, которые являются следствием одной причины.
Первая проблема – то, что пайплайны у нас умеет хорошо распространять ошибки снизу вверх. Грубо говоря, если у вас какой-то компонент нижнего уровня ошибся, то компонент верхнего уровня у вас довольно редко имеет возможность как-то компенсировать его ошибку. Соответственно, всё, что находится выше по пайплайну, у вас будет выдавать ошибочные предсказания.
Вторая проблема частично связана с первой, ее обусловливает. Это независимое обучение отдельных компонентов пайплайна. Как правило, мы берем нашу фиксированную обучающую выборку, обучаем сначала компонент для извлечения сущностей из предложений. Опираясь на истинные данные, которые у нас есть в выборке, мы обучаем компонент, который предсказывает связи. Но при таком подходе возникает проблема того, что, если компонент ошибается, он начинает в дальнейшем передавать ошибку вверх по пайплайну.
Кроме того, существует такое направление, оно называется multi-task learning, которая связана с тем, что у нас многие задачи связаны друг с другом. Когда мы решаем задачу определения отдельных сущностей, мы уже можем кое-что знать о том, как эти сущности могут быть связаны между собой в тексте. Когда мы используем подход на основе пайплайнов, обычно это не столь тривиально получить хорошую систему, которая бы могла делать предсказания в рамках одного компонента.
Как раз решению этих двух проблем посвящены так называемые модели на основе систем переходов. Модели на основе систем переходов определяются четырьмя главными компонентами.
Первый компонент – это конфигурация. Грубо говоря, это набор данных, который у нас описывает текущее состояние предсказания. Причем у нас нет некоторых очень жестких требований к тому, что это конкретно за структура данных, что они в себе содержат. Выделяются две специальные конфигурации С0 – начальная СТ – конечная. С0 – это то, что мы имеем до начала предсказания. СТ – это та конфигурация, в которую мы приходим. Как мы ее достигли? Мы заканчиваем процесс предсказания.
(00:10:15)
Второй важный переход – это множество переходов, которые представляют из себя некоторые правила, по которым мы можем переписывать конфигурацию. Например, если у нас конфигурация содержит какой-то список входных слов и список выходных меток, то эти правила могут описывать, что мы можем убирать элементы из одного списка, вставлять их в другой. Но никто не ограничивает вас в том, что вы можете создать более сложные правила изменения этих конфигураций.
Третий важный компонент- это некоторая функция А, которая говорит для каждой конфигурации, какие переходы из нее вы можете совершить. Вы можете построить такие системы переходов, в которых у вас не из каждой конфигурации возможно выполнить некоторые переходы, поэтому вам нужен какой-то способ, чтобы не делать очевидные глупости. В данном случае функция А выполняет эту роль.
Последний компонент позволяет нам связать всю эту машинерию с машинным обучением. Это функция ϕ от С в момент времени T – ϕ(Ст), которая извлекает вектор чисел, которые являются признаками для текущей конфигурации системы. Эта функция ϕ может быть чем угодно. Но сегодня мы будем говорить только о том случае, что эта функция является нейронной сетью.
Теперь о том, как у нас обычно выглядит оперирование этой машинерией. У нас имеется некоторый вход, в нашем случае это будут обычные предложения, если мы говорим об обработке естественного языка. Этот вход используется для того, чтобы каким-то образом задать первоначальные значения всех структур данных в нашей конфигурации С0. После этого мы можем выполнять отдельные переходы, каким-то образом изменять конфигурацию с помощью этих переходов до того момента, пока мы не достигнем терминальной конфигурации, из которой мы можем уже получить наш финальный результат.
Теперь как это трансформировать в задачу машинного обучения? Все наши объекты в предметной области, например, предложения, где у каждого слова есть какой-то тег, или наши деревья синоптических зависимостей, или что мы можем себе придумать, например, графы, мы должны уметь представлять в виде такой двойки из С0 (изначальной конфигурации с проинициализированными структурами) и последовательности переходов, которые приведут нас в ту правильную конечную конфигурацию, которую мы хотим.
Пока мы будем полагать, что эта последовательность уникальна. У нас есть набор исходных продуктов. У нас есть рецепт, как из этого набора продуктов приготовить финальное блюдо. Но правильный рецепт для каждого входного набора продуктов у нас всегда только один. Когда мы представили исходные объекты в таком виде, мы уже можем решать обычную задачу машинного обучения с помощью максимизации правдоподобия, как это представлено на слайде. Просто будем пытаться оптимизировать лосс того, как правильно мы предсказываем каждый отдельный элемент последовательности переходов.
Если мы это всё вместе интегрируем, у нас получится некоторые конфигурации, из которых мы извлекаем признаки, которые подаются в нашу модель. Эта модель предсказывает нам либо распределение вероятностей, либо конкретный переход, который надо совершить. Мы совершаем этот переход, при этом каким-то образом изменяя нашу конфигурацию, и опять начинаем повторять до тех пор, пока мы не достигнем терминальной конфигурации. Что хорошего в использовании нейронных сетей в данном подходе?
(00:15:00)
Модель и то, что нам дает функция ϕ, может быть нейронной сетью от начала до конца. По сути, мы получаем какой-то пайплайн, который у нас дифференцируется от начала до конца и который мы можем оптимизировать как обычную нейронную сеть. При этом элементами конфигурации могут быть не прямо слова, а какие-то векторные представления, которые получены с помощью нейронных сетей или других способов получения векторных представлений. Из-за того, что мы используем нейронные сети, мы можем разделить параметры по всему ходу предсказания, модель не учитывает то, как конкретный шаг используется внутри.
С учетом того, что у нас нет сильных ограничений на структуру конфигурации и на то, каким образом элементы последовательности ее изменяют, как наши переходы изменяют эту конфигурацию, это дает нам возможность решать очень разные задачи в рамках одного фреймворка.
Теперь мы посмотрим конкретные задачи, которые можно решать в рамках данного фреймворка. Например, как я уже рассматривал до этого пример распознавания именованных сущностей, Lample в своей работе 2016 года предложил очень простой способ. Он определил конфигурацию из четырех элементов, где есть buffer, содержащий все слова из предложения, которое вы сейчас обрабатываете; stack, куда д в ходе представления некоторые слова могут забрасываться моделью; output – это все наши найденные сущности (entities) и history – это история того, какие переходы мы совершили в ходе предсказания.
Множество переходов состоит из трех элементов. Это shift, out который перемещает слово из буфера в stack, reduce – схлопывает все слова из stack специальным образом и получает предсказание, out – просто выкидывает слово из рассмотрения.
Процесс предсказания представлен внизу на слайде. Изначально у нас есть буфер, проинициализированный предложением «Mark Watney visited Mars». Дальше мы можем посмотреть, как у нас изменяются отдельные элементы конфигурации при выполнении переходов.
Мы знаем, что Mark Watney – это человек. Мы переместим оба слова в stack и хлопнем этот stack, скажем, что мы предсказали, что Mark Watney – это человек. После того мы выкинем ненужное нам слово visited. Посмотрим, что Mars – это какая-то интересная для нас сущность, в данном случае, локация, и скажем, что Mars – это именованная сущность и это будет наш выход.
В своей статье они использовали изучение BiLSTM для извлечения признаков из текста и специальные сети под названием Stack SLSTM для извлечения признаков из каждого отдельного элемента конфигурации. Я не буду подробно останавливаться на Stack SLSTM. Конкретную машинерию за ними можно посмотреть в статье, но видно, что в данном случае простая комбинация SLSTM и CRF довольно неплохо произошла в предложенную модель на основе системы переходов.
Но есть некоторый специальный случай этой задачи, так называемый discontinuous NER. Эта задача посвящена решению такой проблемы, когда у нас именованная сущность разрывается в тексте. Наиболее частый случай, когда мы разрываем что-то союзом, например, muscle pain and fatigue. В данном случае мы знаем, что у нас есть сущности – muscle pain и muscle fatigue.
(00:20:00)
Ребята в этом году предложили модель на основе системы переходов, которая во многом аналогична предыдущей. Конфигурация модели точно такая же, но они решили усложнить систему переходов. Shift делает то же самое. Out делает то же самое. Дальше они ввели три перехода: reduce, который смотрит на два топовых слова в stack, склеивает их вместе и кладет в этот же stack обратно; две версии left-reduce, которые извлекают два, схлопывают, но оставляют второй, и right-reduce, который извлекает два слова из stack, схлопывает, кладет обратно, но оставляет первое. Complete смотрит, что сейчас лежит наверху stack и переносит эту сущность в output.
Для извлечения признаков они использовали BiLSTM, ELMO. Насколько я помню, они пробовали BERT, но с BERT у них не получилось. Работа на ELMO им дало лучшее качество. Здесь рассмотрены элементы конфигурации, как они изменяются в течение предсказания. Самое интересное место помечено. Вот этот момент, когда мы уже понимаем, что muscle – это какая-то интересная для нас сущность, мы ее помещаем в stack, pain – тоже интересная для нас сущность, поэтому ее помещаем в stack.
После этого мы знаем, что muscle у нас не только pain, но и fatigue. Мы знаем, что это образует цельную сущность. Мы ее предсказываем с помощью left-reduce, кладем в stack, но мы знаем, что muscle нужен будет потом, поэтому мы его оставляем, тут используются left-reduce. Потом опять выкидываем ненужное слово and, делаем опять reduce, но в данном случае уже полный. Во-первых, мы рассмотрели все слова, и дальше они нам не будут нужны. После этого делаем complete и делаем предсказание.
Это позволило довольно сильно поднять метрики для того случая, когда они предсказывают отдельные сущности, которые содержат в себе разрыв. У них получилось 63,1% по F1.
Следующая задача – семантический разбор диалога, который решали в Facebook. Задача поставлена следующим образом. Мы хотим решить две задачи, которые обычно популярны в различных чат-ботах – это intent parsing (classification), определить главную тему предложения или запроса, который нам послал пользователь, второе – это slot filling.
После того, как мы определили, что это за предложение, какого оно типа, мы хотим извлечь оттуда какую-то информацию, которую можем использовать для того, чтобы выполнить этот запрос. Понятно, если пользователь спросит направление до какой-то игры, где, видимо, играют Eagles, то мы должны понять, что пользователь хочет узнать направление. Потом мы хотим узнать, что the Eagles game – это какой-то ивент, где участвует, видимо, Eagles. Мы должны найти отдельные слоты. В данном случае это наименование события и категория этого события, то, что нам поможет найти, а вообще существует ли этот ивент, проводится ли он сейчас, и как до него конкретно добраться, где он проводится.
Для решения такой задачи они решили обратиться к формализму nested intent parsing и slot filling, где они представили все свои входные данные предсказания в виде таких деревьев.
(00:25:03)
Если вы посмотрите, вы можете заметить, что эти деревья очень похожи на те деревья, которые получаются в ходе фазового анализа предложений, которая является очень популярной, распространенной задачей, и которая решается с помощью методов на основе систем переходов.
Для решения этой задачи они решили использовать уже известную сеть, которая называется Recurrent Neural Network Grammar, которая была использована как раз для решения задачи синтаксического разбора и построения деревьев конституентов. В данной модели четыре элемента конфигурации: список необработанных слов на входе, это stack для найденных конституентов, то есть отдельных частей входа, output – это то место, куда мы выбрасываем все наши предсказанные конституенты, и history – это история совершенных переходов. У нас также три перехода – перемещение из буфера в stack с помощью shift, reduce у нас схлопывает все слова в stack и помещает их обратно в этот stack, и out, который перемещает из буфера в output.
На слайде показано, как работает эта система. Тут три действия. Вместо out тут используется NT, которая обозначает открытие нового не терминала. В этом примере вы можете увидеть, как у нас исходное предложение «The hungry cat meows» развивается в иерархическую структуру, где есть одна фраза «The hungry cat», и вторая глагольная фраза «meows», которая в целом составляет одно предложение.
Используя похожесть этих двух доменов, тот, который они рассматривали, и предсказание дерева конституентов, решили использовать эту модель в их задаче и сравнили ее с тремя альтернативами, простыми seq2seq моделями.
Одна модель простая, на основе сверточной сети, она сверточная сеть на LSTM и одна на Transformer, которые в тот момент только-только появились.
Самое главное достижение у них – это самый высокий F1 по дереву, достижимый с помощью этой модели. Второй важный момент – это метрика Tree Validity, которая показывает, насколько корректно построено ваше дерево. Видно, что Transformer не всегда могут корректно предсказать это входное дерево. Не совсем понятно, почему они не могли применить такой же подход к ограничению того, что модель может давать на выходе в зависимости от того, что она предсказала ранее. Это трюк не новый. Они могли его спокойно применить тут.
Следующая задача связана с моей практикой в компании TomskSoft и двумя задачами, которые я там решал. Первая задача связана с извлечением мнений из текстов отзывов пользователей. Что такое мнение? У нас есть некоторые характеристики продуктов или услуг, которые пользователи получили или приобрели. Это может быть сам товар, отдельная часть мобильного телефона: экран, батарея либо какое-то его свойство, водостойкость. Описание – это некоторое эмоционально окрашенное высказывание об аспекте, которое вы используете в своем отзыве. Например, вы можете сказать «батарея хорошая», «батарея плохая» или «батарея достаточно долго держит, держит день».
(00:30:11)
Связка из аспекта, описания и двух атрибутов, один из которых – это тональность, которая говорит, хорошо или плохо это высказывание говорит об аспекте. Мы сделали некоторую классификацию того, к чему относится аспект. Аспект может быть товар либо его часть, продавец, как пользователь повзаимодействовал с продавцом, и опыт доставки – пришло вовремя, задержалась, трекалось.
Для обучения модели мы разместили корпус отзывов на русском языке на AliExpress. Они выглядят примерно так. Можете видеть сущности и их атрибуты. Это очень похоже на самую первую задачу, про которую я рассказал, аспект реляционного анализа тональности и является некоторой вариацией, только с учетом того, что у нас есть еще сверху дополнительные атрибуты, которые характеризует связку из аспекта и описания вместе.
Для того, чтобы совершать предсказания и извлекать эти мнения, разработали модель на основе системы переходов, у которой конфигурация состоит из четырех элементов: это буфер необработанных слов, список извлеченных спанов, этих упоминаний аспектов и описаний, список отношений спланов со значениями предсказанных атрибутов и H – это история совершенных переходов.
Множество переходов состоит из шести элементов. Первое у нас выбрасывает слова из исходного предложения. Start с меткой l говорит, что мы только что предсказали первое слово какого-то из этих спанов.
Add нам говорит, что очередное слово должно включиться в уже существующий спан. Грубо говоря, предсказание спанов мы осуществляем инкрементально, по одному слову за раз.
Переход link у нас связывает предсказанные ранее спаны. Так как мы их копим в списке S, для этого мы используем этот переход, числа n1 и n2 у нас фиксированные. Всего, насколько я помню, мы исследовали вариант с семью возможными позициями. Link у нас предсказывает позиции один-два, один-три, один-семь, и в обратном порядке, семь-один. Он пытается предсказать еще направление связи.
Переход Attr (a, v) предказывает, что к последней связи, которую мы предсказали, мы должны прицепить информацию о том, что мы предсказали для атрибута «а» значение «v». В данном случае атрибут нас – тональность с двумя возможными значениями положительными и отрицательными, и атрибут «c» с тремя доступными значениями: «продавец», «доставка» и «товар».
Специальный переход end, который обозначает конец предсказания. Таким способом мы преобразуем наше мнение, которое представлено такой структурой из двух спанов и связи с атрибутами в виде последовательности переходов. Тут просто продемонстрированы примерные этапы преобразования отдельных элементов конфигурации в вектор фичей, которые вместе агрегируются и предсказывают вероятность совершения каждого отдельного перехода.
Для извлечения признаков используется BiLSTM. Мы также пробовали сверточные сети, но они не взлетели. Самое главное, что нам это помогло добиться улучшения всех метрик, но набольший прирост у нас оказался при определении атрибутов.
(00:35:05)
Мы скакнули с 48 по F1 до 57, и 57 до 68. Во многом это обуславливается тем, что все остальные модели, с которыми мы сравнивали, они не основывались на системе переходов. Это были пайплайны. Видно, что они могли сохранять довольно неплохо точность предсказания отношений, но, видимо, последним компонентам, которые осуществляют предсказания атрибутов, не хватало либо репрезентативной мощности, либо накопленные ошибки мешали им правильно предсказывать конкретные значения атрибутов.
Вторая задача, с которой вы столкнулись – это обработка запросов пользователей в службу поддержки программных продуктов. В данном случае мы говорим о двух типах сущностей. Это функция, которая описывает либо некоторые фичи ПО, либо элементы его GUI и описание, которое относится к четырем классам. Это описание ошибки, возникающей у какой-то фичи, запрос добавления новой фичи, просто высказывание эмоционального характера о том, нравится или не нравится фича. Так как у нас было мало реальных данных с саппорта, мы в качестве прокси данных использовали отзывы из Google Play.
На слайде приведены примеры этих самых запросов. Видно, что, в отличие от задач NER, где разные люди с довольно высокой степенью вероятности выберут одни и те же слова в качестве сущностей, в этой задаче мы наблюдали, что у нас разные аннотаторы имеют разные предпочтения по длине выбираемых спанов, потому что мы первоначально не задавали жестких ограничений на то, как они будут выбирать. Мы просто говорили им: «Выделите функции и выделите описание», что потом сыграло злую шутку в том, что мы считали коэффициент согласованности между аннотаторами, и он составляет около 0,6, что говорит о том, что разметка в высокой степени является субъективной.
Мы использовали абсолютно ту же самую модель, только в данном случае мы изменили типа спанов, которые мы предсказываем, и на этот раз не предсказываем вообще никаких атрибутов. В данном случае мы смогли получить намного более заметный прирост, который, возможно, связан с тем, что наша модель каким-то образом смогла лучше обработать такой корпус, который очень по-разному аннотирован.
Во-вторых, этот корпус намного меньше. Насколько я помню, он раза в четыре меньше, чем корпус для предсказания мнений. В данном случае мы, скорее всего, видим еще то, что те репрезентации, которые получаются у моделей на основе систем переходов, они еще обладают некоторой большей эффективностью в количестве данных, которые необходимы вам для достижения заданной точности.
Напоследок я хочу рассказать об одном трюке, который используется при обучении данных моделей. Так как у нас все размеры выборок ограничены, то количество цепочек этих переходов, которые мы используем во время обучения, также ограничено. Из этого есть два следствия. Во-первых, когда я говорил, что у нас каждому входному объекту соответствует одна возможная правильная цепочка действий, это положение выполняется далеко не всегда. Можно собрать такую систему переходов, в которой у вас одному входному объекту может соответствовать несколько возможных цепочек переходов, которые приведут к одному и тому же правильному предсказанию. Такое встречается в разных системах для dependancy парсинга. Для них и думали способы обучения через динамических оракулов.
Вторая проблема связана с тем, что, из-за того, что выборка ограничена, и мы всегда следуем одному и тому же рецепту, мы посещаем ограниченное число конфигураций. Но мы же знаем, что во время предсказаний мы обязательно будем совершать ошибки. Это может нас завести в некоторые конфигурации, которые мы не видим во время обучения, но которые являются такими, из которых мы впоследствии можем достигнуть нашей финальной цели и получить хорошее предсказание.
Это продемонстрировано на слайде. Например, во время обучения мы всегда ходили только по одному пути, использовали одни и те же переходы, которые есть в обучающем наборе. Но во время вывода мы каким-то образом могли попасть в конфигурацию, которая является правильной, но мы ее просто не видели. Но модель об этом не знает, что конфигурация правильная, и дальше может найти какой-то другой путь, который всё-таки приведет нас к правильной цели.
Но модель этого не умеет, поэтому она обычно путается и дальше начинает предсказывать вам не то, что вы хотели бы увидеть на выходе, что нам говорит о том, что, возможно, мы можем это как-то учесть. Для этого существуют специальные динамические оракулы, которые используются для того, что во время обучения иногда скармливать ей либо какие-то неправильные переходы, из-за которых модель может попасть в частично неправильное состояние. Но мы можем руками восстановить или построить такую цепочку дальнейших переходов, которые приведут нас не в то же самое корректное состояние в конкретную конфигурацию, но в конфигурацию, которая наиболее близка к этой.
Соответственно, если мы будем обучать модель таким образом, мы сможем, грубо говоря, заставить ее посмотреть на разные возможные конфигурации во время обучения, и в дальнейшем уже меньше путаться и научиться некоторым образом восстанавливать те ошибки, которые она уже совершала, что не могут делать модели на основе пайплайнов.
Возвращаясь к преимуществам и недостаткам рассмотренных моделей, среди преимуществ в рамках одного фреймворка на основе сети переходов можем решать очные разные задачи. У нас есть хороший индуктивный bias через эти элементы конфигурации, потому что мы подбираем элементы конфигурации под конкретные задачи.
Нативный multi-task learning, как показано на задачах, связанных с изучением мнений, когда мы одновременно вытаскивали и спаны, и отношения, и еще предсказывали атрибуты. Всё это в одной сети, которая разделяет параметры между разными задачами.
Среди недостатков – без динамических оракулов она всё-таки так же подвержена проблеме распространения ошибок, только уже в данном случае не при передаче от одного этапа на другой, а просто при совершении предсказания цепочки переходов. Эти модели очень не дружелюбны к GPU, потому что они очень последовательны в отличие от тех же трансформеров. Они сложнее в реализации, потому что вам нужно реализовать всю машинерию, связанную с тем, как вы представляете вашу структуру данных, как вы реализуете эту функцию А, которая у вас выдает список дальнейших возможных переходов.
В некоторых задачах, особенно там, где у вас есть какие-то очень специфические ограничения на выход, которые вы не можете удовлетворить с помощью обычных моделей, этот класс моделей может вам помочь при решении таких задач. Тут ссылки на все пейперы, которые я рассмотрел. У меня всё. Спасибо за внимание.
Николай Михайловский: Спасибо, Егор, очень кратко и интересно. Коллеги, пожалуйста задавайте вопросы. Можно задавать вопросы через функцию QnA, можно через чат, можно поднимать руку. Пожалуйста, ваши вопросы. Пока коллеги собираются с вопросами, мне с самого начала показалось, что технология чем-то похожа на Bayesian belief networks, в которых тоже имеются некие графы переходов между состояниями, хотя там нет всей этой машинерии. Можете что-то прокомментировать по этому поводу?
(00:45:25)
Егор Грибков: Я не большой знаток байесовских методов. Но, насколько мне известно, там обычно подразумеваются графы с фиксированной структурой, на которой мы осуществляем распространение наших белифов между узлами сети с помощью message passing. Возможно, там есть некоторые связи, но мне о них неизвестно. Я ни разу не видел попытки свести строго байесовский подход с системой переходов.
Николай Михайловский: У нас в чате есть вопрос. Насколько хуже работает динамический оракул + неструктурированное предсказание? Например, если брать Спейси, который умеет такое делать для синтактического анализа.
Егор Грибков: Вся идея динамического оракула в том, вы его применяете, когда у вас есть какая-то структурированная модель внутри. Насколько я знаю, Спейси используют и для NER, и для dependency парсинга. Там используется динамический оракул и структурированное предсказание.
Николай Михайловский: По поводу соотношения качества.
Егор Грибков: Тут имеет говорить смысл говорить о структурированном предсказании без динамического оракула. Я не могу сейчас привести конкретные метрики. Но они не такие большие, они в пределах процентов, не десятки процентов, три-пять. Это то, что я видел в задачах dependance парсинга. Всегда есть преимущество, не случайная флуктуация. Это реально полезная вещь. Но это не то, что позволит вам добиться впечатляюще большей производительности. Это будет меньше, если вы смените SLSTM Transformer.
Николай Михайловский: Спасибо. Коллеги, пожалуйста, еще вопросы.
Егор Грибков: Еще можно дать такой комментарий, что всё зависит от исходной модели. Чем больше у вас исходная модель может запомнить структур, тем меньше вам имеет смысл использовать динамический оракул.
Николай Михайловский: Коллеги, пожалуйста, еще вопросы. Юрий опять спрашивает, какие типичные ошибки сейчас у задачи. Юрий, может быть, вы голосом уточните вопрос?
Юрий: Вопрос такой. Задача предсказания этих аспектов на запросах. Какие типичные ошибки для всех задач? Модель просто ошибается, потому что неконсистентный датасет, потому что ошибки в датасете, или есть классы каких-то ошибок, которые можно выделить и улучшить ситуацию другими способами?
(00:50:06)
Егор Грибков: Какая наша задача, с которой мы столкнулись – это «пришел в целости и сохранности». Проблема в том, что мы еще отчасти решаем задачу discontinuous NER. Модели ведут себя не всегда консистентно в плане выборе того, объединяют ли они сейчас предсказание в один спан или разделят его на два. Это одна из самых частых ошибок.
Вторая частая ошибка у этой модели. Так как она предсказывает расстояние между фиксированными позициями в этом стеке, куда она складывает спаны, и в датасете основное количество связей короткие, один или два таких спана, у нее очень сильный байес в строну того, чтобы предсказывать короткие связи. Это приводит к тому, что она иногда чуть-чуть не добирает в плане длинных связей, и наоборот, перебирает в плане коротких связей. Это самая частая проблема.
Также возникает другая проблема, связанная с предсказанием тональности, которая заключается в том, что некоторые слова, которые не являются эмоционально окрашенными, хорошо или плохо, а говорят о какой-то характеристике. Самый понятный пример – это большой и маленький. В зависимости от товара они могут обозначать как что-то хорошее, так и плохое. Если батарея большой емкости, то это хорошо, а если батарея большая по размеру и тяжелая, то это, скорее всего, плохо.
Так как размер датасета у нас был довольно ограничен, это тоже очень частый кейс, то, что модели просто не хватает обучающих данных для того, чтобы начать учитывать нюансы конкретных продуктов. Я назвал основные.
Юрий: Там еще вторая часть вопроса маленькая. Есть ли какие-то способы, может быть, отдельных моделей, чтобы улучшить именно для этих конкретных классов ошибок?
Егор Грибков: Да, я думаю, есть. По крайней мере, то, что плохо решаем discontinuous случай, в данном случае, скорее, это надо исправлять с помощью разметки. Возможно, его как-то можно исправить с помощью _____ (00:53:06), просто обработка аутпута, смотреть, есть ли там союзы.
Есть еще один способ, про который я тут не говорил. Как и в обычной seq2seq модели, в данном случае можно использовать, beam search, когда мы делаем не одно предсказание цепочки, всегда выбираем максимум на каждом этапе, а мы имеем какой-то пул вариантов, которые мы постепенно отсекаем, самые нежизнеспособные варианты. Использование пулов тоже может дать значительный прирост. И всякие такие подходы, типа ассемблирования, может дать буст.
Юрий:
Николай Михайловский: Спасибо, Юрий и Егор. Еще вопросы.
Егор Грибков: Еще могу прокомментировать по поводу того, что мы использовали только сверстки LSTM сети. Пока не удалось всё это завести с BERT. Спаны модели, которая использует фичи из BERT, ищет даже лучшее на 2-3%, но совсем не может определить связи. Но мы делали начальный эксперимент, когда брали фиксированный BERT, с замороженными весами и тюнили только остаток сети.
Николай Михайловский: Связь аспектов и описания решает отдельная модель или на основе расположения?
(00:54:56)
Егор Грибков: Как раз связь аспектов и описания у нас решает одна модель. У нее есть специальный переход, link. У нас есть отдельная структура S, где мы храним все найденные на текущий момент эти сущности, аспекты и описания. Мы их запомнили. Затем переход link может нам сказать, в этом списке свежее первый и второй спан. Но мы можем найти связи не между всеми, только между семью такими спанами. Никаких признаков для учета положений нет.
Николай Михайловский: Станислав еще в чате спрашивает, на PyTorch или на TensorFlow.
Егор Грибков: Первая модель была написана на изученческом фреймфорке, который называется DyNet, который писали для себя ребята из Carnegie Mellon, чтобы быстро читать всякие NLP сетки, в частности, для этих моделей на основе систем переходов в синтактическом парсинге. А сейчас всё переписано на PyTorch.
Николай Михайловский: В строку вопрос, есть какие-то открытые репозитории с подобными моделями?
Егор Грибков: Для парсинга наверняка. Discontinuous NER тоже могу потом найти, перевести. Для других не уверен.
Николай Михайловский: Большое спасибо, было очень интересно. Область оказалось неожиданной, такие механизмы, управляемые нейронной сеткой, и работает вроде бы хорошо. Здорово. Большое спасибо и до новых встреч. До свидания.
Егор Грибков: Спасибо за внимание. До свидания.
(00:57:23) (Конец записи.)