Глубокое Q-обучение

Добро пожаловать на мой курс обучения с подкреплением ❤️

Это пятая часть практического курса по обучению с подкреплением, который проведет вас с нуля до HERO 🦸‍♂️.

Часть 1: Введение в обучение с подкреплением
Часть 2: Табличное Q-обучение
Часть 3: Табличное SARSA
Часть 4: Линейное Q-обучение
👉🏻 Часть 5: Глубокое Q-обучение (сегодня)

В части 4 мы создали неплохой агент для среды Cart Pole. Мы использовали параметрическое обучение Q с линейной моделью.

Сегодня мы заменим эту линейную модель нейронной сетью.

И мы круто решим среду Cart Pole 😎

Сегодняшний урок немного длиннее, так как включает мини-ускоренный курс по обучению моделей нейронных сетей. Если вы не являетесь экспертом в области глубокого обучения, я настоятельно рекомендую вам не пропускать его.

Весь код для этого урока находится в этом репозитории Github. Git клонирует его, чтобы решить сегодняшнюю проблему.

И если вам понравился курс, пожалуйста, поставьте ему ⭐ на Github!

Сделайте большой глоток ☕. Мы готовы начать!

Часть 5

Содержание

  1. Давайте углубимся!
  2. Практическое введение в глубокое обучение
  3. Deep Q учится решать Cart Pole
  4. Резюме ✨
  5. Домашнее задание 📚
  6. "Что дальше? ❤️»

1. Давайте углубимся!

В предыдущем уроке мы использовали эту линейную параметризацию для представления оптимальной функции q.

Это небольшая модель всего с 10 параметрами.

Успех (или неудача) параметрического агента Q-обучения сильно зависит от параметризации, которую мы используем для аппроксимации функции оптимального значения q.

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

И тут в игру вступают нейронные сети.

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

Универсальная аппроксимационная теорема📘 это математический результат, который, по сути, говорит

Нейронные сети настолько гибки, насколько вы хотите. Если вы создадите достаточно большую нейронную сеть (т. е. с достаточным количеством параметров), вы обнаружите точное соответствие между входными функциями и целевыми значениями.

Или, если вы предпочитаете более философский подход…

Сегодня мы собираемся заменить линейную модель из части 4 самой простой архитектурой нейронной сети: нейронной сетью с прямой связью.

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

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

Если вы действительно один из них, не стесняйтесь пропустить следующий раздел и сразу перейти к разделу 3.

В противном случае, давайте разогреем наше мастерство глубокого обучения следующей задачей на имитацию обучения, которую я создал сегодня.

Предстоит охватить довольно много, так что вооружитесь глубоким вниманием.

2. Практическое введение в глубокое обучение: изучение оптимальной политики на основе размеченных данных

👉🏽 блокноты/05_crash_course_on_neural_nets.ipynb

В этом разделе мы решим проблему контролируемого машинного обучения с использованием глубокого обучения.

Но почему бы нам просто не решить проблему с тележкой? 🤔

Ключевое различие между задачей Supervised ML и оптимизацией, которую мы решаем при параметрическом Q-обучении, заключается в том, что в Supverside ML цели фиксированы, в то время как при параметрическом Q-обучении ониНЕ фиксированы, но двигаться.

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

В контролируемом машинном обучении у вас есть набор данных пар (входные данные, выходные данные), и вы хотите найти правильное сопоставление между входными данными (также известными как функции ) и выходные данные (так называемые цели/метки).

Хорошо, какую проблему контролируемого машинного обучения мы собираемся решить?

Я взял идеального глубокого агента, которого мы будем обучать в следующем разделе (он же идеальный агент), и сгенерировал выборку из 1000 состояний (входные данные) с соответствующими действиями, предпринятыми этим идеальным агентом ( выходы). Из этой выборки наблюдений мы хотим узнать основную оптимальную политику, которой следует агент.

Думайте об этом как о проблеме имитации обучения. Вам дается 1000 образцов (состояние, действие) из экспертной работы, и ваша задача состоит в том, чтобы изучить основную стратегию, которой следует агент.

Хватит болтать. Давайте посмотрим на код. Сначала мы увидим, как генерировать обучающие данные. Затем мы обучим несколько моделей нейронных сетей и извлечем некоторые знания.

2.1 Генерация данных поезда

Как обычно начинаем с загрузки окружения

Чтобы сгенерировать обучающие данные, нам сначала нужно получить идеальные параметры агента (и гиперпараметры). Я загрузил их на общедоступный Google Диск, к которому у вас есть доступ, и откуда вы можете скачать их следующим образом:

В path_to_agent_data у вас есть 2 файла:

  • model → сохраненная модель PyTorch с параметрами параметрической функции, в данном случае нейросети.
  • hparams.json → гиперпараметры, используемые для обучения агента

Теперь вы можете создать экземпляр объекта QAgent из этих параметров (и гиперпараметров) следующим образом:

Прежде чем идти дальше, я хочу, чтобы вы поверили мне, когда я скажу, что агент идеален. Давайте оценим его в 1000 случайных эпизодах и проверим общую награду.

500 — это максимальная суммарная награда, и наши агенты получали ее во всех 1000 эпизодах. Фантастика! Вам нужно будет дождаться следующего раздела, чтобы самостоятельно обучить этого идеального агента.

Теперь мы позволяем агенту взаимодействовать с окружающей средой в течение нескольких эпизодов, пока не соберем 1000 пар (состояние, действие). Вот как мы генерируем наши данные о поездах.

Функция generate_state_action_data генерирует CSV-файл, который выглядит следующим образом:

Где:

  • s1, s2, s3, s4 — входные объекты, а
  • action — это цель, в данном случае двоичная цель (0 или 1). Мы будем решать проблему бинарной классификации.

Теперь, прежде чем мы перейдем к моделированию, нам еще нужно сделать кое-что.

Когда вы обучаете модели машинного обучения с учителем (особенно нейронные сети) и хотите правильно оценить их точность, вы НЕ МОЖЕТЕ использовать тот же набор данных, который использовался для их обучения.

Почему?

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

Чтобы решить эту проблему, мы создаем другой набор данных, называемый тестовыми данными, который мы не используем для настройки каких-либо параметров модели. Тестовые данные используются исключительно для оценки производительности модели.

Мы генерируем так же, как набор поездов.

Обратите внимание, как мы использовали другое начальное число, чем для train.csv , чтобы гарантировать, что мы не генерируем одни и те же образцы для обучающих и тестовых наборов данных.

Прохладный. Мы получили данные. Перейдем к части моделирования.

2.2. Моделирование

Как мы всегда делаем в наших задачах обучения с подкреплением, лучше всего начать с создания быстрой базовой модели, чтобы понять, насколько сложна проблема.

Давайте загрузим файлы CSV:

Если мы проверим данные поезда, мы увидим, что целевое значение (то есть оптимальное действие) имеет полностью сбалансированное распределение.

Это означает, что очень фиктивная базовая модель, которая всегда предсказывает действие = 0 (или действие = 1), имеет точность 50 %, что означает, что предсказание модели соответствует правильной метке в 50 % случаев.

Загрузка данных в вашу модель PyTorch

Прежде чем мы перейдем к моделям, нам нужно построить данные конвейер, чтобы быстро перемещать данные пакетами из фреймов данных pandas в нашу модель PyTorch. .

PyTorch API предлагает 2 вспомогательных объекта, которые позволяют легко это сделать:

  • torch.utils.data.Dataset → удобная оболочка вокруг фрейма данных вашей панды. Он извлекает функции фрейма данных и маркирует один образец за раз.
  • torch.utils.data.DataLoader → выполняет за вас всю тяжелую работу, перемещая данные из Dataset в модель Pytorch партиями. Он использует библиотеку Python multiprocessing для ускорения поиска данных.

Нам нужны два конвейера данных, один для данных поезда и один для тестовых данных.

Мы создаем собственный класс Dataset и реализуем 3 обязательных метода: __init__(), __len__() и __getitem__(idx)..

Затем мы создаем 2 объекта Dataset:

DataLoaders еще проще реализовать, так как нам нужно только объявить их следующим образом:

Хороший! Конвейеры данных готовы. Теперь у нас есть способ быстро перемещать данные пакетами и передавать их в модели, которые мы будем строить.

Все модели будут обучаться с использованием кросс-энтропийной функции потерь, которая является стандартным выбором для задач классификации.

Мы будем использовать TensorBoard для визуализации показателей обучения и тестирования (потери и точность). Несмотря на то, что он был разработан Google для своей платформы DL TensorFlow, Tensorboard имеет очень аккуратную интеграцию с PyTorch.

2.2.1 Линейная модель → 10 параметров

Это наш первый кандидат на изучение оптимальной политики.

Мы создаем модель PyTorch следующим образом:

Мы обучаем эту модель на 150 эпох. Эпоха — это полный проход по всем данным поезда. Следовательно, мы собираемся использовать каждую выборку в обучающих данных 150 раз, чтобы настроить параметры модели.

В конце каждой эпохи мы вычисляем потери и точность модели, используя тестовые данные. Таким образом мы получаем оценку насколько хороша модель.

Давайте запустим сервер Tensorboard, чтобы визуализировать метрики обучения и тестирования. Мы можем сделать это из блокнота Jupyter, используя

Примечание: вы можете запустить Tensorboard прямо из командной строки, если хотите, и перейти к URL-адресу, напечатанному на консоли, в моем случае localhost:6009/

Откройте Tensoboard и выберите последний запуск. Вы должны увидеть эти 2 графика:

  • Точность данных о поездах, пакет за пакетом. Он стабилизируется около 70%.

  • Точность тестовых данных, пакет за пакетом. Он также стабилизируется на уровне около 70%. Это число больше, чем базовый уровень в 50%, поэтому модель чему-то учится.

70% не так уж и плохо, но и далеко не идеально.

💡Совет: отображайте метрики поезда для обнаружения ошибок
Всегда отображайте точность и потери поезда, так как это может помочь вам найти ошибки в коде. Если точность (потери) не увеличивается (уменьшается) после каждой эпохи, это означает, что ваша сеть не обучается. Вероятно, это связано с ошибкой в ​​вашем коде, которую необходимо исправить.

🧠 Обучение: недостаточное соответствие данных поезда
Если модель слишком мала для задачи, мы наблюдаем плато точности обучения и тестирования на скромном уровне, в этом случай 70%. Мы говорим, что модель не соответствует данным, и нам нужно попробовать более крупную модель.

Давайте расширим сеть, чтобы улучшить результаты.

2.2.2 Нейронная сеть с 1 скрытым слоем → 1795 параметров

Мы создаем нейронную сеть с одним скрытым слоем с 256 единицами:

Обучаем 150 эпох и потом идем в Tensorboard проверять метрики

  • Точность тестовых данных. Мы улучшили показатели с 70 % до примерно 85 %.

85% выглядит намного лучше. Но все же я думаю, что мы можем добиться большего. Давайте попробуем более крупную нейронную сеть.

2.2.3 Нейронная сеть с 2 скрытыми слоями → 67 586 параметров

Вы увидите, что его точность тестирования достигает 90 %.

Увеличение размера сети кажется разумной стратегией. Давайте сделаем еще один шаг и добавим еще один слой.

2.2.4 Нейронная сеть с 3 скрытыми слоями → 133 378 параметров

Если вы проверите его точность на тестовых данных, вы увидите, что она достигает 90%. Следовательно, эта модель не улучшает наши лучшие результаты.

Интуитивно кажется, что наша предыдущая модель с двумя скрытыми слоями и примерно 67 тысячами параметров достаточно хорошо справлялась со своей задачей. Использование более сложной модели на самом деле не дает лучших результатов.

🧠 Обучение: переобучение данных поезда
Если ваша модель слишком велика по сравнению с объемом обучающих данных, вы подгоните данные поезда. Чтобы обнаружить переобучение, посмотрите на поезд и проверьте потери.
Если потери в поезде продолжают уменьшаться, а тестовые потери остаются на плато, это означает, что вы начали переоснащать.

Мы можем проверить переоснащение в этом случае, посмотрев на поезд и проверив потери:

  • Потери данных о поездахпочти достигают 0.

  • Потери на тестовых данных стабилизировались на уровне 0,3, что соответствует предыдущей модели с двумя скрытыми слоями.

💡Совет. Собирайте больше данных, чтобы улучшить результаты

Наиболее эффективной стратегией улучшения модели нейронной сети является использование большего набора поездов. Этот совет применим к любой модели машинного обучения, а не только к нейронным сетям. Тем не менее, нейронные сети больше всего выигрывают от больших наборов поездов, поскольку они очень параметричны и гибки, чтобы адаптироваться к самым сложным шаблонам в данных.

Как видите, нужно немало поэкспериментировать, чтобы найти правильную архитектуру нейронной сети для решения проблемы.

Вы можете спросить…

Есть ли систематический способ найти правильную архитектуру для моих данных?

Да, есть. В этом разделе мы перешли от маленьких моделей к большим моделям, чтобы постепенно усложнять их. Однако на практике следует идти другим путем.

💡Совет: переходите от большого к меньшему

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

У Andrej Karpathy есть очень хорошая запись в блоге на эту тему, которую я настоятельно рекомендую вам прочитать
📝 Рецепт обучения нейронных сетей

Я надеюсь, что после этого раздела вы лучше поймете, как обучать модели нейронных сетей.

Я рекомендую вам просмотреть код в src/supervised_ml.py, чтобы закрепить то, что мы рассмотрели в этом разделе. Обучение моделей нейронных сетей в контролируемой среде — очень практичный пример использования глубокого обучения в реальном мире. Потренируйтесь 100 раз и дайте мне знать, если у вас есть вопросы 📩.

В следующем разделе мы вернемся к задаче о столбе тележки.

Готовы ли вы смешать RL с тем, что вы только что узнали о нейронных сетях?

3. Глубокое Q-обучение для решения проблемы с телегой

Вернемся к параметрическому Q-learning и Cart Pole.

Мы полностью воспользуемся кодом из части 4, с той лишь разницей, что заменим линейную параметризацию оптимальной функции q

с нейронной сетью с 2 скрытыми слоями

Это будет первый алгоритм глубокого обучения с подкреплением в курсе. В данном случае это Deep Q-сеть.

А как насчет гиперпараметров?

Алгоритмы RL чрезвычайно чувствительны к гиперпараметрам. И Deep Q-learning не исключение.

Я не собираюсь лгать тебе. Поиск правильных гиперпараметров может занять очень много времени. Гиперпараметры критичны в глубоком обучении с подкреплением, и многие авторы не публикуют их. И это очень расстраивает любого, кто выходит на поле.

Даже случайность в обучающем цикле, возникающая, например, из-за перетасовки пакетов данных поезда в памяти, может оказать большое влияние на конечные параметры агента.

Из-за этого мы всегда фиксируем все семена в начале нашего скрипта Python.

Однако этого недостаточно для обеспечения воспроизводимости на разных машинах. Может случиться так, что и вы, и я используем одни и те же гиперпараметры и случайное начальное число, но получим разные модели только потому, что вы тренируетесь на графическом процессоре, а я нет.

Другими словами, полностью воспроизводимые результаты не гарантируются для разных версий PyTorch, разных платформ или аппаратных настроек (GPU и CPU).

Воспроизводимость результатов
Возможно, вы не получите таких же результатов, как я, при использовании точно таких же гиперпараметров, которые я привожу в этом разделе.

Не расстраивайтесь. На следующем уроке мы научимся настраивать гиперпараметры самостоятельно, и вы сможете найти те, которые вам подходят, если они вам не подходят.

Плохие гиперпараметры

👉🏽 блокноты/06_deep_q_agent_bad_hyperparameters.ipynb

Эти гиперпараметры были не самым худшим, что я нашел, определенно. Я называю их плохими, потому что они дают результаты, аналогичные нашей линейной q-модели из части 4.

Какой смысл использовать сложную модель нейронной сети, когда гиперпараметры настроены плохо?

Это гиперпараметры:

Как обычно фиксируем сид

Мы объявляем QAgent из этих гиперпараметров

А мы тренируемся на 200 серий:

Затем мы оцениваем агента на 1000 новых серий.

Результаты неплохие, но мы можем добиться большего.

Давайте сделаем это тогда!

Хорошие гиперпараметры

👉🏽 блокноты/07_deep_q_agent_good_hyperparameters.ipynb

Эти гиперпараметры отлично сработали на моем MacBook:

Как обычно фиксируем сид

Мы объявляем QAgent из этих гиперпараметров

А мы тренируемся на 200 серий:

Если вы оцениваете агента по 1,000 эпизодам

Вы увидите, что он достигает 100% производительности:

Ууууууу!! Офигеть!!!

Это довольно круто. Мы нашли идеального глубокого q-агента в среде CartPole! (И если вы еще не на своем компьютере, дождитесь части 6, и я расскажу о науке и технике, лежащих в основе настройки гиперпараметров 😉).

Это было все на сегодня, ребята.

Хотите узнать больше?

4. Резюме ✨

Вот основные выводы, которые я хочу, чтобы вы извлекли из сегодняшнего урока:

  • Нейронные сети — очень мощные функциональные аппроксиматоры. Вы можете использовать их в полностью контролируемых условиях (например, узнать оптимальную политику из помеченных данных) или как компонент алгоритма RL (например, для аппроксимации оптимальной функции q-значения).
  • Найти правильную архитектуру нейронной сети не просто. Слишком большой (маленький) нейрон вызывает переоснащение (недообучение). В общем, начните с большой сети, которая соответствует обучающим данным. Затем вы начинаете уменьшать его, чтобы повысить точность проверки.
  • Гиперпараметры в глубоком Q-обучении имеют решающее значение для обеспечения сходимости цикла обучения к оптимальному решению. Более того, полная воспроизводимость на разных платформах (например, Windows и Mac), базовом оборудовании (GPU и CPU) и версии PyTorch чрезвычайно сложна, если не возможна в данный момент.

5. Домашнее задание 📚

👉🏽 тетради/08_homework.ipynb

Запачкаем руки:

  1. Git clone репозиторий на локальный компьютер.
  2. Настройка среды для этого урока 03_cart_pole
  3. Откройте 03_cart_pole/notebooks/08_homework.ipynb и попробуйте выполнить 2 задания.

Если вы не являетесь мастером глубокого обучения, я рекомендую вам решить 1-ю задачу. Увеличьте количество данных о поездах и постарайтесь достичь точности не менее 95 % в нашей проблеме имитации.

Во втором задании я предлагаю вам найти более простую нейронную сеть (например, только с одним скрытым слоем), которая может идеально решить проблему CartPole.

6. Что дальше? ❤️

На следующем уроке мы научимся настраивать гиперпараметры как PRO, используя для этого правильные инструменты.

До тех пор,

Люби и учись.

И отдельное спасибо Нерия Узан, за такую ​​преданность курсу. Спасибо за кропотливую работу и обратную связь, которую вы мне даете!

Хотите стать (даже) лучшим специалистом по данным и получить доступ к лучшим курсам по машинному обучению и науке о данных?

👉🏽 Подпишитесь на рассылку datamachines.

👉🏽 Подпишитесь на меня на Medium.

👉🏽 Поставьте ⭐ курсу GitHub repo

Хорошего дня 🧡❤️💙

Пау