>>1.00<<>>1.00<<Видео проигрыватель загружается.Воспроизвести видеоВоспроизвестиБез звукаТекущее время 0:00/Продолжительность 8:14Загрузка: 0.00%0:00Тип потока ОНЛАЙНSeek to live, currently behind liveОНЛАЙНОставшееся время -8:14 1xСкорость воспроизведения2x1.75x1.5x1.25x1x, выбрано0.75x0.5xГлавыГлавыОписанияОтключить описания, выбраноСубтитрынастройки субтитров, откроется диалог настройки субтитровСубтитры выкл., выбраноЗвуковая дорожкаPicture-in-PictureПолноэкранный режимThis is a modal window.Начало диалоговго окна. Кнопка Escape закроет или отменит окноТекстColorБелыйЧерныйКрасныйЗеленыйСинийЖелтыйПурпурныйГолубойTransparencyПрозрачностьПолупрозрачныйФонColorЧерныйБелыйКрасныйЗеленыйСинийЖелтыйПурпурныйГолубойTransparencyПрозрачностьПолупрозрачныйПрозрачныйОкноColorЧерныйБелыйКрасныйЗеленыйСинийЖелтыйПурпурныйГолубойTransparencyПрозрачныйПолупрозрачныйПрозрачностьРазмер шрифта50%75%100%125%150%175%200%300%400%Стиль края текстаНичегоПоднятыйПониженныйОдинаковыйТеньШрифтПропорциональный без засечекМоноширинный без засечекПропорциональный с засечкамиМоноширинный с засечкамиСлучайныйПисьменныйМалые прописныеСбросить сбросить все найстройки по умолчаниюГотовоЗакрыть модальное окноКонец диалогового окна.
Кроме этого, мы хотим иметь возможность включать dropout в механизме внимания. Авторы трансформера рекомендуют делать так. Для этого мы передаём ещё два аргумента. Первый аргумент — это флаг, которые принимает значение "true", когда мы находимся в режиме обучения — это значит, что dropout нужно включить. Если мы не в режиме обучения, то dropout выключается. И второй параметр — это число от нуля до единицы, это сила dropout. Если эта переменная равна 0, то, по сути, dropout выключен. Если — равно 1, то dropout зануляет практически все элементы входной последовательности. Эта функция возвращает кортеж из двух элементов. То есть, эта функция возвращает сразу два тензора. Первый тензор — это основной результат работы механизма внимания. То есть, для каждого запроса и для каждой "головы" найден новый вектор признаков. Второй тензор возвращать не обязательно, но мы это будем делать для целей визуализации. Это тоже четырёхмерный тензор, который показывает нам оценки значимости или релевантности каждой позиции из последовательности ключей для каждой позиции из последовательности запросов. Самый первый шаг в механизме внимания — это сравнение. Здесь мы берём последовательность запросов, последовательность ключей, берём все возможные пары выходной позиции и входной позиции и находим сходство посредством скалярного произведения. Для того, чтобы красиво записать вычисления всех нужных нам оценок сходства, мы используем так называемую "эйнштейновскую запись" (мы приложим ссылку для того, чтобы вы могли поизучать, что это такое). Частое это достаточно удобный способ для описания сложных тензорных произведений. Если в двух словах, то — для того, чтобы описать тензорное произведение в эйнштейновской записи мы задаём обозначения для всех измерений входных тензоров. То есть, "b" — это "batch size", "v" — это "количество запросов" (то есть длина последовательности запросов), "h" — это "количество голов", "s" — это размерность вектора признаков для каждой позиции, для каждой головы. То же самое для второго тензора — это тензор ключей, здесь всё то же самое, кроме второго измерения, потому что, теоретически, количество запросов и количество ключей могут отличаться, хотя в данном семинаре это не так. И, затем, после знака "стрелочки" мы описываем измерения результирующего тензора. Те буквы, которые были слева от стрелочки, но их нету справа от стрелочки, соответствуют измерениям, по которым будет производиться скалярное произведение. Конкретно в этой ситуации у нас уходит буковка "s" — это значит, что мы производим скалярное произведение по последнему измерению и немного переворачиваем результирующий тензор — так, чтобы у нас первое измерение соответствовало количеству примеров в батче, второе — количеству запросов (то есть, длине последовательность запросов), третье — количеству ключей и четвёртое количеству "голов". Получаем такой вот четырёхмерный тензор. Надо сказать, что запросы и ключи мы сравниваем только внутри одной "головы" и только внутри одного примера в батче. Затем мы применяем наши маски. Во-первых, мы применяем маску паддингов. Напомню, что эта маска содержит нолики для значимых токенов и единички для токенов выравнивания (паддингов). Применение этой маски заключается в том, что мы записываем −∞-\infty−∞ во все позиции тензора сходства, соответствующие сравнениям какого-либо запроса с ключами, соответствующими паддингу. Напомню, что, когда мы будем применять софтмакс для того, чтобы получить нормированные оценки сходства, позиции, на которых стояло −∞-\infty−∞ получат значение "0". Далее, аналогичным образом, мы применяем маску зависимостей. Как мы помним, в маске зависимостей тоже есть "нолики", есть −∞-\infty−∞. Когда мы к какому-то конечному числу добавляем −∞-\infty−∞, то результат становится равным −∞-\infty−∞. Обратите внимание на вот эту странную запись — мы ставим квадратные скобки, как будто хотим выбрать из тензора какие-то строки или столбцы (то есть, проиндексировать тензор), а потом передаём туда None. Что это за ерунда? Такую запись можно использовать для того, чтобы добавить измерения в тензор. Это примерно то же самое, что вызвать несколько раз метод "unsqueeze" из pytorch. Двоеточие соответствует взятию всех элементов по соответствующему измерению. Таким образом в выделенной строчке мы добавляем два измерения на первую позицию (то есть, как бы, добавляем измерения для размера батча), и на последнюю позицию (то есть, добавляем измерения для количества голов). Далее мы применяем софтмакс по третьему измерению. То есть по измерению, соответствующему количеству ключей (напомню, что измерения нумеруются с нуля). Таким образом, сумма весов в тензоре "normed rels" для каждой выходной позиции, для каждого элемента батча и для каждой "головы" будет равна 1. Далее мы применяем dropout, причём применяем его не на матрицу признаков, как это обычно делается, а мы применяем его поверх нормированных оценок сходства. Таким образом, мы исключаем зависимости каких-то выходных позиций от входных. Это достаточно хороший способ регуляризации в данном случае. Далее нам нужно взять тензор весов (то есть тензор "normed rels") и тензор значений ("values") и перемножить их и сложить так, чтобы получить новый вектор признаков для каждой выходной позиций. Здесь мы сначала добавляем измерение в исходные тензоры, так, чтобы у них были одинаковые количества измерений, а затем применяем операцию поэлементного перемножения. И в numpy, и в pytorch есть так называемый механизм "broadcasting" — это когда у нас формы тензоров не совпадают, а мы к ним как применяем операцию перемножения или сложения. Рytorch и numpy каким-то образом дополняют размерности этих тензоров, так, чтобы они совпали и операцию можно было выполнить. Одно из базовых правил broadcasting — это когда размерность тензора по какому-то измерению равна единице, мы можем по этому измерению его просто клонировать нужное количество раз. Конечно клонирование, фактически, не выполняется — память дополнительно не выделяется, но, как будто бы, мы клонируем. Таким образом, в результате broadcasting, например, вот это измерение — последнее измерение тензора "normed rels expanded" станет равно "value_size", то есть количеству признаков для каждого значения. В результате процедуры broadcasting и перемножения мы получаем пятимерный тензор — обратите внимание, что единички (вот эти) были автоматически расширены до соответствующей размерности второго тензора. И, наконец, мы сворачиваем полученный тензор по размерности, соответствующей количеству ключей. Таким образом, получаем четырёхмерный тензор, который для каждого примера в батче, для каждой выходной позиции и для каждой головы содержит некоторый вектор признаков, ну, и возвращаем всё.

К сожалению, у нас пока нет статистики ответов на данный вопрос, но мы работаем над этим.