Видео проигрыватель загружается.Воспроизвести видеоВоспроизвестиБез звукаТекущее время 0:00/Продолжительность 4:18Загрузка: 0.00%0:00Тип потока ОНЛАЙНSeek to live, currently behind liveОНЛАЙНОставшееся время -4:18 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%Стиль края текстаНичегоПоднятыйПониженныйОдинаковыйТеньШрифтПропорциональный без засечекМоноширинный без засечекПропорциональный с засечкамиМоноширинный с засечкамиСлучайныйПисьменныйМалые прописныеСбросить сбросить все найстройки по умолчаниюГотовоЗакрыть модальное окноКонец диалогового окна.
Это была реализация механизма внимания с несколькими головами и с раздельными последовательностями запросов, ключей и значений. Теперь нам нужно сделать небольшой шажок сторону "self attention". Это уже кирпичик, имеющий непосредственное отношение к трансформеру. По сути, "self-attention" — это обычный механизм внимания. Самая главная его особенность заключается в том, что ключи, запросы и значения вычисляются из одной и той же последовательности. Давайте посмотрим, как это всё работает. Метод "forward" — на вход нам дают одну последовательность. Эта последовательность представляет батч текстов, то есть у нас есть какое-то количество примеров в батче, наибольшая длина текста и последнее измерение соответствует вектору признаков, то есть рабочему размеру модели. Что мы делаем дальше? Дальше мы берём три простых линейных слоя. По сути, каждый линейный слой параметризуется квадратной матрицей. В принципе, не обязательно брать именно линейный слой — можно навернуть сюда более сложную архитектуру, но... не нужно, чаще всего. Итак, мы берём три этих линейных слоя и применяем их к исходной последовательности. Таким образом, мы преобразовываем вектор признаков каждого входного элемента независимо от других элементов. Затем мы немного меняем форму, то есть мы последнее измерение (оно обозначается "model size") разбиваем на два измерения — это количество голов (то есть, по сути, это количество независимых механизмов внимания) и новое количество признаков. Это новое количество признаков равняется, по сути, "model size" делить на количество голов. Как вы видите, запросы, ключи и значения получаются абсолютно одинаково. Отличие заключается только в том, что веса (вот этих) преобразований независимы и они сходятся к разным значениям в ходе обучения. Далее мы берём эти три тензора, берём маски, которые нам передали свыше на вход, и передаём в функцию, которую мы только что рассмотрели — функцию "my multihead attention". Также мы передаём туда флаг "self train" — этот флаг есть у каждого экземпляра класса "torch.nn.module". Он автоматически обновляется, в зависимости от того, находится ли вся модель в режиме обучения, или в режиме предсказания. Как мы помним, функция multihead attention возвращает нам четырёхмерный тензор, мы схлопываем последнее измерение обратно в model size для того, чтобы слои self-attention можно было комбинировать с любыми другими слоями. То есть это удобно — когда форма тензора не меняется после преобразования. А также мы сохраняем карту активации — это позволит нам потом эти карты активации нарисовать и, возможно, получить какие-то знания о том, как работает модель (но — не факт). Важный момент здесь — это вызывать метод "detach". Если мы не будем его вызывать, то у нас будет попросту утекать память, потому что каждый тензор хранит ссылки на тензоры, из которых он был получен, и, таким образом, мы будем хранить ссылки на предыдущие батчи, даже. Поэтому, если мы не хотим дальше использовать какой-то тензор в обучении, не хотим прокидывать через него производную, то всегда лучше сделать "detach". Итак, это был блок "self attention". Вернёмся немножко назад — к конструктору нашего класса "self attention", посмотрим, что же нам нужно, чтобы создать экземпляр этого класса. Нам нужен размер модели (суммарное количество признаков по всем головам, model_size), нам нужно количество голов и нам нужен коэффициент dropout. Важно, чтобы размер модели ("model_size") делился нацело на количество голов.

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