В предыдущей статье я описал несколько алгоритмов эволюционных стратегий (evolution strategies, ES), помогающих оптимизировать параметры функции без необходимости явно вычислять градиенты. При решении задач обучения с подкреплением (reinforcement learning, RL) эти алгоритмы можно применять для поиска подходящих наборов параметров модели для агента нейросети (neural network agent). В этой статье я расскажу об использовании ES в некоторых RL-задачах, а также опишу методы поиска более стабильных и устойчивых политик.


Эволюционные стратегии в обучении с подкреплением


Поскольку RL-алгоритмам необходимо, чтобы на каждом такте агенту передавался сигнал подкрепления (reward signal), то для этих алгоритмов важно лишь результирующее накопительное подкрепление, получаемое агентом после его прогона в среде. Во многих случаях нам известны лишь выходные данные в конце задачи, например успешно ли отработал агент, взял ли робот-манипулятор объект, выжил ли агент и т. д. Во всех этих задачах ES может быть эффективнее по сравнению с традиционным RL. Ниже я привёл псевдокод, в котором инкапсулирован прогон агента в среде OpenAI Gym. Здесь нас интересует только накопительное подкрепление:


def rollout(agent, env):
  obs = env.reset()
  done = False
  total_reward = 0
  while not done:
    a = agent.get_action(obs)
    obs, reward, done = env.step(a)
    total_reward += reward
  return total_reward

Можно определить rollout как целевую функцию, сопоставляющую параметры модели агента с фитнес-баллами, и использовать ES-решатель (solver) для поиска подходящего набора параметров, как это описано в предыдущей статье:


env = gym.make('worlddomination-v0')

# use our favourite ES
solver = EvolutionStrategy()

while True:

  # ask the ES to give set of params
  solutions = solver.ask()

  # create array to hold the results
  fitlist = np.zeros(solver.popsize)

  # evaluate for each given solution
  for i in range(solver.popsize):

    # init the agent with a solution
    agent = Agent(solutions[i])

    # rollout env with this agent
    fitlist[i] = rollout(agent, env)

  # give scores results back to ES
  solver.tell(fitness_list)

  # get best param & fitness from ES
  bestsol, bestfit = solver.result()

  # see if our task is solved
  if bestfit > MY_REQUIREMENT:
    break

Детерминистические и стохастические политики


Результат наблюдения за средой — это входные данные для агента, а выходные — его действие в каждом такте во время прогона внутри среды. Мы можем смоделировать агента как нам хочется и использовать методы из прописанных в коде правил, деревьев принятия решений и линейных функций для рекуррентных нейросетей. В этой статье я воспользуюсь простой упреждающей нейросетью (feed-forward network) с двумя скрытыми уровнями, чтобы результат наблюдения агента за средой (вектор х) напрямую транслировать в действие (вектор у):


h1=fh(W1x+b1)
h2=fh(W2h1+b2)
y=fout(Wouth2+bout)


Функциями активации fh и fout могут быть tanh, sigmoid, relu или любая другая. Во всех своих экспериментах я использовал tanh. Если будет такая потребность, то можно в выходном уровне в качестве сквозной функции (pass-through function) без нелинейностей взять fout. Если мы конкатенируем все веса и параметры погрешности (bias parameters) в единый вектор W, то увидим, что вышеописанная нейросеть — это детерминистическая функция y=F(x,W). Тогда можно использовать ES для нахождения решения W с помощью цикла поиска, описанного в предыдущей статье.


А если мы не хотим, чтобы политика агента была детерминистической? Для некоторых задач, даже таких простых, как камень-ножницы-бумага, оптимальная политика — случайное действие. То есть агент должен обучаться стохастической политике. Один из способов превращения y=F(x,W) в стохастическую политику заключается в том, чтобы сделать W случайным. Каждый параметр модели wi?W может быть случайным значением, полученным из нормального распределения N(?i,?i).


Такой вид стохастической нейросети называется байесовой нейросетью. Это сеть с предварительным распределением весов. В нашем случае параметры модели, для которой мы ищем решение, являются набором векторов ? и ?, а не весами W. При каждом проходе нейросети мы из N(?,?I) получаем новый W. Есть много интересных работ об использовании байесовых нейросетей для решения разных задач, а также о проблематике обучения этих сетей. ES можно использовать для непосредственного нахождения решений стохастической политики, установив в качестве пространства решений ? и ? вместо W.


Стохастические сети часто встречаются в работах, посвящённых RL. Например, в алгоритме Proximal Policy Optimization (PPO) последний уровень представляет собой набор параметров ? и ?, а также действие, отобранное из N(?,?I). Добавление шума к параметрам может стимулировать агента исследовать среду и избежать локального оптимума.


Я обнаружил, что, когда агент должен исследовать среду, нам зачастую не нужно, чтобы вектор W был совершенно случайным — достаточно лишь погрешности (bias). В трудных задачах, связанных с движением, к примеру в среде roboschool, мне нередко приходится использовать ES для нахождения стохастической политики, при которой из нормального распределения извлекаются лишь параметры погрешности.


Развивающиеся политики устойчивости для двуногого ходока


Это одна из сфер, где ES полезны для нахождения политик устойчивости. Я хочу управлять балансом между эффективностью данных и степень устойчивости политики на протяжении нескольких случайных попыток. Я испытал ES в отличной среде BipedalWalkerHardcore-v2, разработанной Олегом Климовым. Среда использует физический движок Box2D Physics Engine, который применялся и в Angry Birds.



Наш агент решил BipedalWalkerHardcore-v2.


В этой среде наш агент изучал политику хождения без падений по случайно генерируемой полосе препятствий с ограничением по времени. Использовалось 24 входных сигнала: 10 лидарных датчиков, углы и контакт с поверхностью. Агент не знает, в каком месте трассы он находится. Пространство действий (action space) состоит из четырёх непрерывно работающих значений (continuous values), управляющих крутящими моментами четырёх моторов. Суммарное подкрепление (total reward) вычисляется на основе всей пройденной агентом дистанции. Если агент проходит всю трассу, то зарабатывает больше 300 баллов. Правда, будет вычтено немного баллов в зависимости от величины применённого крутящего момента, так что потребление энергии тоже является ограничением.


В BipedalWalkerHardcore-v2 задача считается решённой, если агент набирает в среднем 300 и больше баллов за 100 последовательных случайных попыток. Хотя с помощью RL-алгоритма можно сравнительно легко обучить агента успешно проходить всю трассу, но куда труднее заставить проходить эффективно и со стабильным результатом. Задача получается довольно интересная. Насколько я знаю, по состоянию на октябрь 2017-го мой агент проходит трассу лучше всех.


image
Начало. Учится ходить.


image
Учится исправлять ошибки, но получается ещё медленно...


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


Можно посмотреть на это с другой стороны и увидеть, что хотя мы и протестировали агента на 100 попытках, но попытки были одиночными, так что задача теста не соответствует задаче тренировки, под которую мы оптимизировали нашу систему. Если в стохастическом окружении многократно усреднить каждого агента в популяции, то можно уменьшить разрыв между обучающим и тестовым наборами. Если можно переобучить под обучающий набор, то можно переобучить и под тестовый, тем более в RL с этим нет сложностей :)


Конечно, эффективность данных алгоритма теперь в 16 раз хуже. Но финальная политика стала гораздо устойчивее. Когда я протестировал финальную политику на 100 последовательных случайных попытках, то для прохождения этой среды понадобилось в среднем больше 300 баллов. Без этого усредняющего метода лучший агент на 100 попытках мог набрать ?220—230 баллов. Насколько я знаю, наше решение первым прошло эту среду (по состоянию на октябрь 2017-го).


image



Победившее решение изучалось с помощью PEPG с использованием усреднённого результата по 16 пробегам в эпизоде.


Я также использовал PPO, великолепный алгоритм градиента политики для RL. В меру своих возможностей я постарался настроить его так, чтобы он хорошо работал в моей задаче. Мне удалось добиться только ?240—250 баллов на 100 случайных попытках. Но уверен, что кому-нибудь всё же удастся применить PPO или другой RL-алгоритм для прохождения этой среды.


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


Несколько решений, найденных ES:


image
Решение CMA-ES.


image
Решение OpenAI-ES.


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


image
Двуногий ходок, использующий стохастическую политику.


Хватающий робот-манипулятор Kuka


Я пытался применить комбинацию ES и методики усреднения для решения более простой задачи с роботом-манипулятором Kuka. Эта среда доступна в среде pybullet. Используемая в симуляторе модель Kuka соответствует настоящему манипулятору Kuka. В этой задаче агент получает координаты объекта.


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


image
Задача хватания манипулятором, использующая стохастическую политику.


Если агент успешно хватает объект, то получает 10 000 баллов, а если нет, то 0. Часть баллов отнимается за потребление энергии. Если усреднить подкрепления по 16 случайным попыткам, можно оптимизировать ES с точки зрения устойчивости. Однако в конце концов я смог получить политику, при которой объект хватается примерно в 70—75 % случаев при детерминистической и стохастической политиках. Есть ещё к чему стремиться.


Обучаем Minitaur нескольким задачам


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


image
Агенты Шаолиня.


image
Обучение дрифту.


Недавняя работа, посвящённая самостоятельно играющим агентам, доказывает, что агенты, освоившие трудные задачи наподобие борьбы сумо (а этот спорт требует многих навыков), способны выполнять без дополнительного обучения более простые задачи вроде сопротивления ветру при ходьбе. Эрвин Куманс недавно пытался экспериментировать с добавлением утки на крышку Minitaur, который учится ходить. Если утка падает, то задание не засчитывается. Так что можно надеяться, что подобные дополнения к задаче помогут транслировать изученные политики из симулятора в реального Minitaur. Я взял один из примеров и поэкспериментировал с Minitaur и уткой, для обучения применив ES.


image
Политика хождения CMA-ES в pybullet.


image
Настоящий Minitaur компании Ghost Robotics.


Модель Minitaur в pybullet сделана по образцу настоящего Minitaur. Однако политика, изученная в идеальной виртуальной среде, обычно не работает в реальном мире. У неё даже может не получиться обобщить маленькие дополнения к задаче внутри симулятора. К примеру, в предыдущем ролике Minitaur обучен идти вперёд (с помощью CMA-ES), но эта же политика не всегда позволяет перенести через комнату утку, если положить её в симуляторе поверх робота.


image
Политика хождения работает с уткой.


image
Политика, изученная с помощью утки.


Политика, изученная на простом хождении без утки, ещё как-то работает, когда утку кладёшь на робота, то есть это не слишком усложняет задачу. Утка стоит устойчиво, так что Minitaur’у было не так уж трудно не уронить её. Я пытался заменить утку мячом, чтобы сильно усложнить задачу.


image


image
Учимся обманывать.


Но это не привело к моментальному возникновению стабильной политики балансирования. Вместо этого CMA-ES выработал политику, технически позволяющую перенести мяч, закатив его в углубление между ногами и там его и удерживая. Можно сделать вывод, что алгоритм, ищущий решение в соответствии с поставленной целью (objective-driven search algorithm), научится использовать любые конструктивные недостатки среды ради выполнения задачи.


image
Стохастическая политика, изученная на мяче.


image
Та же политика, но с уткой.


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


ESTool


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


Python’овская библиотека multiprocessing позволяет запускать процессы параллельно. Я предпочитаю запускать отдельные Python-процессы по каждой задаче с помощью Message Passing Interface (MPI) и mpi4py. Это позволяет обойти глобальную блокировку интерпретатора и быть уверенным, что каждый процесс получит собственные экземпляры-песочницы numpy и gym, а это важно, когда речь идёт об инициализации генераторов случайных чисел.


image
Roboschool Hopper, Walker, Ant.


image
Roboschool Reacher.


Агенты с помощью estool обучались на разных roboschool-задачах.


Я реализовал простой инструмент estool, который с помощью описанной в предыдущей статье библиотеки es.py обучает простые сети со сквозной политикой (feed-forward policy networks) выполнять имеющие gym-интерфейс RL-задачи с постоянным управлением (continuous control RL tasks). Я использовал estool для упрощения обучения во всех описанных выше экспериментах, а также в различных задачах с постоянным управлением внутри gym и roboschool. estool использует MPI для распределённой обработки, поэтому для раскидывания воркеров по разным машинам не нужно много телодвижений.


ESTool с pybullet


GitHub


Кроме сред, поставляемых с gym и roboschool, estool хорошо работает с большинством сред pybullet gym. Можно модифицировать имеющиеся pybullet-среды, чтобы получить более подходящие для ваших задач. Например, я без усилий сделал среду с Minitaur, носящим мяч (в директории custom_envs в репозитории). Простота настройки сред облегчает проверку новых идей. Если хотите внедрить 3D-модели из других программных пакетов вроде ROS или Blender, то можете создать новые интересные pybullet-среды и предложить другим пройти их.


Многие модели и среды в pybullet, например Kuka и Minitaur, смоделированы по образу и подобию настоящих роботов для переноса в них текущих знаний обученных алгоритмов. Фактически во многих свежих исследованиях (1, 2, 3, 4) pybullet используется для управления экспериментами по переносу знаний.


Но чтобы поэкспериментировать с переносом знаний из симуляторов в реальные устройства, вам не нужно обзаводиться дорогими роботами. В pybullet есть модель racecar, созданная по мотивам аппаратного open source-набора MIT racecar. Есть даже pybullet-среда, монтирующая виртуальную камеру на виртуальную гоночную машину, чтобы у агента был виртуальный экран в качестве входного средства наблюдения.


Попробуем сначала более простую версию, где машине нужно лишь изучить политику движения к гигантскому мячу. В среде RacecarBulletEnv-v0 агент получает на вход относительные координаты мяча, а на выходе — непрерывные действия по управлению скоростью мотора и направлением руля. Задача простая, обучение на 2014 Macbook Pro (с восьмиядерным процессором) занимает 5 минут (50 поколений). Если применять estool, то эта команда запустит обучение в восьми процессах и присвоит каждому процессу по 4 задачи, в результате получится 32 воркера. Для развития политик используется CMA-ES:


python train.py bullet_racecar -o cma -n 8 -t 4 

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


python model.py bullet_racecar log/bullet_racecar.cma.1.32.best.json 

image
Среда pybullet racecar, по мотивам MIT Racecar.


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


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


image


image


Стандартная задача движения аналогична используемым в roboschool вроде Inverted Pendulum. Также в pybullet есть Hopper, Walker, HalfCheetah, Ant и Humanoid. Я выработал политику для Ant, которая с помощью PEPG за час доходит до 3000 баллов на многоядерной машине, с популяцией из 256 агентов:


python train.py bullet_ant -o pepg -n 64 -t 4

image


image


Пример пробега по AntBulletEnv. С помощью gym.wrappers.Monitor можно записывать пробеги в MP4-видео.


image


image


Заключение


В этой статье я рассказал, как с помощью ES вырабатывать политики для агентов сквозных нейросетей, чтобы выполнять различные RL-задачи с постоянным управлением, определяемые интерфейсом gym. Я описал инструмент estool, он позволяет мне с помощью MPI-фреймворка в распределённой вычислительной среде быстро опробовать ES-алгоритмы с разными настройками.


Пока я описал только методы обучения агентов посредством проб и ошибок. Такая форма обучения с нуля называется обучением с подкреплением без использования моделей (model-free). В следующей статье (если я её вообще напишу) я подробнее расскажу об обучении на основе моделей, когда для выполнения текущей задачи агент учится использовать ранее обученную модель. И да, я снова буду применять эволюционные алгоритмы.


Интересные ссылки


ESTool
Стабильный или устойчивый? В чём разница?
Документация по OpenAI Gym
Эволюционные стратегии в качестве масштабируемой альтернативы обучению с подкреплением
Edward — библиотека для вероятностного моделирования, выводов и критики
История байесовых нейросетей
BipedalWalkerHardcore-v2
roboschool
pybullet
Emergent Complexity посредством соревнования между несколькими агентами
GraspGAN

Комментарии (3)


  1. brickerino
    24.11.2017 18:31

    >Python’овская библиотека multiprocessing позволяет запускать процессы параллельно. Я предпочитаю запускать отдельные Python-процессы по каждой задаче с помощью Message Passing Interface (MPI) и mpi4py. Это позволяет обойти глобальную блокировку интерпретатора и быть уверенным, что каждый процесс получит собственные экземпляры-песочницы numpy и gym, а это важно, когда речь идёт об инициализации генераторов случайных чисел.

    Но Холмс!
    Ведь multiprocessing.Pool и так запускает несколько процессов. Не очень понятно, какую проблему вы здесь решаете.


  1. Aquahawk
    24.11.2017 18:47

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


    1. Hardcoin
      24.11.2017 23:16

      Потому что никто не прикрутил к браузеру обучающий алгоритм. Не может он пока научиться ничему сам.