Spinning Up: как стать исследователем глубокого RL
Эссе Джоша Ачиама (OpenAI, 2018): какая нужна подготовка, почему учиться надо на собственных реализациях, как отлаживать RL-код, как выбрать исследовательский проект и как ставить честные эксперименты.
Джош Ачиам, 13 октября 2018 года
Если вы мечтаете стать исследователем в области глубокого RL, вы, вероятно, уже слышали о нём самое разное. Вы знаете, что это трудно и не всегда работает. Что даже когда вы следуете рецепту, воспроизводимость остаётся проблемой. И что если начинать с нуля, кривая обучения невероятно крутая. Верно и то, что отличных материалов уже немало, но материал настолько новый, что ясного, хорошо размеченного пути к мастерству нет. Цель этой колонки — помочь вам преодолеть начальное препятствие и дать ясное понимание того, как раскрутиться (spin up) до исследователя глубокого RL. В частности, здесь будет описана полезная программа наращивания знаний, перемежаемая всякими мелочами, которые ведут к более качественным исследованиям.
Правильная подготовка
Заголовок раздела «Правильная подготовка»Наберите прочную математическую базу. Из теории вероятностей и статистики вам нужно уверенно владеть случайными величинами, теоремой Байеса, цепным правилом вероятностей, матожиданиями, стандартными отклонениями и выборкой по значимости (importance sampling). Из многомерного анализа — понимать градиенты и (необязательно, но поможет) разложения в ряд Тейлора.
Наберите общие знания по глубокому обучению. Не нужно знать каждый специальный трюк и каждую архитектуру, но основы помогают. Знайте стандартные архитектуры (MLP, простую RNN, LSTM (см. также этот блог), GRU, свёрточные слои, ResNet, механизмы внимания), распространённые регуляризаторы (weight decay, dropout), нормализацию (batch norm, layer norm, weight norm) и оптимизаторы (SGD, SGD с моментом, Adam, другие). Знайте, что такое трюк репараметризации.
Освойтесь хотя бы с одной библиотекой глубокого обучения. Хорошо начать с Tensorflow или PyTorch. Не нужно уметь всё, но вы должны уверенно писать простую программу обучения с учителем.
Освойтесь с основными понятиями и терминологией RL. Знайте, что такое состояния, действия, траектории, политики, награды, функции ценности и функции ценности действия. Если вы с ними не знакомы, в Spinning Up есть введение в этот материал; стоит также посмотреть RL-Intro с хакатона OpenAI или исключительно подробный обзор Лилиан Венг. Если вы из тех, кто любит математическую теорию, можете дополнительно изучить математику теории монотонного улучшения (на ней основаны продвинутые алгоритмы градиента политики) или классические алгоритмы RL (хотя их вытеснили алгоритмы глубокого RL, в них есть ценные идеи, которые иногда двигают новые исследования).
Учитесь на практике
Заголовок раздела «Учитесь на практике»Пишите собственные реализации. Реализуйте с нуля как можно больше базовых алгоритмов глубокого RL, стремясь написать для каждого самую короткую правильную реализацию. Это безусловно лучший способ понять, как они работают, и выработать интуицию об их особенностях.
Простота критически важна. Организуйте работу так, чтобы сначала реализовать самые простые алгоритмы и лишь постепенно добавлять сложность. Если начать с чего-то со слишком большим числом движущихся частей, велики шансы, что оно сломается и вы потеряете недели на отладку. Это типичная ловушка для новичков в глубоком RL. Если вы в неё попали, не отчаивайтесь — но попробуйте сменить курс и поработать над более простым алгоритмом, а к сложному вернуться позже.
Какие алгоритмы? Начать, вероятно, стоит с vanilla policy gradient (его также называют REINFORCE), DQN, A2C (синхронной версии A3C), PPO (варианта с клиппированной целевой функцией) и DDPG, примерно в таком порядке. Простейшие версии всех этих алгоритмов укладываются в несколько сотен строк кода (примерно 250–300), а некоторые — и в меньше (например, версию VPG без излишеств можно написать примерно в 80 строк). Пишите однопоточный код, прежде чем пробовать параллельные версии этих алгоритмов. (Но хотя бы один попробуйте распараллелить.)
Сосредоточьтесь на понимании. Чтобы написать работающий RL-код, нужно ясное и внимательное к деталям понимание алгоритмов. Дело в том, что сломанный RL-код почти всегда ломается молча: код вроде бы работает нормально, только агент никогда не учится решать задачу. Обычно проблема в том, что что-то считается не по той формуле, или не на том распределении, или данные передаются не туда. Иногда единственный способ найти такие ошибки — читать код критическим взглядом, точно зная, что он должен делать, и найти, где он отклоняется от правильного поведения. Чтобы развить такое знание, нужно работать и с академической литературой, и (когда возможно) с другими существующими реализациями, поэтому заметную часть времени стоит тратить на чтение.
Что искать в статьях. Когда реализуете алгоритм по статье, прочёсывайте её, особенно абляционный анализ и дополнительные материалы (если они есть). Абляции дадут интуицию о том, какие параметры или подпрограммы сильнее всего влияют на то, заработает ли всё, — это поможет диагностировать ошибки. В дополнительных материалах часто есть конкретные детали вроде архитектуры сети и гиперпараметров оптимизации, и стоит постараться привести вашу реализацию в соответствие с ними, чтобы повысить шансы на успех.
Но не переобучайтесь на детали статей. Иногда статья предписывает больше трюков, чем строго необходимо, поэтому относитесь к этому с осторожностью и по возможности пробуйте упрощения. Например, оригинальная статья о DDPG предлагает сложную архитектуру нейросети и схему инициализации, а также batch normalization. Всё это не строго обязательно, и некоторые из лучших опубликованных результатов DDPG получены на более простых сетях. Другой пример: в оригинальной статье об A3C используются асинхронные обновления от разных акторов-учеников (actor-learners), но оказывается, что синхронные обновления работают примерно так же хорошо.
Не переобучайтесь и на существующие реализации. Изучайте существующие реализации ради вдохновения, но не переобучайтесь на их инженерные детали. Библиотеки RL часто выбирают абстракции, удобные для переиспользования кода между алгоритмами, но ненужные, если вы пишете один алгоритм или поддерживаете один сценарий.
Быстро итерируйте в простых средах. Чтобы отлаживать реализации, пробуйте их на простых средах, где обучение должно идти быстро: CartPole-v0, InvertedPendulum-v0, FrozenLake-v0 и HalfCheetah-v2 (с коротким горизонтом — только 100 или 250 шагов вместо полных 1000) из OpenAI Gym. Не пытайтесь запускать алгоритм в Atari или в сложной среде Humanoid, если вы сначала не убедились, что он работает на простейшей игрушечной задаче. Идеальное время на один эксперимент на этапе отладки — меньше 5 минут (на вашей локальной машине) или немногим больше. Такие маленькие эксперименты не требуют особого железа и без проблем идут на CPU.
Если не работает — считайте, что это ошибка в коде. Потратьте много сил на поиск ошибок, прежде чем браться за подстройку гиперпараметров: обычно виновата ошибка. Плохие гиперпараметры могут заметно ухудшить качество RL, но если вы используете гиперпараметры, похожие на те, что в статьях и стандартных реализациях, проблема, скорее всего, не в них. Стоит помнить и то, что иногда в одной среде всё работает даже при критической ошибке, поэтому, когда результаты начнут выглядеть многообещающе, обязательно проверьте больше чем в одной среде.
Меряйте всё. Ставьте много инструментов, чтобы видеть, что происходит внутри. Чем больше статистики процесса обучения вы выводите на каждой итерации, тем легче отлаживать — в конце концов, вы не поймёте, что всё сломано, если не видите, как оно ломается. Лично я люблю смотреть на среднее, стандартное отклонение, минимум и максимум накопленных наград, длин эпизодов и оценок функции ценности, а также на значения функций потерь и детали любых параметров исследования (например, на среднюю энтропию при стохастической оптимизации политики или текущий эпсилон при ε-жадном исследовании, как в DQN). А ещё время от времени смотрите видео того, как действует ваш агент: это даст понимание, которого иначе не получить.
Масштабируйте эксперименты, когда всё работает. Когда у вас есть реализация алгоритма RL, которая, похоже, правильно работает в простейших средах, проверьте её в средах посложнее. Эксперименты на этом этапе займут больше времени — где-то от нескольких часов до пары дней, смотря по обстоятельствам. Тут может пригодиться специализированное железо — мощный GPU или 32-ядерная машина, — и стоит присмотреться к облачным вычислительным ресурсам вроде AWS или GCE.
Сохраняйте эти привычки! Эти привычки стоит сохранить и после того этапа, когда вы только изучаете глубокое RL: они ускорят ваши исследования!
Как выбрать исследовательский проект
Заголовок раздела «Как выбрать исследовательский проект»Когда вы достаточно уверенно освоите основы глубокого RL, пора начинать раздвигать границы и заниматься исследованиями. Для этого вам понадобится идея проекта.
Начните с изучения литературы, чтобы узнать, какие в области есть темы. Тем, которые могут вас заинтересовать, много: эффективность использования данных, исследование среды, перенос обучения, иерархия, память, RL с моделью, метаобучение и многоагентные системы — и это лишь некоторые. Если ищете вдохновение или просто хотите примерно понять, что вообще есть, посмотрите список ключевых статей в Spinning Up. Найдите статью на одну из этих тем, которая вам нравится, — что-то, что вдохновляет, — и прочитайте её внимательно. Используйте раздел о связанных работах и цитаты, чтобы найти близкие статьи и глубоко погрузиться в литературу. Вы начнёте понимать, где нерешённые задачи и где вы можете что-то изменить.
Подходы к генерации идей. Начать думать об идеях проекта можно разными способами, и выбранная рамка влияет на то, как проект может развиваться и с какими рисками столкнётся. Вот несколько примеров.
Рамка 1: улучшение существующего подхода. Это инкрементальный угол: вы пытаетесь получить прирост качества в устоявшейся постановке задачи, подправляя существующий алгоритм. Здесь очень помогает повторная реализация предыдущих работ: она показывает, в чём существующие алгоритмы хрупки и как их можно улучшить. Новичку эта рамка покажется самой доступной, но она может быть полезна исследователям с любым опытом. Хотя некоторые исследователи находят инкрементализм не слишком увлекательным, некоторые из самых впечатляющих достижений машинного обучения получены именно в работах такого рода.
Поскольку такие проекты привязаны к существующим методам, они по своей природе узкие и могут завершиться быстро (за несколько месяцев), что бывает желательно (особенно в начале исследовательского пути). Но отсюда и риски: может оказаться, что задуманные вами правки алгоритма его не улучшают, и тогда, если вы не придумаете новых правок, проект просто закончен, а ясного сигнала, что делать дальше, у вас нет.
Рамка 2: фокус на нерешённых бенчмарках. Вместо того чтобы думать, как улучшить существующий метод, вы ставите цель добиться успеха в задаче, которую ещё никто не решил. Например: добиться идеального обобщения с обучающих уровней на тестовые в домене Sonic или в Gym Retro. Когда вы бьётесь над нерешённой задачей, вы можете перепробовать самые разные методы — и прежние подходы, и новые, придуманные для этого проекта. Новичок вполне может взяться за такую задачу, но кривая обучения будет круче.
У проектов в этой рамке широкие рамки, и они могут длиться долго (от нескольких месяцев до года и больше). Главный риск в том, что бенчмарк может оказаться нерешаемым без существенного прорыва, то есть на него легко потратить много времени без всякого прогресса. Но даже если такой проект проваливается, он часто приводит исследователя ко множеству новых идей, которые становятся плодородной почвой для следующего проекта.
Рамка 3: создание новой постановки задачи. Вместо того чтобы думать о существующих методах или о текущих больших вызовах, придумайте совершенно другую концептуальную задачу, которую ещё не изучали. Затем разберитесь, как добиться в ней прогресса. Для таких проектов стандартного бенчмарка, скорее всего, ещё нет, и вам придётся его разработать. Это может быть огромной трудностью, но за неё стоит взяться — отличные бенчмарки двигают вперёд всю область.
Задачи в этой рамке появляются тогда, когда появляются: специально искать их трудно.
Не изобретайте велосипед. Когда у вас появилась хорошая идея, которую хочется начать проверять, — это здорово! Но пока вы на ранних стадиях, как можно тщательнее проверьте, что её ещё не реализовали. Бывает очень обидно пройти полпути и только тогда узнать, что статья о вашей идее уже есть. Особенно досадно, когда работа шла параллельно, а так время от времени случается! Но пусть это вас не останавливает — и уж точно пусть не подталкивает застолбить место недоделанным исследованием и преувеличить достоинства частичной работы. Делайте хорошие исследования и доводите проекты до полного и тщательного исследования: именно это считается и, безусловно, важнее всего в долгосрочной перспективе.
Как вести строгие исследования в RL
Заголовок раздела «Как вести строгие исследования в RL»Итак, у вас есть идея, и вы почти уверены, что её ещё не реализовали. Вы используете приобретённые навыки, чтобы её реализовать, и начинаете проверять на стандартных доменах. Похоже, работает! Но что это значит и насколько хорошо оно должно работать, чтобы быть важным? Это одна из самых трудных частей исследований в глубоком RL. Чтобы подтвердить, что ваше предложение — значимый вклад, нужно строго доказать, что оно действительно даёт выигрыш в качестве по сравнению с самым сильным возможным базовым алгоритмом — тем, что сейчас достигает SOTA (state of the art, лучшего известного результата) на ваших тестовых доменах. Если вы придумали новый тестовый домен и прежнего SOTA нет, всё равно нужно попробовать самый надёжный алгоритм из литературы, который мог бы правдоподобно хорошо справиться в новом домене, — и затем превзойти его.
Сравнивайте честно. Если вы реализуете базовый алгоритм с нуля, а не сравниваетесь напрямую с числами из чужой статьи, важно потратить на настройку базового алгоритма столько же времени, сколько на настройку своего. Так сравнение будет честным. Кроме того, старайтесь держать «всё остальное равным», даже если между вашим алгоритмом и базовым есть существенные различия. Например, если вы исследуете варианты архитектуры, держите число параметров модели примерно одинаковым у вашей модели и у базовой. Ни в коем случае не ставьте базовый алгоритм в невыгодное положение! Оказывается, базовые алгоритмы в RL довольно сильные, и получить над ними большие и устойчивые победы бывает трудно или требует хорошего понимания устройства алгоритмов.
Исключите случайность как мешающий фактор. Остерегайтесь того, что случайные зёрна (random seeds) заставят результаты выглядеть сильнее или слабее, чем они есть, поэтому запускайте всё на многих зёрнах (минимум 3, а если хотите основательности — 10 или больше). Это действительно важно и заслуживает особого внимания: глубокое RL во многих распространённых сценариях довольно хрупко относительно случайного зерна. Разброс может быть настолько большим, что две разные группы зёрен дают кривые обучения, различающиеся так сильно, будто они вообще не из одного распределения (см. рисунок 10 здесь).
Ставьте эксперименты с высокой добросовестностью. Не берите для статьи результаты только лучших или самых интересных запусков. Вместо этого запустите новые, финальные эксперименты — для всех методов, которые собираетесь сравнивать (если сравниваетесь со своими реализациями базовых алгоритмов), — и заранее обязуйтесь сообщить о результате, каким бы он ни был. Это слабая форма предварительной регистрации (preregistration): этап настройки вы используете, чтобы выдвинуть гипотезы, а финальные запуски — чтобы сделать выводы.
Проверяйте каждое утверждение отдельно. Ещё один критически важный аспект исследований — абляционный анализ. В любом предложенном методе, скорее всего, есть несколько ключевых проектных решений — например, выбор архитектуры или техники регуляризации, — каждое из которых может отдельно влиять на качество. Утверждение вашей работы — что эти решения вместе помогают, — на самом деле замаскированная связка нескольких утверждений, по одному на каждый элемент устройства. Систематически оценивая, что будет, если заменить их альтернативными решениями или убрать совсем, вы поймёте, как правильно распределить заслуги за выигрыш, который даёт ваш метод. Это позволяет делать каждое отдельное утверждение с определённой уверенностью и повышает общую силу вашей работы.
Заключительные мысли
Заголовок раздела «Заключительные мысли»Глубокое RL — увлекательная, быстро развивающаяся область, и нам нужно как можно больше людей, которые возьмутся за открытые задачи и продвинутся в них. Надеемся, после этого текста вы чувствуете себя чуть лучше подготовленными, чтобы стать её частью! А когда будете готовы, дайте нам знать.
P. S. Другие материалы
Заголовок раздела «P. S. Другие материалы»Подумайте о том, чтобы прочитать и другие полезные статьи о том, как расти исследователем или инженером в этой области:
- Advice for Short-term Machine Learning Research Projects («Советы для краткосрочных исследовательских проектов в машинном обучении»), Тим Рокташель, Якоб Фёрстер и Грег Фаркуар.
- ML Engineering for AI Safety & Robustness: a Google Brain Engineer’s Guide to Entering the Field («ML-инженерия для безопасности и надёжности ИИ: руководство инженера Google Brain по входу в область»), Кэтрин Олссон и 80,000 Hours.
Источники
Заголовок раздела «Источники»Названия работ оставлены в оригинале.
- Deep Reinforcement Learning Doesn’t Work Yet, Alex Irpan, 2018
- Reproducibility of Benchmarked Deep Reinforcement Learning Tasks for Continuous Control, Islam et al, 2017
- Deep Reinforcement Learning that Matters, Henderson et al, 2017
- Lessons Learned Reproducing a Deep Reinforcement Learning Paper, Matthew Rahtz, 2018
- UCL Course on RL
- Berkeley Deep RL Course
- Deep RL Bootcamp
- Nuts and Bolts of Deep RL, John Schulman
- Stanford Deep Learning Tutorial: Multi-Layer Neural Network
- The Unreasonable Effectiveness of Recurrent Neural Networks, Andrej Karpathy, 2015
- LSTM: A Search Space Odyssey, Greff et al, 2015
- Understanding LSTM Networks, Chris Olah, 2015
- Empirical Evaluation of Gated Recurrent Neural Networks on Sequence Modeling, Chung et al, 2014 (статья о GRU)
- Conv Nets: A Modular Perspective, Chris Olah, 2014
- Stanford CS231n, Convolutional Neural Networks for Visual Recognition
- Deep Residual Learning for Image Recognition, He et al, 2015 (ResNet)
- Neural Machine Translation by Jointly Learning to Align and Translate, Bahdanau et al, 2014 (механизмы внимания)
- Attention Is All You Need, Vaswani et al, 2017
- A Simple Weight Decay Can Improve Generalization, Krogh and Hertz, 1992
- Dropout: A Simple Way to Prevent Neural Networks from Overfitting, Srivastava et al, 2014
- Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift, Ioffe and Szegedy, 2015
- Layer Normalization, Ba et al, 2016
- Weight Normalization: A Simple Reparameterization to Accelerate Training of Deep Neural Networks, Salimans and Kingma, 2016
- Stanford Deep Learning Tutorial: Stochastic Gradient Descent
- Adam: A Method for Stochastic Optimization, Kingma and Ba, 2014
- An overview of gradient descent optimization algorithms, Sebastian Ruder, 2016
- Auto-Encoding Variational Bayes, Kingma and Welling, 2013 (трюк репараметризации)
- Tensorflow
- PyTorch
- Spinning Up in Deep RL: Introduction to RL, Part 1
- RL-Intro — слайды с хакатона OpenAI, Josh Achiam, 2018
- A (Long) Peek into Reinforcement Learning, Lilian Weng, 2018
- Optimizing Expectations, John Schulman, 2016 (теория монотонного улучшения)
- Algorithms for Reinforcement Learning, Csaba Szepesvari, 2009 (классические алгоритмы RL)
- Benchmarking Deep Reinforcement Learning for Continuous Control, Duan et al, 2016
- Playing Atari with Deep Reinforcement Learning, Mnih et al, 2013 (DQN)
- OpenAI Baselines: ACKTR & A2C
- Asynchronous Methods for Deep Reinforcement Learning, Mnih et al, 2016 (A3C)
- Proximal Policy Optimization Algorithms, Schulman et al, 2017 (PPO)
- Continuous Control with Deep Reinforcement Learning, Lillicrap et al, 2015 (DDPG)
- RL-Intro Policy Gradient Sample Code, Josh Achiam, 2018
- OpenAI Baselines
- rllab
- OpenAI Gym
- OpenAI Retro Contest
- OpenAI Gym Retro
- Center for Open Science — объяснение, что такое предварительная регистрация научных экспериментов.