Attention и self-attention на Python
Attention позволяет каждому токену посмотреть на остальные токены и решить, какие из них важны. У каждого токена есть запрос (что он ищет), ключ (что он предлагает) и значение (информация, которую он передаёт).
Суть простыми словами
Attention позволяет каждому токену посмотреть на остальные токены и решить, какие из них важны. У каждого токена есть запрос (что он ищет), ключ (что он предлагает) и значение (информация, которую он передаёт).
Вычислите scaled dot-product attention вручную с запросами, ключами и значениями, а затем добавьте causal mask, как в GPT.
Главные идеи
- Веса attention получаются из softmax, поэтому каждая строка в сумме даёт 1.
- Деление на √d не даёт оценкам становиться слишком большими для длинных векторов.
- Causal mask не позволяет токену смотреть на будущие токены во время генерации.
- Multi-head attention выполняет несколько attention параллельно, а позиционное кодирование добавляет порядок слов.
Когда это использовать?
- Понять, что происходит внутри нейронных сетей и библиотек ИИ.
- Разобраться в идее до того, как реализовать её в соответствующих задачах.
- Подготовиться к курсам по машинному обучению, собеседованиям и проектам.
Посмотрите в действии
Щёлкните по строке тепловой карты, чтобы увидеть, куда смотрит этот токен. Включите causal mask, чтобы скрыть будущие токены, и меняйте резкость, чтобы сфокусировать attention.
Пример кода
import math
def softmax(row):
exps = [math.exp(v - max(row)) for v in row]
return [e / sum(exps) for e in exps]
# Three tokens, each with a query, key and value vector of size 2.
Q = [[1, 0], [0, 1], [1, 1]]
K = [[1, 0], [0, 1], [1, 1]]
V = [[10, 0], [0, 10], [5, 5]]
d = len(K[0])
def attention(causal=False):
out = []
for i, q in enumerate(Q):
# Score: how well this query matches every key, scaled by sqrt(d).
scores = [sum(a * b for a, b in zip(q, k)) / math.sqrt(d) for k in K]
if causal: # a token may only look at itself and earlier tokens
scores = [s if j <= i else -1e9 for j, s in enumerate(scores)]
weights = softmax(scores)
out.append([round(sum(w * v[c] for w, v in zip(weights, V)), 2) for c in range(2)])
return out
print("attention:", attention())
print("causal attention:", attention(causal=True))
Ожидаемый результат
attention: [[6.02, 3.98], [3.98, 6.02], [5.0, 5.0]]
causal attention: [[10.0, 0.0], [3.3, 6.7], [5.0, 5.0]]
Как это работает
Для каждого запроса оценки - это его скалярные произведения со всеми ключами, делённые на √d. Softmax превращает оценки в веса, а выход - это взвешенное среднее значений. С causal mask первый токен видит только себя, поэтому его выход в точности равен его собственному значению [10, 0].
Измените значения и запустите программу в онлайн-компиляторе Python CodeUtility без локальной установки Python.
Практические задания
Изменяйте входные данные и проверяйте граничные случаи перед работой с большими наборами.
- Измените входные данные или веса и предскажите результат до запуска.
- Выводите промежуточные значения, чтобы проследить каждый шаг вычислений.
- Решите задачи по ссылкам ниже, чтобы самостоятельно реализовать идею.
Попрактикуйтесь на задаче
Примените материал этого урока к реальной задаче. Каждая задача запускается в браузере, с мгновенными тестами и разбором от ИИ.
- Синусоидальное позиционное кодирование Вычислите синусные и косинусные векторы позиций, которые Transformer добавляет к эмбеддингам токенов. Средне
- Масштабированное скалярное внимание Реализуйте операцию внимания — основу трансформеров и больших языковых моделей. Сложно
- Каузальное (маскированное) самовнимание Реализуйте маскированное внимание моделей GPT, где каждый токен видит только себя и предыдущие токены. Средне
- Многоголовое самовнимание Спроецируйте вход в запросы, ключи и значения, выполните внимание в нескольких головах параллельно и объедините их. Сложно