Крис Ола: глубокое обучение, NLP и представления
Подробный конспект эссе «Deep Learning, NLP, and Representations»: почему универсальность ничего не объясняет, как эмбеддинги слов сами выучивают сходство и аналогии, общие представления для двух языков и для картинок со словами, рекурсивные сети.
Коротко
Заголовок раздела «Коротко»- Теорема об универсальной аппроксимации не объясняет, почему нейросети работают: она лишь говорит, что сеть может быть таблицей поиска. Таблица запоминает, но не обобщает.
- Настоящее объяснение, по Оле, — представления (representations): сеть сама находит удачный способ записать данные, и в этой записи задача становится простой.
- Лучший пример — эмбеддингиэмбеддинг, векторное представлениеEN embedding слов. Их учат ради скучной задачи («правильная ли это фраза?»), а побочным эффектом получаются близость синонимов и аналогии вида «женщина − мужчина ≈ королева − король».
- Представление, выученное на одной задаче, переносится на другие (предобучение, перенос обучения). И наоборот: разные виды данных — два языка, картинки и слова — можно уложить в одно общее пространство.
- Рекурсивные (древовидные) сети собирают из представлений слов представления фраз и предложений. Обратная задача — восстановить фразу из вектора — в 2014 году только начинала получаться (Cho и др. — будущий seq2seq).
Как читать вместе с курсом
Заголовок раздела «Как читать вместе с курсом»Эссе — идеальное чтение после урока 4.3.1 «Слова как векторы»: вы уже знаете, что такое эмбеддинг и как работают аналогии, а Ола объясняет, почему это важно для всего глубокого обучения. Раздел про универсальность связан с уроком 3.1.1 «Нейрон, слой, MLP», раздел про кодировщик-декодировщик Cho — с уроком 4.1.5, где вы собираете seq2seq сами.
Помните, что эссе написано в 2014 году, до трансформеров. Модели, о которых говорит Ола, давно устарели, но взгляд «глубокое обучение — это обучение представлений» стал общим местом — от BERT до современных LLM.
1. Универсальность — слабый аргумент
Заголовок раздела «1. Универсальность — слабый аргумент»Часто говорят: сеть с одним скрытым слоемскрытый слойEN hidden layerСлой между входом и выходом. Его значения никто не размечал — сеть сама решает, какие признаки в нём строить. универсальна, при достаточном числе нейронов она приблизит любую функцию. Ола называет эту теорему «часто цитируемой и ещё чаще неправильно понимаемой».
Почему она верна, проще всего увидеть на перцептронах — нейронах, которые выдают 1, если взвешенная сумма входов превышает порог, и 0 иначе. Пусть на входе двоичных признаков. Возможных входов конечное число: . Для каждого можно завести в скрытом слое отдельный нейрон, который загорается только на этом входе, а весами от него к выходу задать нужный ответ. Получилась таблица поиска: «увидел вот это — ответь вот так».
flowchart LR x["вход: 3 бита"] --> h1["нейрон для 000"] x --> h2["нейрон для 001"] x --> h3["…"] x --> h8["нейрон для 111"] h1 --> y["выход"] h2 --> y h3 --> y h8 --> y
Для нужно нейронов, для — уже больше миллиарда. (В сноске Ола уточняет, что на практике всё не так плохо: один нейрон может покрывать сразу группу входов. Для сигмоид универсальность тоже верна, но доказывать её сложнее.)
Вывод Олы: сказать «моя модель может то же, что таблица поиска» — значит почти ничего не сказать. Универсальность гарантирует, что сеть может подогнаться под обучающие данные, но ничего не говорит о том, как она поведёт себя на новых данных. Причина успеха глубокого обучения тоньше.
2. Эмбеддинги слов
Заголовок раздела «2. Эмбеддинги слов»Эмбеддинг слова — это функция , которая сопоставляет слову вектор из нескольких сотен чисел (Ола пишет: «возможно, от 200 до 500»). Технически это просто таблица — матрица , где у каждого слова своя строка: . Вначале строки случайные, а осмысленными они становятся в процессе обучения на какой-нибудь задаче.
Задача-предлог. Пример Олы (по работе Леона Ботту, 2011): берём из Википедии фрагменты по пять слов — «cat sat on the mat» — и у половины портим одно слово на случайное: «cat sat song the mat». Сеть должна отличить нормальный фрагмент от испорченного. Устроена она из двух модулей: превращает каждое слово в вектор, а модуль по пяти векторам выдаёт 1 («нормально») или 0 («испорчено»).
flowchart LR w1["cat"] --> W1["W"] w2["sat"] --> W2["W"] w3["song"] --> W3["W"] w4["the"] --> W4["W"] w5["mat"] --> W5["W"] W1 --> R["R"] W2 --> R W3 --> R W4 --> R W5 --> R R --> o["0 — фрагмент испорчен"]
Сама задача неинтересна — разве что для поиска опечаток. Интересна таблица . Ола подчёркивает: можно было взять и другую задачу-предлог, например предсказание следующего слова, — для нас это не важно, важен побочный продукт.
Что оказывается в таблице
Заголовок раздела «Что оказывается в таблице»Похожие слова — рядом. Если спроецировать эмбеддинги на плоскость методом t-SNEt-SNE (стохастическое вложение соседей)EN t-distributed stochastic neighbor embedding (t-SNE)Метод визуализации, сохраняющий соседство точек. Размеры кластеров и расстояния между далёкими кластерами на картинке t-SNE почти ничего не значат., получается карта: числа собираются в одном районе, профессии — в другом. Таблица ближайших соседей (из работы Коллобера и др., 2011) показывает то же: соседи у слова почти всегда родственные по смыслу.
Почему сеть к этому приходит? Замена слова синонимом («a few people sing well» → «a couple people sing well») не меняет правильность фразы. Если кладёт «few» и «couple» рядом, то для модуля вход почти не изменился. Сеть, которая увидела фразу «the wall is blue» и знает, что она правильная, выигрывает, если подтянет «red» поближе к «blue»: тогда и «the wall is red» будет распознана верно.
Это и есть обобщение. Число возможных пятёрок слов астрономическое, а примеров мало. Близость похожих слов позволяет переносить знание с одной фразы на целый класс похожих — и не только заменой синонимов: «the wall is blue» → «the ceiling is red». Ола замечает, что выигрыш растёт экспоненциально с числом заменяемых слов. И формулирует красиво: все слова, которые вы понимаете, вы встречали раньше, но не все предложения, которые вы понимаете, вы встречали раньше. С нейросетями так же.
Аналогии — это разности векторов. Ещё удивительнее (работы Миколова и др., 2013): отношения между словами кодируются постоянным вектором разности:
Читается: «сдвиг от „мужчины“ к „женщине“ примерно такой же, как от „дяди“ к „тёте“ и от „короля“ к „королеве“». Для рода это ещё можно объяснить грамматикой: «she is the aunt», но «he is the uncle», и фраза «she is the uncle» скорее испорчена. Но, как показывает таблица Миколова, так же кодируются и куда более сложные отношения — страна → столица, компания → глава компании. Ола пишет, что это кажется «почти чудом».
Посмотрим на механику с игрушечной таблицей, где координаты подобраны вручную:
import numpy as np
# Игрушечная «таблица эмбеддингов»: строка матрицы θ — вектор слова.# Координаты придуманы вручную: [мужской/женский, королевский, родственник, шум]words = ["король", "королева", "мужчина", "женщина", "дядя", "тётя", "стол"]theta = np.array([ [ 1.0, 1.0, 0.0, 0.1], # король [-1.0, 1.0, 0.0, 0.2], # королева [ 1.0, 0.0, 0.0, 0.0], # мужчина [-1.0, 0.0, 0.0, 0.1], # женщина [ 1.0, 0.0, 1.0, 0.0], # дядя [-1.0, 0.0, 1.0, 0.1], # тётя [ 0.0, 0.0, 0.0, 1.0], # стол])W = {w: theta[i] for i, w in enumerate(words)} # W(слово) = строка таблицы
def nearest(v, exclude): # ищем слово с наибольшим косинусным сходством к вектору v sims = theta @ v / (np.linalg.norm(theta, axis=1) * np.linalg.norm(v)) order = np.argsort(-sims) return next(words[i] for i in order if words[i] not in exclude)
print(W["женщина"] - W["мужчина"]) # «вектор пола»print(W["тётя"] - W["дядя"]) # почти тот же векторv = W["король"] - W["мужчина"] + W["женщина"]print(nearest(v, exclude={"король", "мужчина", "женщина"}))[-2. 0. 0. 0.1][-2. 0. 0. 0.1]королеваЗдесь мы сами вписали «ось пола» в первую координату. Главная мысль Олы в том, что у настоящих эмбеддингов никто ничего не вписывал: близость синонимов и аналогии — побочные эффекты оптимизации простой задачи. Сеть автоматически научилась хорошему способу представлять данные. А хорошее представление, в свою очередь, — ключ к успеху во множестве задач машинного обучения. Как обучить такие векторы самим, вы делаете в уроке 4.3.2.
3. Общие представления
Заголовок раздела «3. Общие представления»Можно ли сделать с эмбеддингами что-то полезное, кроме проверки «правильности» пятёрок слов? Да.
Одно представление — много задач
Заголовок раздела «Одно представление — много задач»Выучив на задаче A, можно взять его готовым и обучить поверх новый модуль для задачи B. Ола цитирует Луонга и др. (2013): представления слов стали «секретным ингредиентом» многих NLP-систем — для распознавания именованных сущностей, разметки частей речи, синтаксического разбора. Этот приём называют по-разному, в зависимости от деталей: предобучение, перенос обученияперенос обученияEN transfer learningБерём модель, обученную на большой задаче (ImageNet), и дообучаем на своей маленькой. Признаки нижних слоёв (края, текстуры) универсальны и переносятся., многозадачное обучение. Его сила — в том, что представление учится сразу на нескольких видах данных.
flowchart LR w["слово"] --> W["W (общий)"] W --> F["F: задача A"] W --> G["G: задача B"]
Много видов данных — одно представление
Заголовок раздела «Много видов данных — одно представление»Обратный приём: учить отображать разные виды данных в одно пространство.
Два языка. В работе Сохера и соавторов (Zou, Socher, Cer, Manning, 2013) обучают два эмбеддинга — английский и китайский — и добавляют условие: слова, про которые известно, что они переводы друг друга, должны оказаться рядом. Конечно, они оказываются рядом — этого и добивались. Интересно другое: рядом оказываются и пары, про которые сеть не знала, что это переводы. Ола объясняет: синонимы тянутся друг к другу, разности вроде «род» кодируются постоянными векторами, и если совместить достаточно много точек, два «облака» слов совпадут по форме. Тогда, если известно, что мужские варианты слов — переводы друг друга, женские тоже встанут на свои места. Это как два одинаковых по форме листа, которые совместили по нескольким булавкам. Для нашего курса пример особенно уместен: речь именно об английском и китайском.
Картинки и слова. Ещё смелее — класть в одно пространство изображения и слова. Классификатор картинок выдаёт не номер класса, а вектор в пространстве эмбеддингов слов: собаки — рядом с вектором «dog», лошади — рядом с «horse».
Самое интересное начинается на классах, которых модель не видела. В работе Сохера и др. (2013) картинки кошек (модель не училась их распознавать) не разбрасываются случайно, а попадают в окрестность вектора «dog» — и при этом близко к вектору «cat». Грузовики оказываются рядом с «truck», который соседствует с «automobile». У стэнфордской группы было всего 8 известных классов и 2 неизвестных. Группа Google сделала большую версию на 1000 классов (DeViSE, Frome и др., 2013), а затем вариант Норузи и др. (2014). Неизвестный класс модели обычно не попадают в точный вектор, но попадают в правильную окрестность — и могут отличить, скажем, эскулапова полоза от броненосца, никогда их не видев. Ола сравнивает это с человеком, который не видел ни того, ни другого, но по словам примерно представляет, как они выглядят. Сегодня это называют zero-shotzero-shot (без примеров)EN zero-shotРешение задачи без обучающих примеров и без дообучения — только по описанию задачи в промпте. С несколькими примерами в промпте — few-shot.-классификацией, а прямой наследник этой идеи — модель CLIP.
Ола добавляет в скобках: всё это использует только сходство слов, а можно было бы использовать и отношения. В пространстве слов есть постоянный «вектор пола», а в пространстве картинок — постоянные визуальные признаки пола. Даже не видев короля, по картинке «королевы с бородой» разумно предположить мужской вариант.
4. Рекурсивные нейросети
Заголовок раздела «4. Рекурсивные нейросети»Модульная сеть из раздела 2 принимает ровно пять слов. Ола обращает внимание, что строить сети из небольших модулей, как из кубиков, в 2014 году было не очень принято, но в NLP это оказалось успешным.
Чтобы снять ограничение на длину, добавим модуль ассоциации : он принимает два представления (слов или фраз) и сливает их в одно того же размера. Применяя снова и снова, получаем представление фразы и даже целого предложения. Сливать слова подряд слева направо не обязательно: фразу «the cat sat on the mat» естественно разобрать по скобкам «((the cat) (sat (on (the mat))))» и применять по этому дереву.
flowchart BT the1["the"] --> A1["A"] cat["cat"] --> A1 the2["the"] --> A2["A"] mat["mat"] --> A2 on["on"] --> A3["A"] A2 --> A3 sat["sat"] --> A4["A"] A3 --> A4 A1 --> A5["A: всё предложение"] A4 --> A5
Такие модели называют рекурсивными (выход модуля снова идёт на вход модуля того же типа) или древовидными нейросетями. Не путайте с рекуррентными (RNN): у рекуррентной сети «дерево» вырождено в цепочку слева направо.
Пример успеха — предсказание тональности предложений по дереву разбора (Сохер и др., 2013): тональность вычисляется в каждом узле, и модель видит, как, например, отрицание переворачивает оценку всей ветки.
Обратимые представления. Большая цель того времени — представление предложения, из которого можно восстановить предложение с тем же смыслом. Для этого нужен модуль «разъединения» , обратный к . Будь он у нас, можно было бы сделать общее представление предложений двух языков и переводить через него. Ола пишет, что это оказалось «очень, очень трудно». Свежий на тот момент прогресс — модель Cho и др. (2014), которая кодирует английскую фразу в вектор и декодирует её по-французски; на карте t-SNE её представления фраз о времени аккуратно группируются по смыслу. Это та самая архитектура «кодировщик — декодировщик», из которой выросли seq2seq, внимание и в итоге трансформер (уроки 4.1.5 и 4.4.1). Кстати, в той же работе Cho впервые предложен GRU.
5. Критика и вывод
Заголовок раздела «5. Критика и вывод»Ола честно отмечает, что слышал критику этих результатов от лингвистов и специалистов по NLP — не самих результатов, а выводов из них и сравнения с другими методами. Сформулировать её сам он не берётся и приглашает критиков в комментарии.
Вывод эссе: взгляд на глубокое обучение через представления отвечает на вопрос, почему глубокие сети так эффективны, — потому что из оптимизации многослойных моделей сами собой появляются лучшие способы представлять данные. Ола признаётся, что находит в этом что-то «чрезвычайно красивое». Пост задуман как подготовка к следующему — о связи глубокого обучения с теорией типов и функциональным программированием (позже вышло эссе «Neural Networks, Types, and Functional Programming»).
Что сделать руками
Заголовок раздела «Что сделать руками»- В уроке 4.3.2 обучите word2vec и проверьте сами: какие слова оказываются ближайшими соседями, работает ли «король − мужчина + женщина».
- Повторите идею двуязычного эмбеддинга на игрушечном уровне: возьмите русские и китайские векторы из мультиязычной модели эмбеддингов (урок 4.3.1) для 10 пар «слово — перевод» и проверьте, ближе ли перевод, чем случайное слово.
- Подумайте над вопросом Олы: почему таблица поиска (раздел 1) не может обобщать, а эмбеддинг — может? Что общего у похожих слов в таблице и чего нет у строк таблицы поиска?
Словарик
Заголовок раздела «Словарик»| EN | RU |
|---|---|
| universality, universal approximation | универсальность, универсальная аппроксимация |
| lookup table | таблица поиска |
| representation | представление |
| word embedding | эмбеддинг слова, векторное представление слова |
| t-SNE | t-SNE — метод визуализации многомерных данных на плоскости |
| analogy, difference vector | аналогия, вектор разности |
| pretraining, transfer learning, multi-task learning | предобучение, перенос обучения, многозадачное обучение |
| shared representation | общее представление |
| bilingual word embedding | двуязычный эмбеддинг слов |
| zero-shot | классификация классов, которых не было в обучении |
| recursive (tree-structured) neural network | рекурсивная (древовидная) нейросеть |
| association / disassociation module | модуль ассоциации / разъединения |
| encoder–decoder | кодировщик — декодировщик |