В чем разница между механизмами Attention и Self-Attention?

«В чем разница между механизмами Attention и Self-Attention?» — вопрос из категории NLP и трансформеры, который задают на 26% собеседований Data Scientist / ML Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Attention (Внимание) и Self-Attention (Само-внимание) — это взаимосвязанные механизмы в архитектурах нейронных сетей, но они решают разные задачи.

Attention (Механизм внимания)

Это общий механизм, который позволяет модели сопоставлять две разные последовательности. Классический пример — архитектура encoder-decoder в машинном переводе: декодер (выходная последовательность) "внимательно смотрит" на энкодер (входную последовательность), чтобы решить, какое слово перевести следующим.

  • Вход: Запросы (Queries) от одной последовательности и Пары Ключ-Значение (Keys-Values) от другой.
  • Задача: Найти релевантные части в последовательности-источнике (encoder) для каждого элемента последовательности-цели (decoder).

Self-Attention (Механизм само-внимания)

Это частный случай механизма внимания, где все три компонента (Queries, Keys, Values) происходят из одной и той же последовательности. Это позволяет каждому элементу последовательности взаимодействовать со всеми другими элементами этой же последовательности, улавливая внутренние зависимости (синтаксические, семантические).

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

Визуализация отличия:

Attention:        Sequence A (Queries)  <--->  Sequence B (Keys/Values)
                 (e.g., Decoder Output)        (e.g., Encoder Output)

Self-Attention:  Sequence A (Queries)  <--->  Sequence A (Keys/Values)
                 (e.g., Input Sentence)        (e.g., Same Input Sentence)

Реализация Scaled Dot-Product Self-Attention (упрощенная):

import torch
import torch.nn.functional as F

def self_attention(input_sequence, d_model=64):
    # input_sequence shape: (batch_size, seq_len, d_model)
    batch_size, seq_len, _ = input_sequence.shape

    # Линейные проекции для получения Q, K, V из одного входа
    W_q = torch.nn.Linear(d_model, d_model, bias=False)
    W_k = torch.nn.Linear(d_model, d_model, bias=False)
    W_v = torch.nn.Linear(d_model, d_model, bias=False)

    Q = W_q(input_sequence)  # (batch, seq_len, d_model)
    K = W_k(input_sequence)  # (batch, seq_len, d_model)
    V = W_v(input_sequence)  # (batch, seq_len, d_model)

    # Вычисление весов внимания
    scores = torch.bmm(Q, K.transpose(1, 2)) / (d_model ** 0.5)  # Масштабирование
    attention_weights = F.softmax(scores, dim=-1)  # (batch, seq_len, seq_len)

    # Применение весов к значениям
    output = torch.bmm(attention_weights, V)  # (batch, seq_len, d_model)
    return output, attention_weights

# Пример вызова
x = torch.randn(2, 10, 64)  # 2 примера, длина последовательности 10, размерность 64
context_vector, attn = self_attention(x)

Итог: Self-Attention — это основа блока Transformer, которая кодирует контекст внутри последовательности. Классический Attention используется для связи между разными последовательностями, например, в seq2seq-моделях.