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

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

В то время как в первой статье обсуждалось значение фиксированных синусоидальных абсолютных позиционных кодировок, в этой статье мы сосредоточимся на относительных позиционных кодировках. Мы также обсудим плюсы и минусы использования обучаемого позиционного кодирования. Попутно я предлагаю реализовать двунаправленное относительное позиционное кодирование, основанное на архитектуре Transformer-XL. Мне не удалось найти никого, кто бы это обсуждал, поэтому, пожалуйста, свяжитесь с нами, если вы можете пролить свет на то, занимался ли кто-нибудь этим.

Если и есть один вывод из этой статьи, связанный с TL; DR, то это так:

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

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

Раздел I (введение):

  • Зачем изучать относительные кодировки?
  • Как модель думает об относительных кодировках?

Раздел II (вычислительная техника):

  • Как построить относительную позиционную кодировку с учетом абсолютной.
  • Алгоритм O (n) для построения относительных позиционных кодировок.
  • Код для вышеупомянутого алгоритма и то, как вы можете сделать его двунаправленным.

Раздел III (обучаемые кодировки):

  • Почему вам следует вводить позиционную информацию прямо в логиты.
  • Плюсы и минусы обучаемых и фиксированных кодировок.
  • Корреляционная декомпозиция логитов Embedding-Position.

Раздел I (введение):

Позиция в повседневной речи

Быстрая викторина. Как бы вы ответили на следующий вопрос:

Где ближайший банк?

  1. Рядом с театром.
  2. На углу Первой и Главной улиц.
  3. На широте: 41,559599, долготе: 2,431680.

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

Контекстная позиция vs вычислимая позиция

Есть две основные причины, по которым «Рядом с театром» может быть приемлемым ответом. Первый,

«Рядом с театром» описывает относительное положение.

Если нам известно расположение театра, мы можем вычислить «рядом с» + «театр», чтобы добраться до нового места. Конечно, это кажется разумным, но как узнать положение театра? Разве мы не сказали, что позиция нечетко определена? Верный. Это подводит нас ко второму пункту:

Каждый ответ несет в себе контекстную информацию, в том числе текущую позицию обоих людей в разговоре.

Когда я отвечаю «Рядом с театром», подразумевается, что человек, задающий вопрос, знает, где я. Это контекстная информация. У спрашивающего, в свою очередь, также есть своя контекстная информация. Говоря повседневным языком, мы по умолчанию вычисляем позиции относительно нашей собственной позиции. Это придает положению четко определенный смысл: положение всегда относительно.

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

Даем модели абзац и просим вычислить местонахождение банка. Допустим, мы скормим ему предложение:

«Банк находится недалеко отсюда. Он находится рядом с театром ».

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

  1. Найдите в хеш-таблице Location["here"]=0. Помните, что люди используют относительное позиционное кодирование, поэтому машина узнала, что положение «здесь» равно нулю.
  2. Найдите в хэш-таблице операцию Operation["next to"]=lambda x: x+1, которая просто добавляет расстояние 1 к любой позиции.
  3. Найдите в хеш-таблице Location["next to"]=street_pos.
  4. Вычислить Location["bank"] = Operation["next to"](Location["theater"]["here"]).

Шаг 4 - ключевая часть. Все остальное выучить несложно. Это просто значения хеш-таблицы. Фактически, вы могли бы просто жестко закодировать их в модель и на этом закончить. Шаг 4, однако, требует логики, которую гораздо сложнее запрограммировать жестко. Прежде чем перейти к этому, давайте резюмируем то, что мы видели, используя наши предыдущие термины, выделенные жирным шрифтом.

Предложение 1 - «Банк недалеко отсюда» - это контекстная информация. Из всех возможных значений « theatre» в хэш-таблице Location["theater"] он говорит нам, что нужно использовать именно то, которое находится «здесь».

Предложение 2 - «Это [банк] рядом с театром» - это реальный ответ, который слышит спрашивающий. Он содержит относительную позиционную информацию, связывающую местонахождение «банка» с местонахождением «театра».

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

От абстрактной позиции к фактическим позициям в последовательности

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

Теперь мы собираемся обсудить позиции с точки зрения местоположения в последовательности. На шаге 4 нашего мысленного эксперимента наша модель должна была выяснить, как сложить набор чисел для вычисления местоположения [«банка»]. Грамматику можно рассматривать как набор (часто нарушенных и непоследовательных) правил, предназначенных для того, чтобы взять набор слов и присвоить им значение в зависимости от их положения в последовательности. Например, возьмем предложение:

«Я живу, чтобы есть».

Это выражает любовь говорящих к еде. Они бы умерли, если бы не могли есть (что, я думаю, не только гиперболически, но и буквально…). Грамматика говорит нам, что глагол «есть» - это цель жизни. Итак, вы можете представить модель, которая учится: «Когда вы видите структуру« глагол »+« to », слово в позиции index [« глагол »] + 2 описывает назначение глагола».

Действительно, давайте поменяем два глагола на запись:

«Я ем, чтобы жить».

Теперь мы получаем противоположный смысл! Говорящий подразумевает, что он не любит еду и ест только для того, чтобы продолжать жить. Однако это все еще соответствует изученной нами грамматической модели! index [‘eat’] + 2 = index [‘live’] по-прежнему работает, жить здесь - это цель еды.

Модель действовала как человек. Он занял свою собственную позицию (индекс [‘eat’]) и обработал ее как позицию «абсолютного нуля». Затем он сказал: «Эй, меня волнует только то, что находится на 2 шага впереди меня», что в данном случае было index ['live']. Для расчета модели требовалось только относительное положение.

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

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

Раздел II (вычислительная техника):

Относительно абсолютной кодировки: простой начальный пример

Давайте начнем с простого примера, чтобы понять, что происходит. Рассмотрим одномерную последовательность со следующим вектором абсолютного позиционного кодирования (буква A для абсолютного)

Если бы я спросил вас, каково положение между любыми двумя точками A_i и A_j, представленными функцией расстояния d (A_i, A_j) , мы надеемся, что ответ должен быть очевиден: d (A_i, A_j) = | A_i-A_j | = | i-j |. Наша задача не в вычислении относительного положения, а в том, чтобы представить вычисленное нами относительное положение. Поскольку существует n возможных позиций, существует возможных пар позиций A_i и A_j. Это предполагает, что наша относительная кодировка должна быть матрицей (n, n). Обозначим относительное кодирование матрицей R (R - относительное). Затем мы можем учесть все возможные относительные положения, заполнив поля R в соответствии с формулой

Помните, что если буква не выделена жирным шрифтом, она представляет только скалярное значение, поэтому это уравнение для каждой из n² записей. Фактическая матрица теперь выглядит так

Обратите внимание на нули на диагонали, которые означают, что относительное положение индекса по отношению к самому себе равно нулю. Эта конкретная матрица известна как циркулянтная матрица, которая является частным случаем более общего класса матриц, называемых матрицей Теплица. Если бы мы ослабили условие симметрии A _i-A_j = A_j-A_i, нижние диагонали были бы отрицательными, поэтому матрица была бы только теплицевой. Вы знаете, что получаете матрицу Теплица, когда каждая диагональ постоянна. Основная диагональ - это все 0, следующая - все 1, следующая - все 2 и т. Д. Очень желательно получить матрицу Теплица, так как это значительно упростит последующие вычисления.

Мы замечаем, что во всей матрице (n, n) есть только n уникальных значений. Это (0, 1,…, n-1). Таким образом, матричное представление сильно избыточно. Мы также замечаем, что эти уникальные значения полностью представлены элементами вектора абсолютного кодирования A плюс значение 0. Таким образом, мы постулируем, что мы должны иметь возможность определять R, только манипулируя матрицей A, что предполагает, что мы можем сформировать R за O (n) вычислений, а не за O (n²). Все зависит от того, что наша матрица R действительно теплицева. Однако обратите внимание, что если значения последовательности не были равномерно распределены, например у нас было что-то вроде A = (1, 2, 5, 6, 9,…, n). Тогда мы бы НЕ открыли матрицу Теплица (вычислите одну диагональ, чтобы убедить себя, например, A_3-A_2! = A_2-A_1).

Это говорит о том, что если нам нужна матрица относительного кодирования Теплица (что мы определенно делаем), наш вектор абсолютного позиционного кодирования должен удовлетворять любому из двух условий. Во-первых, все его значения расположены на одинаковом расстоянии, как это было в нашем простом примере. Но мы знаем из Части I, что наши абсолютные позиции не будут простыми целыми числами, а будут неким сложным d_model-мерным вектором. Удовлетворять первым условиям - непросто. Второе условие - требовать, чтобы каждая запись вектора абсолютного позиционного кодирования фактически представляла фиксированные относительные позиции.

Хорошо, я знаю, что это может не иметь никакого смысла, поэтому рассмотрите это объяснение. Предположим, что в мире есть 3 позиции, называемые X, Y и Z. Мы предполагаем, что они расположены на одинаковом расстоянии, что бы это ни значило, и последовательно, но на самом деле мы не можем измерить их абсолютные положения. Что мы можем измерить, так это результат некоторой функции расстояния d (X, Y) = NUMBER. Мы можем найти что-то вроде d (X, Y) = 2, d (X, Z) = 6, d (Y, Z) = 2, и остальные 0. Единственное, что это функция расстояния. необходимо выплюнуть d (x, x) = 0, d (x, y) = d (y, x) и убедиться, что если (XY) ›(ZT), то d (X, Y)› d (Z, T). Другими словами, чтобы успешно описать позиционное кодирование, нам просто нужно указать относительные положения каждого элемента в последовательности, вызвать это | ij |, а затем вычислить фиксированное значение R (| ij |), которое сигнализирует тому, кто прочитает значение насколько близки i, j. В этом примере, если мы введем R (| i-j |) = 6, наша модель узнает, что 6 подразумевает разделение на 2!

Все это - много слов для того, что можно кратко записать в виде определения уравнения:

Это наше определяющее уравнение для относительного позиционного кодирования.

Все, что мы сделали, это переместили | i-j | в индекс A. Это крошечное изменение, но оно влечет за собой более масштабное концептуальное изменение. Последнее, что мы упоминаем в этом подразделе, это то, что матрица относительного позиционного кодирования имеет более высокий ранг, чем вектор абсолютного позиционного кодирования, из которого она была получена. Это общая особенность. Относительная кодировка всегда будет на единицу выше ее абсолютной кодировки. Для одномерного случая это означает, что мы получаем вектор и матрицу. Помимо этого, мы получаем тензор ранга k и тензор ранга (k + 1). Мы исчерпали полезность игрушечных примеров, поэтому перейдем к позиционному кодированию в реальной жизни.

Фиксированный синусоидальный тензор относительного положения

Прежде чем создавать инструмент, обычно полезно знать, для чего он будет использоваться. В этом случае давайте рассмотрим модель внимания. Причина, по которой нам нужно позиционное кодирование, заключается в том, чтобы дать механизму внимания ощущение положения элементов в последовательности, на которую он обращает внимание. Внимание представлено матрицей M из логитов, где запись M_ {ij} дает логическую вероятность того, что данный запрос с индексом i соответствует с ключом в индексе j. Обратите внимание, что размеры матрицы логитов (seq_len, seq_len). Это как раз размеры R, что имеет смысл. Логиты сравнивают вещи в одной позиции с другой. Таким образом, для нас имеет смысл напрямую вводить позиционную информацию в логиты нашей модели, и это действительно будет нашей целью. Мы будем называть эти позиционные логиты просто позиционными логитами.

Мы принимаем язык моделей внимания и рассматриваем две последовательности: запрос, индексы которого являются индексами строк R, и ключ, чьи индексы являются индексами столбцов R. . M_ {ij} = q_i точка k_j. Без потери общности мы также можем предположить, что длина запроса меньше или равна длине ключа.

Как и в нашем начальном случае, для работы нам нужна фиксированная абсолютная позиционная кодировка. Для этого мы используем ту же фиксированную синусоидальную кодировку, которая подробно обсуждается в Части I этой серии. Это матрица A формы (query_len, d_model), которая может быть представлена ​​в виде списка векторов A = (a _0,… , a _ {n-1}), где a _i - это i -я строка строки A, а размерности d_model. Написав это таким образом, мы видим, что единственное отличие от нашего простого начального примера состоит в том, что все элементы A теперь выделены жирным шрифтом (что означает векторы). Это предполагает, что мы можем сразу же считать матричную форму R:

Однако это верно только в том случае, если длина запроса, которую мы обозначаем n,, равна длине ключа m. В этот момент вы можете спросить: Почему длина запроса никогда не будет равна длине ключа? И разве я не мог бы просто использовать обивку, чтобы разобраться с таким случаем? " Чтобы ответить на этот вопрос на примере, именно такая ситуация возникает при реализации «Transformer XL, когда мы рассматриваем состояния памяти, которые находятся дальше в прошлом, чем текущая длина запроса. Есть два варианта сравнения запросов и ключей разной длины:

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

Обратите внимание, что если бы мы увеличили длину запроса до длины ключа, мы бы получили размерную матрицу (n , n) , форма которой правильно задана предыдущим уравнение. Каждый из двух вариантов на самом деле является подмножеством этой большой матрицы. В первом варианте мы вычисляем полную матрицу (n, n), затем удаляем первые n-m строк, оставляя матрицу (m, n). Второй вариант вычисляется аналогично, вместо этого удаляются последние столбцы n-m. Теперь предположим, что мы работаем с матрицей (n, n), а затем при необходимости усечем ее в соответствии с требуемым направлением времени.

Мы собираемся показать, как тензор R может быть вычислен за O (n) операций серией сдвигов влево и вправо тензора A _i 1 _j = R _ {i, 0}, где индексы предназначены для того, чтобы помочь вам понять тензорную структуру. Это просто набор повторов одной уникальной матрицы A. Алгоритм сводится к следующему простому примеру: найти операцию, которая выполняет:

Я буду ссылаться на номера строк через нулевую индексацию. Мы замечаем, что если мы сдвинем строку вправо один на 1, строку два на 2 и строку три на 3, то мы правильно воспроизведем правую верхнюю диагональ. Теперь предположим, что мы перевернули все позиции i → -i. Это эквивалентно переворачиванию левой матрицы влево-вправо.

Затем мы могли бы выполнить обратную процедуру; сдвиньте влево строку два на 1, строку один на 2, затем строку с нулем на 3, и мы правильно воспроизведем нижнюю левую диагональ. Комбинируя эти две операции и маскируя неправильные части каждой из них, мы можем успешно построить наш тензор R!

Перед написанием этого алгоритма давайте обсудим, что он вычисляет. Левая нижняя диагональная часть состоит в точности из всех элементов с индексом j≤i. Другими словами, левая нижняя диагональ представляет все пары ключ-запрос, в которых запрос касается ключей, которые встречаются раньше. Правая верхняя диагональ состоит из всего противоположного, где запрос относится к клавишам позже раз. Надеюсь, это поможет дополнить нашу предыдущую диаграмму, на которой обсуждается течение времени.

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

Если мы реализуем декодер, которым является Transformer-XL, тогда нам нужно вычислить только левые нижние диагональные позиционные логиты; правые верхние компоненты являются мусором и в любом случае будут замаскированы. Однако в их статье не рассматривается идея двунаправленности. Поскольку мы знаем, как вычислять относительные положения как для левого, так и для правого направлений, нетрудно создать двунаправленный трансформатор XL.

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

Также несложно вычислить относительные позиционные логиты для всех записей, что позволит запросам обрабатывать прошлые, настоящие и будущие ключи. Двунаправленные преобразователи весьма полезны, например, BERT является известным примером, и мне любопытно узнать, можно ли повысить производительность за счет использования двунаправленного фиксированного относительного позиционного кодирования. Если читатель знает, оставьте, пожалуйста, комментарий! Я делаю акцент на фиксированном, потому что, как мы увидим, вы можете довольно легко включить изученные двунаправленные относительные кодировки, и это то, с чем люди экспериментировали.

Вычисление логитов положения: исследование и настройка модели

Будет намного проще вычислить позиционные логиты, если мы сначала сможем описать, что именно мы вычисляем. Мы начинаем с записи всех вкладов в ванильный уровень внимания с абсолютными позиционными кодировками, затем исследуем, какие вклады необходимо «относить». Мы будем использовать следующие обозначения

Веса W - это обычные веса для преобразования наших вложений / позиций в ключи / запросы. Обычно мы получаем вложение E и позиционное кодирование U, а затем суммируем их в качестве входных данных. Теперь находим логиты внимания M:

Мы используем аналогичный символ «~», поскольку есть коэффициент нормализации sqrt (d_model), который не имеет отношения к текущему обсуждению. Термины в каждой строке описывают различные типы корреляций, которые модель может усвоить. В следующем разделе мы расскажем об этом подробнее. На данный момент мы просто запрашиваем, чтобы матричный элемент M_ {ij} зависел только от позиционной информации U_ {i-j} = R_ {i, j}. Это так же просто, как просто заменить U_j → U_ {i-j}.

Затем мы замечаем, что строки 2 и 3 несколько избыточны. Мы сохраняем строку 2 и используем ее для определения локальных корреляций между E и U. Затем мы адаптируем строку 3 для использования общего (для всех ключей, также повторяющегося в каждой строке) вектора u _i вместо U _i W _ {q, U}. В результате сохраняется глобальный вектор контекста, указывающий, как встраивание связано с позициями с учетом всего того, что мы видели в прошлом. Вы можете думать об этом как о модели, которой разрешено изучать тему разговора. Если в последнее время стали появляться слова, связанные с деньгами, то эта статья может побудить модель интерпретировать слово «банк» как относящееся к финансовым учреждениям, а не к берегу реки.

Последняя строка содержит корреляции позиция-позиция. Обычно, если бы эти параметры были изученными, мы ожидаем, что они будут просто воспроизводить фиксированные позиционные кодировки, которые мы уже предоставили. Лучше использовать этот термин, чтобы трактовать его аналогично строке 3. Мы заменяем v_i вместо U _i W _ {q, U}, который выполняет роль вектор глобальной позиции, отслеживающий нашу глобальную позицию. После этих замен имеем:

Второй член - это то, что мы сейчас пытаемся вычислить.

Код и алгоритм

Алгоритм такой же, как и раньше. Только сейчас у нас есть конкретная вещь, на которую стоит обратить внимание. Для наших целей мы можем сгруппировать все, что находится слева от U, в единую матрицу q_i, так что член, который мы хотим вычислить, равен q _i U _ {ij} ^ T. Начнем с левых сдвигов. Проще сначала показать алгоритм на диаграмме, а затем попытаться объяснить его.

Я подумала, что было бы весело использовать фигуры вместо чисел. Черные звезды обозначают отступы. Численно они эквивалентны 0. В конечном итоге мы хотим сдвинуть влево 2-ю строку на последнюю на одну, 3-ю на последнюю на две строки и т. Д. Мы начинаем с жадного выбора. Возьмите жетон нижней левой панели и переместите его со 2-го до последнего ряда. Это автоматически реализует сдвиг влево, заставляя все остальные элементы в этой строке перемещаться влево по одному. Однако это, в свою очередь, перемещает первый элемент (черная звезда) во второй строке до последней, чтобы некуда было идти, а также заставляет перемещаться один из зеленых кружков, так как теперь он выходит за рамки матрицы. В результате теперь мы должны переместить одну черную звезду и один зеленый кружок на красный ромбовидный ряд. Это, в свою очередь, вытесняет красные бриллианты, оставляя три части, которым некуда деться! Но мы замечаем, что остальная часть матрицы теперь правильно сдвинута влево. Если бы только мы могли избавиться от этих надоедливых оставшихся форм ...

Мы можем. И тоже довольно легко. Вам просто нужно преобразовать матрицу в матрицу с 3 столбцами и удалить первую строку. Выполнено. Если вы вернете ему правильную форму, все будет сдвинуто влево. В дальнейшем мы предполагаем, что входной тензор имеет форму (N, T, Q, K). Вот шаги алгоритма:

Если время увеличивается слева направо:

  1. Поменяйте позиции. Это можно сделать как tf.reverse(U, [2]) или для матриц как np.flipud(U).
  2. Выполните скалярное произведение q _i U _j ^ t.
  3. Слева заполните результат столбцом единиц. Для тензора формы (N, T, Q, K) это означает левую площадку на четвертом и последнем измерении K.
  4. Измените форму до размера (N, T, K + 1, Q).
  5. Снимаем первый ряд.
  6. Преобразуйте в окончательный ответ формы (N, T, Q, K).

Если время увеличивается справа налево:

  1. Не меняйте позиции. Если длина ключа больше длины запроса, удалите последние (klen-qlen) строки U. Выполните скалярное произведение, как на шаге 2.
  2. Нажмите правую кнопку для четвертой и последней позиции. Выполните то же изменение формы
  3. Вместо этого обрежьте последнюю строку.
  4. Если U был изначально усечен, оставьте заполнение таким количеством столбцов, сколько удаленных строк. Изменить форму до окончательного ответа.

Если время двунаправленное:

  1. Вычислите маску, взяв верхнюю и нижнюю диагонали матрицы единиц (klen, klen).
  2. Вычислите левый и правый логиты соответственно, а затем объедините их с масками.

Ниже мы представляем код в NumPy. По большей части это можно превратить непосредственно в TensorFlow, заменив np → tf, но мы подумали, что было бы проще избежать сложностей, связанных с пакетированием и измерениями многоголового внимания. np.triu и np.tril преобразуются в tf.linalg.band_part.

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

Correct answer:
 [[ 5.18 -2.58  1.54 -2.58  5.18]
 [ 0.18 -2.39  0.91 -1.    0.91]
 [-4.05  3.41  1.86 -0.6  -4.53]]
Shifted algorithm:
 [[ 5.18 -2.58  1.54 -2.58  5.18]
 [ 0.18 -2.39  0.91 -1.    0.91]
 [-4.05  3.41  1.86 -0.6  -4.53]]
Match? True

Раздел III (обучаемые кодировки и сравнение):

Выученные вложения

До сих пор (почти) все, что мы делали, включало определяемые пользователем фиксированные позиционные кодировки (я говорю почти потому, что мы добавили те глобальные векторы контекста / положения в Разделе II, которые были изученными параметрами). Это хорошо. Если с этим мы сможем добиться хорошей производительности, это будет быстрее и стабильнее, чем позволить модели самой изучать эти параметры. Однако если есть одна вещь, о которой нам постоянно напоминает глубокое обучение; компьютер, вероятно, может сделать это лучше.

Свертки уже давно используются при обработке изображений, однако при построении сетей компьютерного зрения мы позволяем компьютеру решать, какие типы сверток он будет создавать. На практике это работает намного лучше. Так почему бы не применить здесь тот же подход? Почему бы не позволить компьютеру выучить свои собственные позиционные кодировки? В этом разделе мы обсудим некоторые подходы в этом направлении.

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

Хотя эти 4 термина были получены в результате добавления позиционного кодирования U к встраиваемому вектору E, мы ни в коем случае не обязаны строить логиты таким образом. Вместо этого это дает нам представление о типах вкладов в матрицы логита. В принципе, есть три типа

  1. Вложение-вложение корреляции. Дано строкой 1.
  2. Корреляции встраиваемых позиций. Дано строками 2 и 3.
  3. Позиционно-позиционные корреляции. Задано строками 4.

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

Корреляция позиции внедрения указывает, совпадают ли некоторые слова с абсолютной позицией ключа / запроса. Априори мы этого не ожидали. Если я говорю "привет", оно не должно менять значение в зависимости от того, 2 февраля или 18 июля сегодня. Вместо этого мы часто определяем значение слова на основе его относительного положения. Это намекает на то, что мы можем захотеть заменить эти термины чем-то более «относительным». Опять же, мы уже показали, как их можно обновить с помощью фиксированных относительных кодировок, но здесь мы думаем о добавлении обучаемых параметров.

Наконец, в последней строке у нас есть корреляции между позициями. Надеюсь, модель научится воспроизводить что-то вроде матриц Теплица, с которыми мы работали вручную. Это указывало бы на то, что модель учится осмысленным позициям.

Давайте сначала займемся вложением-позиционными корреляциями. Самый простой способ определить, актуальны ли эти корреляции, - это просто измерить их. В статье Guolin Ke, Di He & Tie-Yan Liu (2020) они анализируют изученные матричные корреляции предварительно обученной модели BERT и разбивают полученные в результате полученные корреляции. Они находят следующие диаграммы,

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

В качестве примечания отметим, что этот вывод сделан на основе предположения, что размеры ключа и запроса одинаковы. В таком контексте, как Transformer-XL, возможно, что существует глобальная позиционная или контекстная информация, которая может распространяться в сети. В этом случае было бы неразумно отказываться от этих взносов.

Эти замечания приводят нас к первой догадке относительно обучаемого позиционного кодирования. Сначала мы решаем внедрить нашу позиционную кодировку в сеть напрямую через позиционные логиты. Затем мы выбираем следующую форму для этих логитов:

где, как было предложено, мы удалили материал, связанный с позиционным встраиванием, и превратили элемент положение-позиция в нечто доступное для изучения. Это представление было одной из первых попыток расширения позиционного кодирования до логитов и было представлено в статье Shaw et. al. (2018) . Есть одно небольшое различие между этим и простым добавлением в логиты обучаемой матрицы. Мы ограничили форму позиционных логитов, обозначенных здесь альфа, тёплицевыми. В результате мы фактически вдвое сократили доступные параметры, связав веса. Это гарантирует, что модель должна обрабатывать позиции симметрично; расстояние d (x, y) должно равняться d (y, x). Актуальная модель Shaw et. al. (2018) немного сложнее, но это общая идея.

По сравнению с нашим методом фиксированного позиционного кодирования, он не так гибок при работе с длинными последовательностями. Поскольку позиционные логиты являются параметрами обучения, они не могут быть скорректированы после обучения модели и ограничиваются любым размером после обучения. Авторы осознали эту проблему и предложили для ее решения реализовать отсечение позиции. За пределами определенного расстояния относительные положения обрезаются до максимального значения k.

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

Есть еще один подход, который мы можем использовать, это компромисс между сохранением всех терминов логита позиционного кодирования и сохранением ограниченного класса с привязанными весами. В статье Guolin Ke, Di He & Tie-Yan Liu (2020) они предлагают использовать логиты

Как они показывают, последние два термина не имеют перекрывающейся выразительности. Это дает модели большую репрезентативную силу. Например, модель может научиться использовать абсолютные вложения для определения смещения, а затем относительные вложения для точной настройки положения.

Одним из преимуществ обучаемых позиционных кодировок перед фиксированными является гибкость в работе с непоследовательными вставками в данные. Например, рассмотрим цель обучения BERT. Мы отложили специальные токены [CLS] и [SEP], чтобы обозначить значение предложения и разделение соответственно. Последние имеют четко определенное позиционное значение, а первые - нет. Выученная позиционная кодировка может справиться с этим, «развязав» токен [CLS]. Ke et. al. (2020) рассматривают этот конкретный случай, перемещая токен [CLS] в нулевой последовательный слот и предоставляя ему свой собственный общий параметр theta. Этот параметр одинаков для всех других токенов, указывая, что токен [CLS] одинаково «далеко» от всех других токенов. В противном случае возникло бы предубеждение, чтобы научиться придавать ранним токенам последовательности больший вес [CLS].

Заключение

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

Мы показали, что до тех пор, пока сеть имеет надежный набор значений расстояния между двумя точками в последовательности, она может использовать это для вычисления относительных положений. Это позволило нам построить тензоры относительного кодирования Теплица, переработав наши уже с трудом заработанные знания об абсолютных позиционных кодировках. Кроме того, благодаря особым свойствам Теплица наших кодировок, мы смогли найти способ вычислить логиты относительного положения за время O (n). Мы представили код для этого, а также обсудили расширения как правых последовательностей, так и двунаправленных относительных кодировок.

Наконец, мы сравнили наши фиксированные синусоидальные кодировки с использованием изученных параметров. Преимуществами фиксированного кодирования являются скорость, гибкость длины последовательности и встроенная надежная модель количественного определения положения. Встроенные кодировки также могут использовать преимущества моделей с разными размерами ключевого запроса. Их также можно преобразовать в гибридную форму, в которой некоторые изучаемые параметры выделены для хранения глобального контекста и позиционной информации. Для сравнения, модель изученных параметров имеет простое представление, а также свободу позволить модели решать, как сравнивать последовательности. Уникальное преимущество удержания обучаемых параметров заключается в работе с непоследовательной информацией, такой как специальные токены, у которых нет / не должно быть четко определенной позиции. Их можно обработать путем развязывания весов и резервирования специальных обучаемых параметров для непоследовательных токенов.

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

использованная литература

  1. Васвани, Ашиш и др. «Внимание - это все, что вам нужно». Препринт arXiv arXiv: 1706.03762 (2017).
  2. Шоу, Питер, Якоб Ушкорейт и Ашиш Васвани. «Самовнимание с относительными представлениями положения». Препринт arXiv arXiv: 1803.02155 (2018).
  3. Дай, Зиханг и др. «Transformer-xl: внимательные языковые модели вне контекста фиксированной длины». Препринт arXiv arXiv: 1901.02860 (2019).
  4. Кэ, Гуолинь, Ди Хэ и Тие-Ян Лю. «Переосмысление позиционного кодирования в предварительном обучении языку». Препринт arXiv arXiv: 2006.15595 (2020).
  5. Раффель, Колин и др. «Изучение ограничений трансферного обучения с помощью унифицированного преобразователя текста в текст». Препринт arXiv arXiv: 1910.10683 (2019).