Ответ
Помимо стандартного scaled dot-product self-attention из трансформеров, в различных архитектурах я применял и другие механизмы внимания:
1. Внимание в encoder-decoder архитектурах (Seq2Seq Attention) До трансформеров активно использовал attention в RNN-based моделях для машинного перевода (например, в архитектуре Bahdanau или Luong). Здесь внимание вычисляется между скрытыми состояниями энкодера и текущим состоянием декодера, позволяя модели "заглядывать" в исходную последовательность.
# Упрощенная реализация additive attention (Bahdanau)
import torch
import torch.nn.functional as F
def bahdanau_attention(encoder_states, decoder_state):
# encoder_states: [seq_len, batch, hidden]
# decoder_state: [batch, hidden]
scores = torch.tanh(encoder_states + decoder_state.unsqueeze(0))
scores = torch.matmul(scores, attention_weight_vector)
alpha = F.softmax(scores, dim=0) # Веса внимания
context = (encoder_states * alpha).sum(dim=0) # Контекстный вектор
return context, alpha
2. Многоголовое внимание (Multi-Head Attention) Хотя это часть трансформера, стоит отметить, что эта идея позволяет модели совместно обрабатывать информацию из разных подпространств представлений. Я настраивал количество голов в зависимости от задачи.
3. Разреженное внимание (Sparse Attention) При работе с длинными последовательностями (тексты, временные ряды) полное внимание становится вычислительно дорогим. Использовал варианты, где каждый токен взаимодействует только с подмножеством других (например, скользящее окно (sliding window), расширяющееся внимание (dilated attention) или блочное внимание).
4. Кросс-модальное внимание (Cross-Modal Attention) Применял в задачах типа "изображение-текст" (image captioning, VQA). Здесь механизм внимания вычисляет релевантность между регионами изображения (признаками от CNN) и словами текстовой последовательности.
5. Структурированное внимание (Structured Attention) Экспериментировал с подходами, где распределение внимания не является независимым по позициям, а следует какой-либо структуре (например, дереву зависимостей в предложении), используя алгоритмы динамического программирования.
Практический вывод: Выбор механизма внимания – это компромисс между выразительностью модели и вычислительной сложностью. Для большинства NLP задач сегодня достаточно стандартного многоголового self-attention. Для очень длинных последовательностей или кросс-модальных задач приходится обращаться к более специализированным вариантам.