В этом посте я хочу объяснить детали из «Перейти к сути: обобщение с помощью сетей генераторов указателей». Это старая статья 2017 года, но в ней есть несколько очень интересных идей, которые привлекли мое внимание, и я хочу воспользоваться возможностью, чтобы объяснить их здесь.
Я предполагаю базовые знания простых нейронных сетей и концепций машинного обучения, но объясню всю необходимую информацию, необходимую для понимания этой конкретной статьи. Статья будет основываться на оригинальных моделях последовательностей с вниманием (эпоха до трансформации), и я буду использовать визуализации из Поста Джея Аламмара: Визуализация модели нейронного машинного перевода, которую я настоятельно рекомендую в качестве дополнительного чтения! Я также буду использовать уравнения из замечательного курса Эндрю Нг Модели последовательности, который также рекомендую для лучшего понимания.
Введение в суммирование текста
Резюме текста заключается в извлечении наиболее важной и релевантной информации из фрагмента текста. Например, обобщение разговора между несколькими людьми или обобщение новостных статей.
Существует два типа методов обобщения: извлекающий и абстрактный. Извлекающее обобщение просто копирует части исходного текста. Абстрактное обобщение создает осмысленное резюме, часто с использованием слов, отсутствующих в исходном тексте. В этом посте мы сосредоточимся на Сетях генераторов указателей, адаптации к оригинальным методам обобщения абстрактного текста.
Последовательность моделей
Входными данными для модели суммирования текста будет фрагмент текста. На выходе будет сводка — еще один фрагмент текста. Чтобы закодировать фрагмент текста, вам сначала нужно его разметить. Токены могут быть отдельными словами или подсловами. А пока давайте предположим, что каждый токен — это слово. Таким образом, у нас есть последовательность слов как на входе, так и на выходе, и эти модели называются (многие ко многим) моделями последовательностей.
Модели Seq2seq состоят из двух компонентов: кодировщика и декодера. Кодер берет все входные слова и преобразует их в вектор контекста, кодируя исходный текст. Декодер берет вектор контекста и генерирует выходной текст — сводку.
До 2017 года (когда была представлена архитектура Трансформатор) как для кодировщика, так и для декодера использовалась рекуррентная нейронная сеть (RNN). Давайте углубимся в то, как они работают!
RNN
Во-первых, давайте сделаем краткий обзор стандартной нейронной сети:
Пусть W₁, b₁ и W₂, b₂ — веса и смещения для слоев 1 и 2 соответственно. Тогда скрытый слой/состояние имеет активацию a₁ и выход y^, определяемый следующими уравнениями:
где g₁ обычно представляет собой tanh/ReLU/GeLU иg₂сигмоид/softmax активационную функцию.
В стандартной нейронной сети выше вы должны передать весь текст на входной слой. Вместо этого RNN обрабатывают слова последовательно по одному.
Мы токенизируем входной текст в последовательность слов. Обозначим слово на временном шаге t(t-е слово) как x‹t›. На каждом временном шаге RNN принимает в качестве входных данных x‹t› и предыдущую скрытую единицу измерения. Например, уравнения для RNN на временном шаге 1 задаются следующим образом:
Единственное отличие состоит в том, что теперь у нас есть дополнительный термин Wₐa₁‹0›, который позволяет нам использовать скрытое состояние предыдущего временного шага. Wₐ — это дополнительная обучаемая матрица. Обратите внимание: поскольку на временном шаге 1 у нас нет предыдущих скрытых состояний, мы инициализируем a1‹0› как вектор нулей.
И вообще, на временном шаге t имеем следующие уравнения:
Зачем нам использовать RNN?
- Входы и выходы могут иметь разную длину, поэтому вам придется дополнять входы до некоторой максимальной длины в стандартной NN.
- Стандартная NN не разделяет изученные функции в разных позициях текста. (например, «Гарри» на позиции 1 и «Гарри» на позиции 10 должны иметь одинаковое значение).
Интуиция такова, что информация о предыдущих словах сохраняется и передается по сети, а затем используется для прогнозирования.
[Позже было обнаружено, что просмотр слов перед текущим словом также полезен, и была введена двунаправленная RNN. RNN также страдают от забывания слов в начале предложения, а позже стали использоваться GRU / LSTM. И BiRNN, и LSTM на самом деле восходят к 1997 году!]
Встраивания
Каждое слово x‹t› представлено вектором встраивания. Векторы вложения обладают тем свойством, что слова, близкие по смыслу, находятся близко друг к другу в векторном пространстве. Например, вставка Word2Vec обладает тем свойством, что
т.е. разница между векторами вложения для королевы и короля примерно равна расстоянию между векторами вложения для женщины и мужчины . Эта разница может указывать, например, на разницу в поле между двумя парами.
Декодер
Как и кодировщик, декодер также является RNN.
Так же, как и раньше, на каждом временном шаге RNN принимает скрытое состояние предыдущего декодера a‹t-1› и некоторые входные данныеx‹t›. Есть три основных отличия от энкодера:
- a‹0› теперь является конечным скрытым состоянием от кодировщика (известного как вектор контекста), который содержит всю закодированную информацию о входном тексте.
- Вход x‹1› представляет собой вектор встраивания для токена ‹EOS› (конец предложения) и x‹t› = y^‹t-1› , т. е. выход на временном шаге t-1 подается в качестве входных данных для временного шага t.
- Декодер продолжает генерировать слова до тех пор, пока не будет сгенерирован токен ‹EOS›.
Выводы декодера
Выход декодера на каждом временном шаге представляет собой вектор логитов, который преобразуется в вектор вероятностей с помощью функции softmax. Это наш прогноз y^‹t›, и это вектор, размер которого равен размеру словаря. Словарный запас — это все слова, которые модель знает и может предсказать. Давайте сделаем пример со словарем, состоящим всего из трех слов: кошка, собака и мышь:
В этом примере модель предсказывает "кошку", "собаку" и "мышь" с вероятностью 0,2, 0,75, 0,05 соответственно. Это можно рассматривать как распределение вероятностей по словарю Pvocab. Метки задаются вектором y с 1 в позиции, соответствующей целевому слову. Следовательно, принимая прогноз с наибольшей вероятностью, модель правильно предсказывает слово.
Словарный запас, как правило, составляет около 50 тысяч слов (~ 30 тысяч токенов для BERT). Следовательно, фактические векторы на самом деле намного больше, как показано ниже:
Функция потерь
Чтобы определить ошибку модели во время обучения, мы используем потерю перекрестной энтропии. Напомним, в мультиклассовой классификации с метками C потери на каждом обучающем примере определяются как:
Потерю каждого слова можно рассматривать как проблему классификации с классами C=размер словарного запаса. Для примера в (8) потери будут
Обратите внимание, что поскольку вероятность правильной метки стремится к 1, функция потерь стремится к 0, что указывает на то, что модель становится более точной.
На самом деле y будет действительно разреженным вектором со всеми нулями и только одной единицей в позиции, соответствующей позиции правильного слова в словаре, и потеря будет просто -log(y^).
Общая потеря для сгенерированного текста может быть рассчитана как среднее значение всех потерь отдельных слов.
Стратегии декодирования
Один из способов декодирования — всегда выбирать слово с наибольшей вероятностью на выходе. Но есть и другие способы, так что давайте посмотрим!
Сначала нам нужно обобщить то, что на самом деле находит модель. Учитывая входной текст x и выходной текст y, модель предсказывает вероятность P(y|x). Точнее, если Tx — количество слов на входе, а Ty — количество слов на выходе, модель предсказывает вероятность :
Предсказание первого токена определяется как P(y‹1›|x), а вероятность первых двух токенов определяется как
используя цепное правило вероятностей P(AnB) = P(A|B)P(B) = P(B|A)P(A). Для всей последовательности это становится:
И модель пытается предсказать последовательность слов y, которая максимизирует эту вероятность:
Теперь давайте посмотрим на различные стратегии декодирования!
Жадный поиск
Жадный поиск просто выбирает слово с наибольшей вероятностью в качестве следующего слова.
Начиная со слова "The", алгоритм жадно выбирает следующее слово с наибольшей вероятностью "nice"и так далее, так что окончательная сгенерированная последовательность слов будет («Эта»,«милая»,«женщина») с общей вероятностью 0,5×0,4=0,2.
Однако этот алгоритм пропускает слова с высокой вероятностью, скрытые за словом с низкой вероятностью. Здесь мы могли бы вместо этого предсказать "The", "собаку", "имеет" с более высокой общей вероятностью 0,4 x 0,9. =0,36
Жадный поиск также приводит к тому, что модель начинает повторяться. (Вы когда-нибудь пытались сломать предсказание следующего слова на своем телефоне?)
Поиск луча
Поиск луча сохраняет наиболее вероятное число гипотез num_beam на каждом временном шаге и в конечном итоге выбирает гипотезу с наибольшей общей вероятностью. Используя пример с num_beams=2:
На временном шаге 1 помимо наиболее вероятной гипотезы ("The", "хорошая") также отслеживается вторая наиболее вероятная гипотеза ("The", «собака»). Затем на временном шаге 2 он может найти ("The", "собака", "имеет") как последовательность с наибольшей вероятностью.
Примечание: в отличие от поиска в ширину поиск по лучу в глубину выполняется намного быстрее, но не гарантирует нахождения точного максимума для P(y|x).
Другие методы улучшения декодирования включают в себя такие вещи, как блокирование n-грамм — удаление опций, создающих уже существующую n-грамму; нормализация длины, поэтому модель не поддерживает короткие выходные данные; а также различные методы выборки.
Механизм внимания
Механизм внимания был введен в 2014, чтобы помочь улучшить перевод длинных предложений. Модели машинного перевода берут последовательность слов на одном языке и выводят последовательность слов на другом языке, поэтому это очень похоже на обобщение.
Давайте посмотрим на пример перевода французского предложения Je suis étudiant на английский язык. До сих пор мы видели:
Как оказалось, в приведенной выше модели вектор контекста оказался узким местом при декодировании длинных предложений. Был введен внимание механизм, позволяющий модели сосредоточиться на соответствующих частях входной последовательности по мере необходимости.
Давайте посмотрим, что происходит на первом шаге декодера после включения внимания. Теперь вместо того, чтобы просто передавать последнее скрытое состояние кодировщика, мы передаем их все. Веса внимания α рассчитываются для каждого скрытого состояния кодировщика, показывая важность каждого состояния и, следовательно, важность каждого слова (каждое скрытое состояние больше всего связано с определенным токеном во входных данных). Использование t' для обозначения входного (французского) временного шага предложения и t > для временного шага output (на английском языке) мы определяем
Сумма этих весов равна единице, поэтому их можно рассматривать как вероятности.
Новый вектор контекста рассчитывается как взвешенная сумма скрытых состояний с весами внимания:
В приведенной ниже визуализации временной шаг 4 на самом деле является первым временным шагом декодера (поскольку в этом примере в кодере 3 временных шага), а hᵢ является альтернативным обозначением для a‹t'› для скрытых состояний кодировщика (т.е. h1 = a‹1'›, h2=a‹2'›, h3=a‹3'›).
Вспомним в исходных уравнениях RNN
Для декодера a₁‹0› — это последнее скрытое состояние кодировщика, а x‹1› — вложение ‹EOS› токен. Теперь мы дополнительно используем вектор контекста дополнительного внимания (16) и объединяем его с текущим скрытым состоянием декодера:
Тот же процесс продолжается для всех других временных шагов в декодере, при этом веса внимания и, следовательно, вектор контекста пересчитываются на каждом временном шаге. В общем случае вектор контекста на временном шаге t определяется выражением
А веса внимания находятся следующим образом
Таким образом, чтобы эффективно найти веса внимания, вы передаете скрытые состояния кодировщика и текущие состояния декодера через другую нейронную сеть с прямой связью, которая учится вычислять веса.
Ниже приведена визуализация всего процесса декодирования с вниманием:
[Напомним, что в наших обозначениях у нас были бы скрытые состояния кодировщика: h1 = a‹1'›, h2=a‹2'›, h3=a‹3'› и скрытые состояния декодера: h4=a‹1›, h5 =a‹2› и контекстные векторы C4 = c‹1›, C5 = c‹2›.]
Концептуально внимание можно изобразить на следующей диаграмме:
Вы можете видеть, как модель правильно обращала внимание при выводе «Европейская экономическая зона». Во французском языке порядок этих слов обратный («европейская экономическая зона») по сравнению с английским. Другие слова в предложении в таком же порядке.
До сих пор мы говорили только о моделях перевода текста, поэтому давайте перейдем к делу и поговорим конкретно о суммировании текста. Давайте посмотрим, как внимание используется при подведении итогов:
В базовой модели Seq2Seq с вниманием модель может обращать внимание на соответствующие слова в исходном тексте для создания новых слов, например. для создания нового слова "победить" в абстрактном резюме "Германия обыграла Аргентину 2:0" модель может обратить внимание на слова "победоносно" и "win" в исходном тексте.
Обобщение с помощью сетей генераторов указателей
Теперь мы, наконец, готовы обсудить статью!
Было обнаружено, что обычная последовательность моделей с вниманием демонстрирует определенное нежелательное поведение, такое как неточное воспроизведение фактических деталей, неспособность обращаться со словами, не входящими в словарь (OOV), и повторение самих себя.
Сеть генератора указателей, представленная в этой статье, облегчает копирование слов из исходного текста с помощью указания, что улучшает обработку слов OOV, сохраняя при этом возможность генерировать слова. Вектор покрытия используется для отслеживания и контроля охвата исходного документа, что эффективно устраняет повторения.
Ниже приведен пример только что описанных проблем:
Сеть генераторов указателей
Это решает проблему для слов OOV.
Примечание: словарь модели обычно содержит несколько специальных токенов, например, токен ‹EOS›, а другой — ‹UNK›. Таким образом, модель может предсказывать слова OOV, если, например. наибольшая вероятность для токена ‹UNK›.
Для каждого временного шага декодера вычисляется вероятность генерации p_gen ∈ [0,1], которая взвешивает вероятность генерации слов из словаря по сравнению с вероятностью копирования слов из исходного текста. Распределение словарного запаса и распределение внимания взвешиваются и суммируются для получения окончательного распределения, на основе которого мы делаем наш прогноз.
Интуиция: когда мы декодируем и хотим предсказать слово OOV, не было бы неплохо, если бы мы могли вместо этого скопировать слово из исходного текста? Это именно то, что мы можем сделать — вместо этого мы можем скопировать слово с некоторой вероятностью 1-pgen на основе распределения внимания. Распределение копий, из которого копируются слова, может быть получено путем суммирования распределений внимания на слово.
Мы определяем расширенный словарь как объединение словаря и всех слов, встречающихся в исходном дистрибутиве. Распределение вероятностей расширенного словаря теперь:
Если w равно OOV, то Pvocab будет равно нулю, и вместо этого мы сможем скопировать новое слово из исходного документа, используя распространение копии. Это устраняет проблему невозврата токенов ‹UNK›. Точно так же, если w не появляется в исходном документе, Pcopy будет равно нулю, и мы сможем сгенерировать слово из словаря, как обычно.
Обратите внимание, что pgen вычисляется на каждом временном шаге декодера на основе вектора контекстаc‹t›, скрытого состояния декодера a‹t› и входных данных. x‹t› следующим образом:
Где векторы wc, wa, wc и скаляр bptr — обучаемые параметры, а σ — сигмовидная функция активации.
Механизм покрытия
Это решает проблему повторения слов в резюме. Теперь мы создаем вектор покрытия, чтобы отслеживать, на какие слова мы уже обращали внимание. Идея состоит в том, чтобы использовать это, чтобы наказать модель, чтобы она не обращала внимание на одни и те же слова в исходном тексте снова и снова. Мы определяем вектор покрытия как сумму внимания за все предыдущие временные шаги:
Интуитивно понятно, что d‹t› — это (ненормализованное) распределение по словам исходного документа, которое представляет степень охвата, полученного этими словами от механизма внимания на данный момент. Обратите внимание, что d‹1› — это нулевой вектор, потому что на первом временном шаге ни один из исходных документов не был покрыт.
Затем мы определяем дополнительную потерю покрытия, которая добавляется к функции потерь:
Интуиция: если вектор покрытия d показывает, что мы уже обращали внимание на это конкретное слово, тогда α должно быть небольшим, чтобы свести к минимуму потери, а α Быть маленьким означает, что мы не обращаем внимания на одно и то же слово. С другой стороны, если d низкое, мы можем безопасно иметь высокое значение α и обращать внимание на это слово, поскольку минимум по-прежнему будетd и потерь будет мало.
Обратите внимание, что вектор контекста также используется для расчета весов внимания путем добавления дополнительного члена к уравнению (21):
Результаты
Результаты были многообещающими:
- Модель стала лучше не повторять слова:
- Показатель Rouge увеличился в наборе данных CNN/Daily Mail:
Однако они обнаружили, что в результате модель стала более экстрактивной и не может генерировать абстрактные сводки:
Дальнейшая работа
В тесте данных CNN/Daily Mail мы видим в Papers with Code, что с использованием Pointer Networks были внесены некоторые дополнительные улучшения:
Однако, в целом, на разных наборах данных Трансформеры лидируют, а такие модели, как BART и PEGASUS, регулярно достигают самых современных результатов, но это тема для другого поста!
Ссылки/дополнительная литература:
- Модель внимания: https://jalammar.github.io/visualizing-neural-machine-translation-mechanics-of-seq2seq-models-with-attention/.
- Встраивания с помощью Wor2Vec: https://jalammar.github.io/illustrated-word2vec/.
- Генерация последовательностей в декодере: https://huggingface.co/blog/how-to-generate
- Курс Модели последовательности: https://www.coursera.org/learn/nlp-sequence-models?specialization=deep-learning
- Оригинальная статья Обобщение с помощью сетей генераторов указателей: https://arxiv.org/pdf/1704.04368.pdf.
Спасибо за прочтение!
Примечания: Я использовал этот конвертер mp4 в gif для вставки гифок. Я сделал уравнения с помощью редактора Overleaf Latex и вставил их как изображения.