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

  1. Зачем нам это нужно?
  2. Какие еще есть альтернативы?
  3. Каковы характеристики идеального позиционного вложения?
  4. Как я могу интуитивно понять это?

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

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

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

  1. Я хочу, чтобы позиционные кодировки (PE) были уникальными для каждой позиции.
  2. Он должен быть детерминированным и зависеть только от позиции, а не от слова/контекста.
  3. Он должен быть обобщаемым; независимо от длины предложения.

С четвертым я, честно говоря, был в тупике. Я не мог придумать логичного объяснения. Я попытался упростить задачу, изолировав вклад каждой независимой переменной.

Независимые переменные в PE
pos: это довольно интуитивно понятно, так как PE должен зависеть от позиции слова
i : битовая позиция для введения различных циклов/частот повторения
d_model : WE размерность=512
omega : для обеспечения уникальности позиционных кодировок. будет равно 10000

При первичной проверке функция PE состоит из вектора пар sin/cos, который зависит как от позиции слова, так и от позиции бита. Он имеет знаменатель, равный 10000, который мы будем называть омегой.

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

  1. Почему нам нужен вектор для определения позиции слова, а не просто одно число?
  2. Зачем использовать пары синус/косинус для представления PE?
  3. Почему мы суммируем WE (встраивание слов) + PE (позиционное встраивание), а не объединяем их?
  4. Почему мы говорим, что начальные биты зарезервированы для PE, а последующие — для WE?
  5. Почему нам нужно, чтобы омега/знаменатель был равен 10000?

Зачем нам вектор?

Давайте посмотрим, что произойдет, если мы представим позиции в виде одного числа. Возьмите следующие примеры предложений

Мне нравится машинное обучение.

Я изучаю трансформеры и модели внимания.

Метод 1: представить позиции в виде числа с плавающей запятой от 0 до 1.

PE для предложения 1 будет I-0,25, любовь-0,5, машина-0,75, обучение-1,0.

PE для предложения 2 будет I-0,125, am-0,25, обучения-0,375, about-0,5, трансформаторы-0,625,и-0,75,внимание-0,875,модели-1,0

Модель столкнется с трудностями при обучении, поскольку дифференциал положения слова несовместим. Представление также противоречит здравому смыслу, поскольку представление для позиции-1 в обоих предложениях отличается, но должно быть таким же, как у них есть позиция. В идеале PE не должен зависеть от длины последовательности.

Метод 2. Представление позиций в виде целых чисел

PE для предложения 1 будет I-1 любовь-2, машина-3, обучение-4

PE для предложения 2 будет I-1, AM-2, Learning-3, About-4, Transformers-5,A-6,Внимание-7,Models-8

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

Решение. Используйте фиксированное детерминированное векторное представление.

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

Зачем использовать пары sin/cos для представления позиционных кодировок?

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

  1. синусоидальные волны демонстрируют близость в векторном представлении относительно небольших изменений положения. Другими словами, косинусное сходство между PE(pos) и PE(pos+1) будет больше, чем PE(pos) и PE(pos+10). Вы можете перейти к коду в конце, чтобы проверить то же самое.
  2. Они облегчают внимание к относительным позициям из-за их свойства вращения. Это означает, что sin(w+k)/cos(w+k) можно представить как повороты sin(w)/cos(w). Со слов автора

Это просто означает PE(pos+k) = num_var * PE(pos), где num_var не зависит от pos.

Это связано с аддитивным свойством синусоидальности.

Вы можете просмотреть этот блог для подробных доказательств этого свойства.

Почему мы суммируем WE (встраивание слов) + PE (позиционное встраивание), а не объединяем их?

Предполагать

Q: запрос
K : ключ
x : вектор запроса
px : позиционное вложение для слова запроса
y : вектор ключа
py : позиционное вложение для ключевого слова

Метод-1 будет учитывать влияние объединения PE и WE, а метод-2 учитывает тот факт, что PE и WE суммируются.

Метод 1: Q(x|px).K(y|py)где | символизирует конкатенацию

В этом случае WE x взаимодействует с WE y, а PE x взаимодействует с PE of y, в то время как нет перекрестных взаимодействий между x и py или y и px.

Метод 2: Q(x+px).K(y+py)

Это можно расширить как
Q(x).K(y) + Q(x).K(py) + K(y).Q(px) + Q(px)K(py)

который отвечает на следующие вопросы

  1. насколько модель должна уделять внимание x при заданном y [также будет присутствовать в методе 1]
  2. насколько модель должна обращать внимание на x при условии, что y находится в положении py
  3. насколько модель должна обращать внимание на y, если x находится в позиции px
  4. насколько модель должна обращать внимание на x в позиции px при условии, что y находится в позиции py [также будет присутствовать в методе 1]

Поскольку WE трансформаторов обучаются с нуля, возможно, что трансформаторы резервируют начальные биты для PE, а более поздние — для WE. А поскольку имеются пропущенные соединения, PE/WE может распространяться на последние уровни.

Почему мы говорим, что начальные биты зарезервированы для PE, а более поздние — для WE?

Частота приведенной выше волны синуса/косинуса зависит как от позиции слова, так и от бита 2*i d-мерного вложения.

Предположим, что день d_model=512,pos=1, тогда для i=1 частота будет 0,97, а для i=256 — 0,0001.

  1. Более ранние биты будут иметь более высокие частоты, следовательно, более высокие циклы повторения. Более поздние биты имеют более низкие частоты и будут ограничены либо 0, либо 1. Например, последний бит (i = 256) потребует, чтобы предложение с ~ 10k + 1 словами имело такое же вложение или имело повторяющийся цикл. Мы также можем связать это с тем, почему более ранние биты в WE+PE (слово+позиция) зарезервированы для PE. Более поздние биты могут использоваться исключительно WE, поскольку PE не хранит там никакой ценной информации.
  2. Я думаю, что зарезервированные биты для PE в PE+WE зависят от омеги. Если омега мала, почти все биты будут иметь повторяющиеся циклы, а если она большая, почти все биты будут либо 0/1. В первом случае PE будет использовать больше битов в PE+WE, а в последнем случае они будут использовать меньше битов для PE. Маленькая омега может привести к тому, что разные позиции слов будут иметь одинаковую кодировку, чего можно избежать с большими значениями, поскольку омега = 10k.
  3. Разрешив модели доступ к разным частотам, я думаю, что модель может выбрать, какие частоты важнее для ее изучения. Но это только моя гипотеза, могу ошибаться.

Почему нам нужно, чтобы знаменатель был равен 10000?

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

Код

Реализовать PE в numpy очень просто. Я добавил комментарии везде, где я чувствовал, что требуется объяснение.

Та же реализация в pytorch выглядит следующим образом

Заключение

Для тех, кому блог показался слишком длинным, вот суть

  1. Поскольку сети, основанные на чистом внимании, устранили повторение, возникла необходимость вводить в модель информацию о местоположении. Это делается с помощью PE.
  2. Нам нужна циклическая функция для PE, поскольку ваши предложения не являются монолитной структурой, а состоят из повторяющихся циклов, в которых позиции слов могут быть связаны на k позиций. Вот почему используются синусоидальные функции.
  3. Функция PE включает в себя позицию слова и бита. Позиция слова используется, чтобы убедиться, что разные позиции слов имеют уникальные кодировки. Зависимость от позиций битов создает повторяющиеся циклы с разной частотой, что помогает модели учитывать относительные позиции. Для любого фиксированного смещения k PE(w+k) будет линейной функцией PE(w).

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

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

  1. Отличный блог на тему Позиционное кодирование от Amirhossein
  2. Обсуждение Reddit по позиционному кодированию
  3. Пост Тимо Денка о доказательстве линейной зависимости между PE(pos) и PE(pos+k)
  4. Внимание — это все, что вам нужно

Подпишитесь на DDIntel Здесь.

Присоединяйтесь к нашей сети здесь: https://datadriveninvestor.com/collaborate