Понимание сетей Transformer и механизма Self-Attention

Техническая диаграмма архитектуры Transformer, показывающая связи механизма self-attention

В 2017 году ландшафт искусственного интеллекта изменился навсегда после публикации фундаментальной работы «Attention Is All You Need» команды исследователей под руководством Vaswani. В работе была представлена архитектура Transformer — революционная архитектура нейронных сетей, которая полностью отказалась от рекуррентности (RNN, LSTM), сделав выбор в пользу параллельной обработки последовательностей данных с использованием Механизма Self-Attention (самовнимания).

Сегодня архитектура Transformer лежит в основе практически всех передовых больших языковых моделей (LLM), включая GPT-4, Gemini, Claude и Llama. В этой статье мы раскроем устройство сетей Transformer и математические основы реализации механизма самовнимания.


1. Проблема узкого места последовательной обработки (RNN против Transformer)

До появления моделей Transformer стандартом для моделирования последовательностей были рекуррентные нейронные сети (RNN) и сети долгой краткосрочной памяти (LSTM). Однако RNN обрабатывают токены последовательно — по одному слову за раз. Чтобы вычислить скрытое состояние для десятого слова, модель должна сначала вычислить скрытые состояния для слов с первого по девятое.

Эта последовательная природа накладывает два серьезных ограничения:

  1. Невозможность параллелизации: Современные графические процессоры (GPU) не могут использоваться эффективно, поскольку вычисления должны ожидать завершения предыдущего шага.
  2. Затухание/взрыв градиентов: Информация из начала длинной последовательности сжимается и теряется к моменту, когда модель достигает конца (проблема узкого места).

Архитектура Transformer решает обе проблемы. Заменяя рекуррентность механизмом Self-Attention, модель Transformer обрабатывает всю входную последовательность одновременно, что обеспечивает колоссальную параллелизацию и прямую связь между любыми двумя токенами в последовательности независимо от расстояния.


2. Что такое механизм Self-Attention?

Механизм самовнимания (Self-attention) позволяет модели оценивать взаимосвязи между различными словами в одной и той же последовательности. Вместо того чтобы обрабатывать слово изолированно, модель формирует представление каждого слова с учетом контекста всех остальных слов в предложении.

Например, в предложениях:

  • «Он сидел на берегу реки и смотрел на песчаный кос
  • «Девочке заплели красивый кос

Слово «кос» (коса) имеет разные значения в зависимости от контекста. Механизм самовнимания позволяет модели обращать внимание на слово «реки» в первом предложении и «девочке» во втором, чтобы правильно скорректировать векторное представление слова «кос».

Аналогия с базами данных: запросы (Queries), ключи (Keys) и значения (Values)

Математическая формулировка самовнимания смоделирована по аналогии с поиском информации в базах данных. Для каждого входного токена мы получаем три векторных представления:

  1. Запрос ($Q$): То, что ищет текущий токен.
  2. Ключ ($K$): Метка или профиль токенов в последовательности.
  3. Значение ($V$): Фактическое содержимое или информация токенов.

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


3. Математическое описание Scaled Dot-Product Attention

Стандартная формула самовнимания называется Scaled Dot-Product Attention (масштабированное внимание на основе скалярного произведения):

$$\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V$$

Ниже приведено пошаговое описание работы этой формулы:

Шаг 1: Вычисление матриц проекции

Для матрицы входной последовательности $X \in \mathbb{R}^{T \times d_{\text{model}}}$, мы умножаем её на обучаемые матрицы весов $W_Q, W_K, W_V$, чтобы получить Запросы ($Q$), Ключи ($K$) и Значения ($V$): $$Q = X W_Q, \quad K = X W_K, \quad V = X W_V$$

Шаг 2: Расчет оценок сходства (скалярное произведение)

Мы вычисляем скалярное произведение матрицы Запросов $Q$ на транспонированную матрицу Ключей $K^T$ для измерения соответствия/релевантности между всеми парами токенов: $$\text{Scores} = QK^T$$ Полученная матрица имеет размерность $T \times T$, где элемент $(i, j)$ показывает, насколько токен $i$ должен быть внимателен к токену $j$.

Шаг 3: Масштабирование оценок

Оценки делятся на квадратный корень из размерности ключей ($d_k$): $$\text{Scaled Scores} = \frac{QK^T}{\sqrt{d_k}}$$ Зачем масштабировать? При больших значениях $d_k$ скалярные произведения сильно возрастают, из-за чего функция softmax попадает в области с экстремально малыми градиентами (проблема затухания градиента). Масштабирование на $\sqrt{d_k}$ стабилизирует процесс обучения.

Шаг 4: Применение Softmax (веса внимания)

Мы применяем функцию softmax к каждой строке, чтобы нормализовать оценки в распределение вероятностей (значения от 0 до 1, сумма которых равна 1): $$\text{Attention Weights} = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)$$

Шаг 5: Взвешенная сумма Значений

Наконец, мы умножаем веса внимания на матрицу Значений $V$: $$\text{Output} = \text{Attention Weights} \times V$$ Этот шаг агрегирует информацию, позволяя выходному представлению каждого токена находиться под сильным влиянием токенов, на которые он «обратил внимание».


4. Multi-Head Attention

Вместо того чтобы выполнять самовнимание один раз, в Transformer используется Multi-Head Attention (многоголовое внимание). Оно разделяет векторы Запросов, Ключей и Значений на $h$ меньших размерностей («голов»), параллельно и независимо вычисляет внимание в каждом подпространстве, а затем конкатенирует результаты.

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


5. Реализация внимания на Python/NumPy

Чтобы лучше понять реализацию, напишем простую симуляцию масштабированного внимания и многоголового внимания на языке Python с использованием библиотеки NumPy:

import numpy as np

def softmax(x):
    # Стабилизированный softmax для предотвращения переполнения
    exp_x = np.exp(x - np.max(x, axis=-1, keepdims=True))
    return exp_x / np.sum(exp_x, axis=-1, keepdims=True)

def scaled_dot_product_attention(Q, K, V, mask=None):
    """
    Вычисляет Scaled Dot-Product Attention.
    Q: [batch_size, seq_len, d_k]
    K: [batch_size, seq_len, d_k]
    V: [batch_size, seq_len, d_v]
    mask: Необязательная бинарная маска [batch_size, seq_len, seq_len]
    """
    d_k = Q.shape[-1]
    
    # Шаги 2 и 3: Скалярное произведение и масштабирование
    scores = np.matmul(Q, K.swapaxes(-2, -1)) / np.sqrt(d_k)
    
    # Необязательное маскирование (например, каузальная маска в декодерах)
    if mask is not None:
        scores = np.where(mask == 0, -1e9, scores)
        
    # Шаг 4: Применение softmax для получения весов внимания
    attention_weights = softmax(scores)
    
    # Шаг 5: Взвешенная сумма значений
    output = np.matmul(attention_weights, V)
    
    return output, attention_weights

# --- Пример выполнения ---
if __name__ == "__main__":
    np.random.seed(42)
    batch_size = 1
    seq_len = 4  
    d_k = 8
    d_v = 8
    
    # Генерация случайных векторов Query, Key и Value
    Q = np.random.randn(batch_size, seq_len, d_k)
    K = np.random.randn(batch_size, seq_len, d_k)
    V = np.random.randn(batch_size, seq_len, d_v)
    
    output, weights = scaled_dot_product_attention(Q, K, V)
    
    print("Матрица весов внимания (Длина последовательности x Длина последовательности):")
    print(np.round(weights[0], 4))
    print("\nФорма выходного тензора внимания:", output.shape)

6. Сравнение архитектур

Характеристика RNN / LSTM Transformer
Последовательная обработка Да (токен за токеном) Нет (параллельная обработка)
Вычислительная сложность $O(T)$ последовательно $O(1)$ последовательно, $O(T^2)$ всего операций
Длинные зависимости Плохо (память затухает с шагами) Отлично (прямая связь независимо от расстояния)
Parallelization Невозможна по оси времени Нативная параллелизация
Позиционное кодирование Не требуется (встроено в шаги) Требуется (Positional Encoding)

7. Дополнительные компоненты блока Transformer

Для полноценной работы самовнимания архитектура Transformer включает в себя несколько важных слоев в каждом блоке:

  1. Positional Encoding (позиционное кодирование): Поскольку модели Transformer обрабатывают все токены сразу, они не имеют встроенного представления об их порядке. Мы внедряем векторы позиционного кодирования (на основе синусоид и косинусоид различной частоты) непосредственно во входные эмбеддинги.
  2. Residual Connections (остаточные связи): Сквозные связи вокруг каждого подслоя (внимания и полносвязного слоя) помогают градиентам распространяться через глубокие сети без затухания.
  3. Layer Normalization (нормализация по слоям): Нормализует активации каждого слоя, стабилизируя и ускоряя обучение.
  4. Feed-Forward Networks (полносвязные сети): Двухслойный перцептрон (MLP), применяемый к каждому токену независимо и добавляющий нелинейную выразительность.

Заключение

Переход Transformer от рекуррентности к параллельному самовниманию открыл путь к законам масштабирования современного ИИ. Понимание концепции запросов, ключей и значений показывает, как модели могут динамически связывать идеи и конструировать смыслы на лету, закладывая основу для когнитивных способностей современных LLM.


Узнайте больше технических подробностей в блоге Ghaznix →