Zero to Hero, лекция 2: языковая модель на биграммах (makemore, часть 1)
Подробный конспект лекции Карпатого: символьная модель имён, построенная двумя способами — подсчётом биграмм и однослойной нейросетью. Сэмплирование, отрицательное лог-правдоподобие, коварство broadcasting и сглаживание, которое оказывается регуляризацией.
Коротко
Заголовок раздела «Коротко»- makemore «делает ещё» того, что ему дали: обучается на 32 тысячах имён и придумывает новые. Внутри — символьная языковая модельязыковая модельEN language model (LM)Распределение вероятностей над последовательностями токенов. На практике — функция «контекст → вероятности следующего токена».: по предыдущим символам она предсказывает следующий. За серию лекций Карпатый проводит её от биграмм до трансформера уровня GPT-2.
- Первая модель — биграммнаябиграммаEN bigramПара соседних токенов. Биграммная модель оценивает P(x_t | x_{t−1}) — таблица V × V.: смотрит только на один предыдущий символ. Её можно «обучить» обычным подсчётом: сколько раз за буквой шла буква . Потом строки таблицы нормируются в вероятности.
- Качество модели меряется одним числом — средним отрицательным лог-правдоподобием (NLLотрицательное лог-правдоподобие (NLL)EN negative log-likelihood (NLL)−log P(данные | модель), обычно усреднённое по токенам. Для языковой модели совпадает с cross-entropy.). Для биграмм на всём наборе это около 2.45. Модель, где все 27 символов равновероятны, дала бы .
- Вторая половина — та же модель как нейросеть: one-hot вход, один линейный слой , softmax и градиентный спуск по NLL. Сеть приходит к той же таблице и тому же loss. Сглаживание счётчиков оказывается L2-регуляризацией весов.
- Главный посыл на всю серию: дальше меняться будет только прямой проход — как из прошлых символов получаются логиты. Softmax, NLL и градиентное обучение останутся прежними вплоть до трансформеров.
Как смотреть вместе с курсом
Заголовок раздела «Как смотреть вместе с курсом»Курс повторяет эту лекцию почти шаг в шаг в уроке 4.1.2 «Биграммная модель на русских именах». Смотреть лучше так: урок 4.1.1 «Что такое языковая модель», потом лекция, потом урок 4.1.2. Он добавляет то, чего в лекции нет: честную проверку на отложенных именах и подбор силы сглаживания. Математика правдоподобия и softmax разобрана в уроке 1.3.2, а broadcasting — в уроке 0.3.2, его стоит освежить перед главой про эффективность (36:20).
Новичку не нужно запоминать детали отрисовки таблицы (18:21) и ветку про torch.tensor против torch.Tensor —
достаточно усвоить вывод. Главы про broadcasting и про NLL пропускать нельзя.
Код лекции — ноутбук makemore_part1_bigrams.ipynb
(MIT), файл names.txt — в репозитории karpathy/makemore (MIT). Нужны
PyTorch и matplotlib, хватит CPU. Китайская учебная версия с переведёнными пояснениями —
002_makemore_Bigrams.
Карта лекции
Заголовок раздела «Карта лекции»Таймкоды — из глав в описании видео.
| Время | Глава в оригинале | О чём |
|---|---|---|
| 0:00 | intro | что такое makemore и план серии |
| 3:06 | reading and exploring the dataset | 32 033 имени, длины от 2 до 15 |
| 6:25 | exploring the bigrams in the dataset | пары соседних символов, маркеры начала и конца |
| 9:24 | counting bigrams in a python dictionary | подсчёт в словаре |
| 12:48 | counting bigrams in a 2D torch tensor (“training the model”) | таблица N в тензоре — это и есть «обучение» |
| 18:21 | visualizing the bigram tensor | картинка таблицы через matplotlib |
| 20:56 | deleting spurious (S) and (E) tokens in favor of a single . token | один служебный символ . вместо двух |
| 24:03 | sampling from the model | генерация имён через torch.multinomial |
| 36:20 | efficiency! vectorized normalization of the rows, tensor broadcasting | нормировка строк и ловушка broadcasting |
| 50:14 | loss function (the negative log likelihood of the data under our model) | правдоподобие, логарифм, NLL |
| 1:00:50 | model smoothing with fake counts | сглаживание «фальшивыми» счётчиками |
| 1:03:00 | PART 2: the neural network approach: intro | та же задача в рамках нейросетей |
| 1:05:27 | creating the bigram dataset for the neural net | пары (вход, ответ) |
| 1:10:01 | feeding integers into neural nets? one-hot encodings | one-hot кодирование |
| 1:13:54 | the “neural net”: one linear layer of neurons implemented with matrix multiplication | слой как матричное умножение |
| 1:18:46 | transforming neural net outputs into probabilities: the softmax | логиты → вероятности |
| 1:26:17 | summary, preview to next steps, reference to micrograd | сводка и связь с micrograd |
| 1:35:52 | vectorized loss | loss одной строкой |
| 1:38:40 | backward and update, in PyTorch | обратный проход и шаг |
| 1:42:59 | putting everything together | обучение на всех 228 тыс. биграммах |
| 1:47:54 | note 1: one-hot encoding really just selects a row of the next Linear layer’s weight matrix | one-hot × W = строка W |
| 1:50:20 | note 2: model smoothing as regularization loss | сглаживание = регуляризация |
| 1:54:36 | sampling from the neural net | генерация из сети |
| 1:56:20 | conclusion | итоги |
1. Что такое makemore
Заголовок раздела «1. Что такое makemore»makemore — репозиторий Карпатого. Как и micrograd из первой лекции, он
собирается в видео с нуля. Пример данных — names.txt: около 32 тысяч имён, которые Карпатый, по его словам, взял
с правительственного сайта. Обученная модель выдаёт что-то похожее на имена, но новое. Карпатый в шутку
предлагает искать так необычное имя для ребёнка.
Модель символьная: каждое имя — последовательность букв, и задача — угадать следующую. План серии, как его обозначает Карпатый: биграммы, «мешок слов» (bag of words), многослойный перцептрон, рекуррентные сети и трансформер, по сути эквивалентный GPT-2. Дальше он собирался перейти от символов к словам и к картинкам, в духе DALL·E и Stable Diffusion. Серия в итоге свернула к GPT и токенизатору, но начало именно такое.
2. Данные и биграммы
Заголовок раздела «2. Данные и биграммы»Имён 32 033, самое короткое — 2 буквы, самое длинное — 15. Важное наблюдение: одно слово — это не один, а много
обучающих примеров. Имя isabella сообщает, что имя часто начинается с i, что после i бывает s, после is —
a и так далее. Ещё один пример спрятан в конце: после isabella имя заканчивается.
БиграммабиграммаEN bigramПара соседних токенов. Биграммная модель оценивает P(x_t | x_{t−1}) — таблица V × V. — два символа подряд. Биграммная модель забывает всю остальную историю и
предсказывает следующий символ только по текущему. Модель очень слабая, но с неё удобно начать. Чтобы не потерять
информацию о начале и конце, к имени приписываются служебные символы: сначала <S> и <E>, а потом один общий
символ ..
Пары соседей Карпатый перебирает изящным приёмом: zip(w, w[1:]). Функция zip идёт по двум последовательностям
параллельно и останавливается, когда короче из них кончится. Счётчики сначала живут в словаре. Самые частые
биграммы в наборе: «n в конце имени» — 6763 раза, «a в конце» — 6640, a→n — 5438, «имя начинается с a» — 4410.
3. Таблица счётчиков в тензоре — это и есть обучение
Заголовок раздела «3. Таблица счётчиков в тензоре — это и есть обучение»Словарь неудобен, поэтому счётчики переезжают в двумерный массив PyTorch: строка — первый символ, столбец — второй.
Попутно Карпатый показывает основы torch.tensor: создание нулями, тип данных (dtype=torch.int32 для целых
счётчиков вместо float32 по умолчанию), индексацию N[1, 3] += 1.
Сначала таблица была — 26 букв плюс <S> и <E>. На картинке видно, что это расточительно:
строка <E> целиком нулевая (после конца ничего не идёт), столбец <S> тоже (начало не бывает вторым символом).
Поэтому остаётся один служебный символ . с номером 0, буквы получают номера 1–26, а таблица становится
. Код из ноутбука лекции (MIT), комментарии наши:
import torch
words = open('names.txt', 'r').read().splitlines() # 32 033 имени, по одному в строке
chars = sorted(list(set(''.join(words)))) # 26 букв в алфавитном порядкеstoi = {s: i + 1 for i, s in enumerate(chars)} # буква → номер 1…26stoi['.'] = 0 # служебный символ начала и концаitos = {i: s for s, i in stoi.items()} # номер → буква
N = torch.zeros((27, 27), dtype=torch.int32)for w in words: chs = ['.'] + list(w) + ['.'] for ch1, ch2 in zip(chs, chs[1:]): # пары соседних символов N[stoi[ch1], stoi[ch2]] += 1 # «обучение» — просто подсчётНулевая строка N[0] — сколько имён начинается с каждой буквы. Последний столбец, N[:, 0], — сколько раз каждая
буква стоит в конце. Всё остальное — какие буквы за какими следуют. В этой таблице уже есть всё, что нужно, чтобы
генерировать имена.
4. Сэмплирование
Заголовок раздела «4. Сэмплирование»Генерация идёт по шагам. Начинаем с ., берём её строку, превращаем счётчики в вероятности (делим на сумму
строки) и случайно выбираем следующий символ по этим вероятностям. Затем берём строку выбранного символа, и так
до тех пор, пока не выпадет . — конец имени.
Случайный выбор делает torch.multinomial: даёшь ему вероятности, он возвращает номера. Карпатый обращает внимание
на две детали:
- чтобы у всех получались одинаковые числа, используется генератор с фиксированным зерном:
torch.Generator().manual_seed(2147483647); - аргумент
replacement=Trueнужно указывать явно — по умолчанию он почему-тоFalse.
На игрушечном примере из трёх вероятностей в выборке видно примерно то же соотношение
нулей, единиц и двоек. Первой буквой в ноутбуке выпадает m. Это правдоподобно: с m начинаются 2538 имён из
32 033, почти 8%.
g = torch.Generator().manual_seed(2147483647) # одинаковые случайные числа у всехfor _ in range(5): out, ix = [], 0 # начинаем со служебного '.' while True: p = N[ix].float() p = p / p.sum() # строка счётчиков → распределение ix = torch.multinomial(p, num_samples=1, replacement=True, generator=g).item() out.append(itos[ix]) if ix == 0: # выпал '.', имя закончилось break print(''.join(out))В ноутбуке Карпатого получаются mor., axx., minaymoryles., kondlaisah., anchshizarie.. В свежих версиях
PyTorch тот же код с тем же зерном выдаёт другие имена: у нас на PyTorch 2.14 вышли cexze., momasurailezitynn.,
konimittain., llayn., ka.. Важна не конкретика, а общий вид. Карпатый признаётся, что сам несколько
минут проверял, не ошибся ли: результат выглядит ужасно. Но всё верно, просто биграмма — очень слабая модель.
Когда она генерирует имя из одной буквы h, она не знает, что h стоит первой. Она видит только «был символ h»,
а после h конец имени вполне вероятен. Для сравнения Карпатый генерирует из необученной модели, где все
27 символов равновероятны. Получается полная каша, так что биграмма всё-таки чему-то научилась.
Подробнее о выборе следующего токена — жадном, с температурой, top-k и top-p — в уроке 4.1.3.
5. Эффективность и ловушка broadcasting
Заголовок раздела «5. Эффективность и ловушка broadcasting»В цикле генерации строка нормируется заново на каждом шаге. Это расточительно, поэтому Карпатый один раз строит
матрицу вероятностей P, где каждая строка уже нормирована. Заодно у него есть повод потренироваться
с тензорами — дальше, до трансформеров, без этого не обойтись.
Нужно разделить каждую строку -матрицы на её сумму. P.sum(1, keepdim=True) даёт суммы строк формы
— столбец. Можно ли делить матрицу на столбец ? Это решают правила
broadcastingbroadcasting (растягивание форм)EN broadcastingПравило, по которому NumPy и PyTorch выполняют операции над массивами разных форм без копирования данных.: формы выравниваются по правому краю, и в каждой позиции размеры должны
совпадать, или один из них равен 1, или его нет вовсе. Здесь всё в порядке: единичная ось растягивается
(копируется) 27 раз, и каждая строка делится на свою сумму.
Дальше Карпатый, по его словам, хочет «немного напугать». Уберите keepdim=True, и сумма станет вектором формы
. Правила снова выполнены: недостающая ось дописывается слева, вектор превращается в строку
и копируется вниз. Код работает без ошибок, но делит каждый столбец, а не строку. Строки перестают
суммироваться в единицу:
P = N.float()good = P / P.sum(1, keepdim=True) # (27, 27) / (27, 1): каждая строка делится на свою суммуbad = P / P.sum(1) # (27, 27) / (27,) → (1, 27): делятся столбцы!print(good[0].sum().item()) # 1.0print(bad[0].sum().item()) # около 7 — нулевая строка не нормированаЕго совет — относиться к broadcasting с уважением: читать документацию, проверять, в какую сторону идёт
растягивание, иначе появятся очень тонкие, трудно находимые баги. В конце главы — мелочь про память: P /= ...
делит на месте, без создания нового тензора, и это может быть быстрее. В курсе та же ловушка разобрана в
предупреждении «Ловушка broadcasting: keepdim» урока
4.1.2.
6. Как оценить модель: отрицательное лог-правдоподобие
Заголовок раздела «6. Как оценить модель: отрицательное лог-правдоподобие»Таблица P — это и есть параметры модели. Как одним числом сказать, хороша ли она? Карпатый смотрит, какую
вероятность модель даёт каждой биграмме из обучающих имён. Ориентир: если бы модель ничего не знала, каждому из
27 символов досталось бы . Всё, что выше, — выученное. В наборе встречаются биграммы
с вероятностями 35–40%.
Дальше рассуждение из статистики, по шагам:
- Правдоподобие — произведение вероятностей всех биграмм из данных. Чем оно больше, тем лучше модель объясняет данные. Но произведение сотен тысяч чисел меньше единицы — исчезающе малое число.
- Поэтому берут логарифм: , произведение превращается в сумму. Логарифм монотонен, значит, максимизировать его — то же самое, что максимизировать правдоподобие. Логарифм вероятности равен 0 при вероятности 1 и уходит в минус бесконечность при вероятности 0.
- Функцию потерь принято минимизировать, поэтому знак меняют — получается отрицательное лог-правдоподобие.
- Для удобства его усредняют по числу биграмм.
Читается так: для каждой из биграмм берём вероятность, которую модель дала правильному следующему символу,
логарифмируем, усредняем и меняем знак. Минимум NLL — ноль, тогда модель всегда уверенно права. На всех 228 146
биграммах набора получается около 2.454. Можно оценить и отдельное слово: имя andrej стоит в среднем около
3.04 на символ — дорого, потому что ej в данных редкость.
7. Сглаживание фальшивыми счётчиками
Заголовок раздела «7. Сглаживание фальшивыми счётчиками»Допишите к имени букву: andrejq. Loss становится бесконечным. Биграмма jq в данных не встречалась ни разу,
модель даёт ей вероятность ноль, а . Совершенно правдоподобная строка объявлена невозможной.
Лечение простое — сглаживание: ко всем счётчикам добавляют одно и то же число, например единицу,
P = (N + 1).float(). Чем больше добавка, тем ближе распределения к равномерным. Чем меньше, тем «острее» модель.
С добавкой 1 у jq вероятность около 0.03%, и andrejq стоит конечные 3.48 на символ. На общем loss по набору
сглаживание почти не сказывается: данных много.
Эта приём известен как сглаживание Лапласасглаживание Лапласа (add-one)EN Laplace (add-one) smoothingДобавить константу ко всем счётчикам, чтобы невиданные n-граммы не получали нулевую вероятность. Классический вариант — +1 (add-one), с произвольным α > 0 — сглаживание Лидстоуна (add-α); силу α подбирают на валидации.. Курс подбирает силу сглаживания на отложенных именах и показывает, почему без этого обойтись нельзя: в маленьком наборе русских имён невиданных биграмм очень много.
8. Часть 2: та же модель — нейросеть
Заголовок раздела «8. Часть 2: та же модель — нейросеть»Подсчёт работает, но такой подход не масштабируется. С контекстом в два символа строк было бы , с тремя — почти 20 тысяч, и счётчиков на каждую не хватит. Поэтому Карпатый переформулирует ту же биграммную задачу в терминах нейросетей. На вход — текущий символ, на выход — распределение следующего, качество — тот же NLL, обучение — градиентный спуск.
Данные. Из каждого имени получаются пары (вход, ответ). Из emma — пять примеров:
. → e, e → m, m → m, m → a, a → ., в номерах xs = [0, 5, 13, 13, 1], ys = [5, 13, 13, 1, 0]. По пути
Карпатый предупреждает про API: есть torch.tensor с маленькой буквы и класс torch.Tensor с большой. Первый
сохраняет тип данных (целые останутся целыми), второй всегда делает float. Разницу пришлось искать в обсуждениях
на форумах, документация её толком не объясняет. Совет — пользоваться маленьким tensor и привыкать читать
документацию и обсуждения.
One-hot. Подать номер символа прямо в нейрон бессмысленно: веса умножаются на вход, и «13» не больше «5»
ни в каком полезном смысле. Поэтому номер превращают в one-hotone-hot кодирование (унитарный код)EN one-hot encodingВектор длины V из нулей с единицей в позиции номера токена. Все one-hot векторы попарно ортогональны.-вектор длины 27: все нули,
одна единица на месте номера. F.one_hot возвращает целые числа, их нужно явно привести к float.
Слой. Веса — матрица из нормального распределения: 27 нейронов, у каждого 27 входов, без
смещения и без нелинейности. Умножение xenc @ W формы за один раз считает выходы
всех 27 нейронов на всех пяти примерах. Элемент — скалярное произведение третьего примера на тринадцатый
столбец .
Softmax. Выход слоя — произвольные числа со знаком, а нужны вероятности: положительные и с суммой 1. Карпатый предлагает считать эти числа логарифмами счётчиков. Их называют логитамилогитEN logitСтрого — логарифм шансов log(p / (1 − p)). В нейросетях логитами называют любые выходы до softmax или сигмоиды.. Экспонента делает их положительными «как бы счётчиками», а нормировка по строке — вероятностями. Две последние операции вместе и есть softmax.
flowchart LR A["символ<br/>номер 5"] --> B["one-hot<br/>длина 27"] B --> C["× W (27×27)<br/>логиты"] C --> D["exp<br/>«счётчики»"] D --> E["÷ сумма строки<br/>вероятности"] E --> F["−log p[ответ]<br/>среднее = loss"]
Loss и обучение. Нужные вероятности выдёргиваются одной индексацией: probs[torch.arange(5), ys] — в строке
взять столбец ys[k]. Дальше всё как в micrograd: обнулить градиент (в PyTorch можно присвоить None, это
эффективнее нуля), loss.backward(), шаг против градиента. PyTorch, как и micrograd, при прямом проходе
записывает граф операций. Не забудьте requires_grad=True у весов. Код из ноутбука лекции (MIT), комментарии наши:
import torch.nn.functional as F
# все биграммы всех имён как пары (вход, ответ)xs, ys = [], []for w in words: chs = ['.'] + list(w) + ['.'] for ch1, ch2 in zip(chs, chs[1:]): xs.append(stoi[ch1]) ys.append(stoi[ch2])xs, ys = torch.tensor(xs), torch.tensor(ys)num = xs.nelement() # 228 146 примеров
g = torch.Generator().manual_seed(2147483647)W = torch.randn((27, 27), generator=g, requires_grad=True)
for k in range(100): xenc = F.one_hot(xs, num_classes=27).float() # вход: one-hot, приводим к float logits = xenc @ W # «логарифмы счётчиков» counts = logits.exp() # «счётчики», аналог N probs = counts / counts.sum(1, keepdim=True) # две последние строки — softmax loss = -probs[torch.arange(num), ys].log().mean() + 0.01 * (W**2).mean() W.grad = None # обнулить градиент loss.backward() W.data += -50 * W.grad # да, learning rate = 50print(loss.item()) # около 2.49 после 100 шагов (вместе со штрафом)Сначала Карпатый учит сеть на пяти примерах из emma. Потом без единого изменения кода — на всех 228 тысячах
биграмм. Задача настолько простая, что подходит огромный learning rate 50. Loss сходится к 2.45–2.46, то есть
к тому же, что дал подсчёт. Так и должно быть: информации на входе столько же — один предыдущий символ. Просто
для биграмм вероятности можно посчитать напрямую и хранить в таблице, а градиентный подход гибче. Его можно
расширять: подавать больше символов и усложнять сеть, а таблица с длинным контекстом разрослась бы до бесконечности.
9. Две заметки, которые связывают обе половины
Заголовок раздела «9. Две заметки, которые связывают обе половины»One-hot × W — это просто выбор строки. Если в one-hot векторе единица стоит на пятом месте, то умножение на
вытаскивает пятую строку . Ровно это делала и модель на счётчиках: брала строку таблицы по номеру символа.
Значит, после обучения — это логарифмы счётчиков, а после нормировки — та же таблица P. Только получена
она не подсчётом, а постепенно, следуя за градиентом loss.
Сглаживание — это регуляризация. Если все веса равны нулю, все логиты нулевые, экспоненты — единицы,
и распределение равномерное. Значит, если тянуть к нулю, распределения будут ровнее, как при большом
сглаживании. Это делает добавка к loss — штраф , регуляризациярегуляризацияEN regularization.
Карпатый описывает её как пружину или гравитацию, которая тянет веса к нулю, пока данные тянут их к своим
вероятностям. Сила штрафа играет ту же роль, что величина фальшивых счётчиков. Курс разбирает обе
заметки в разделе «Шаг 6» урока 4.1.2 и проверяет
первую одной строкой: torch.allclose(X @ W, W[xs]).
10. Генерация из нейросети и вывод
Заголовок раздела «10. Генерация из нейросети и вывод»Генерация меняется в одном месте: строка вероятностей берётся не из P[ix], а из сети — one-hot, умножение на
, экспонента, нормировка. С тем же зерном генератора получаются те же имена, что из таблицы (mor., axx.,
minaymoryles.…). Это одна и та же модель, полученная двумя разными путями.
Итог лекции Карпатый формулирует как обещание. Сейчас нейросеть предельно проста: один символ и один линейный слой. Дальше входом станут несколько символов, а сети будут всё сложнее, вплоть до трансформеров. Но на выходе всегда будут логиты, а дальше — тот же softmax, тот же NLL и та же градиентная оптимизация.
Где курс объясняет то же самое и что есть сверх курса
Заголовок раздела «Где курс объясняет то же самое и что есть сверх курса»| Тема лекции | Где в курсе | Что в лекции сверх курса |
|---|---|---|
| Языковая модель, авторегрессия, n-граммы | 4.1.1 | план серии makemore |
| Биграммы подсчётом, генерация, NLL, сглаживание | 4.1.2 (242 русских имени) | масштаб: 32 тыс. имён, 228 тыс. биграмм; сравнение с равномерной моделью |
| Сэмплирование и генераторы случайных чисел | 4.1.2, 4.1.3 | ловушка replacement=False по умолчанию |
Broadcasting, keepdim | 0.3.2, 4.1.2 | разбор правил по документации PyTorch, деление на месте |
| Правдоподобие, логарифм, softmax, cross-entropy | 1.3.2 | — |
| One-hot, линейный слой, градиентное обучение биграммы | 4.1.2, 3.2.3 | torch.tensor против torch.Tensor, приведение типов one-hot |
| Сглаживание = L2-регуляризация | 4.1.2, модуль 2.1 | образ «пружины», которая тянет веса к нулю |
Что есть в курсе и чего нет в лекции: разбиение на обучение и проверку. Карпатый считает loss только на обучающих данных, а в курсе сглаживание подбирается по отложенной выборке. В лекции это вынесено в упражнения — см. ниже.
Что сделать руками
Заголовок раздела «Что сделать руками»Упражнения из описания видео (их копия с пояснениями на китайском — 002_makemore_Bigrams/bigram_exercises.ipynb
в репозитории karpathy-zero-to-hero-zh-transcripts):
- Триграммы. Обучите модель, которая по двум символам предсказывает третий, подсчётом или нейросетью. Насколько loss лучше, чем у биграммы?
- Честная проверка. Разбейте имена случайно на 80% обучения, 10% валидации и 10% теста. Обучите биграммы и триграммы только на обучающей части и оцените на двух остальных. Что вы видите?
- Подбор сглаживания. По валидации подберите силу сглаживания (или регуляризации) для триграммной модели. Как при этом ведут себя loss на обучении и на валидации? Лучшую модель один раз оцените на тесте.
- Без one-hot. Раз умножение на one-hot просто выбирает строку, уберите
F.one_hotи индексируйтеW[xs]. F.cross_entropy. Посчитайте loss черезtorch.nn.functional.cross_entropyи сравните с ручным. Почему на практике лучше встроенная функция? (Ответ Карпатый даёт в следующей лекции.)- Своя тема. Придумайте и сделайте что-нибудь интересное сами — например, обучите ту же модель на русских именах из урока 4.1.2 и сравните loss с английскими.
Словарик
Заголовок раздела «Словарик»| EN | RU |
|---|---|
| character-level language model | символьная языковая модель |
| bigram | биграмма |
| special token (start / end) | служебный токен (начала / конца) |
| counts, normalize | счётчики, нормировать |
sampling, torch.multinomial, generator, seed | сэмплирование, генератор, зерно |
broadcasting, keepdim | broadcasting (растягивание форм), сохранить ось |
| in-place operation | операция на месте |
| likelihood, log likelihood | правдоподобие, лог-правдоподобие |
| negative log likelihood (NLL) | отрицательное лог-правдоподобие |
| maximum likelihood estimation | метод максимального правдоподобия |
| model smoothing, fake counts | сглаживание модели, фальшивые счётчики |
| one-hot encoding | one-hot кодирование |
| logits (log-counts) | логиты («логарифмы счётчиков») |
| softmax | softmax |
| regularization loss | штраф регуляризации |