Обучение с подкреплением (RL) — это эффективный метод решения проблем, требующих от агентов изучения наилучших способов действий в сложных условиях. RLlib — это мощный инструмент для применения обучения с подкреплением к задачам, где есть несколько агентов или когда агенты должны выполнять несколько ролей. Существует множество ресурсов для изучения RLlib с теоретической или академической точки зрения, но не хватает материалов для изучения того, как использовать RLlib для решения собственных практических задач. Этот учебник поможет восполнить этот пробел.

120 лет обучения с подкреплением

Сначала мы проходим через 120 лет работы по обучению с подкреплением. Если вы хотите сразу перейти к RLlib, смело переходите к следующему разделу.

Торндайк заметил, что некоторые виды поведения у животных возникают в результате постепенного затаптывания [Торндайк, 1898]. В психологии эта штамповка стала изучением бихевиоризма [Skinner, 1953] (см. вставку Скиннера, рис. 1). Бихевиоризм был доминирующей парадигмой исследования человеческой психологии и обучения в середине 20 века. Он был сосредоточен только на реакциях, которые можно было наблюдать, и изучал различные условия и режимы тренировок, которые привели к этим реакциям. Он был популярен, потому что не был «пушистым» — можно было делать проверяемые предсказания. Структура бихевиоризма оказалась слишком ограниченной для описания человеческой психологии, но она показала себя как полезная формулировка для обучения искусственных агентов, таких как роботы [Sutton and Barto, 1998], где это называется «обучение с подкреплением» (часто сокращенно RL). .

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

Когда он достигает цели, кредит возвращается к своим предыдущим состояниям, как показано на рис. 3. Агент изучает функцию Q(s,a), которая дает кумулятивное ожидаемое дисконтированное вознаграждение за пребывание в состояние s и принятие мер a и последующее действие в соответствии с текущей политикой. Значения Q(s,a) показаны размером стрелок на рисунке 3.

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

В примерах на предыдущих рисунках было дискретное состояние и пространство действий. Это дискретное пространство состояний является ограничивающим, потому что по мере роста числа переменных, составляющих ваше состояние, размер пространства растет экспоненциально. Это означает, что вы не можете посетить все возможные состояния, не говоря уже о том, чтобы посетить каждое достаточно, чтобы изучить Q(s,a). Из-за этого ограничения современный RL использует нейронные сети, как показано на рисунке 5.

RLlib автоматически создает модели нейронной сети (глубокое обучение) за кулисами на основе вашей конфигурации. В этом руководстве основное внимание уделяется RLlib.

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

Обзор RLlib

RLlib был создан для решения проблемы распределенного RL, описанной в этой статье. Параллельное обучение в RL сложно, потому что вы должны синхронизировать политики. RLlib решает эту проблему с помощью Ray. Ray — это система для параллельного обучения, а RLlib построен поверх нее. Мы видим изображение параллельного обучения на рисунке 6.

Каждая копия среды может работать на другом компьютере. Среда — это то место, где агент фактически действует в мире. Каждый рабочий использует копию текущей политики для выбора действий для агента, которые выполняются в среде. Затем функция вознаграждения определяет, насколько хорошим является результирующее состояние, и выборки данных в виде кортежей (состояние, действие, вознаграждение) отправляются на центральный процессор. Затем центральный процессор использует эти образцы для обновления политики, которая рассылается рабочим процессам на разных машинах. Это обновление политики можно выполнить с помощью TensorFlow или PyTorch.

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

Пример иерархической многоагентной среды

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

Окружающая среда двух роботов на птичьем дворе показана на рисунке 7. Роботы хотят поймать (подойти) к наиболее похожим на них цыплятам. В этом сценарии у каждого робота и каждой курицы есть личность, основанная на модели ОКЕАНА. Награда для роботов заключается в том, что они приближаются к курице, которая имеет такой же характер, как и робот. Робот также наказывается жизнью на каждом временном шаге (он получает небольшое отрицательное вознаграждение за каждый временной шаг), и его вознаграждение, когда он достигает цыпленка, вычисляется как скалярное произведение его личности на личность цыпленка. Например, невротические роботы получают большее вознаграждение за то, что находят таких же невротических цыплят.

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

• Политика высокого уровня: выбери курицу

• Низкоуровневая политика: перейти на цыпленка

Политика высокого уровня видит мир в виде списка цыплят, где личность каждого цыпленка представлена ​​пятимерным вектором, и у каждого цыпленка есть координаты x и y. Пространство действия политики высокого уровня — какую курицу выбрать.

Низкоуровневая политика предназначена для случаев, когда курица уже выбрана, поэтому она видит мир как положение робота x и y и положение выбранного цыпленка, x и y. Пространство действия политики низкого уровня должно идти в 8 направлениях: С, СВ, В, ЮВ, Ю, ЮЗ, З и СЗ.

Эпизод заканчивается, когда оба робота приближаются к курице. Среда отображается в YourTargetSystem и YourAutonomousAgent в репозитории. В следующем разделе мы рассмотрим, как представляются состояние и области действий для обеих политик (Ошибка! Источник ссылки не найден.).

Абстракции RLlib

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

Пространства OpenAI

OpenAI создал платформу OpenAI Gym для обучения с подкреплением несколько лет назад. Gym предоставляет хорошие абстракции, которые переносятся как в StableBaselines3, так и в RLlib.

Первая важная часть Gym — это пробелы, которые упрощают форматирование вашего домена для нейронных сетей. Здесь показаны области наблюдения высокоуровневых и низкоуровневых политик из your_openai_spaces.py.

robot_position_space = spaces.Box(
             shape=(2,),
             dtype=np.float,
             low=0.0,
             high=1.0)
 
 robot_ocean_space = spaces.Box(
             shape=(NUM_OCEAN_FEATURES,),
             dtype=np.float,
             low=0.0,
             high=1.0)
 
 high_level_obs_space = spaces.Dict({
         'chicken_oceans': chicken_ocean_space,
         'chicken_positions': chicken_position_space,
         'robot_ocean': robot_ocean_space,
         'robot_position': robot_position_space,
 })
 
 low_level_obs_space = spaces.Dict({
         'robot_position': robot_position_space,
         'chicken_positions': chicken_position_space,
 })

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

Среда спортзала OpenAI

Второй важной частью OpenAI Gym является класс Env. Env предоставляет единый API для взаимодействия с вашей средой. На рисунке 8 мы видим, что класс Env имеет четыре основных метода.

1. сброс

2. шаг

3. визуализировать

4. закрыть

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

Самый важный метод – ступенчатый. Входными данными для метода является действие, выбранное политикой. Результатом метода является наблюдаемое состояние и вознаграждение. Затем алгоритм обучения использует это наблюдение и вознаграждение для обновления политики. Выходные данные для метода также включают информацию о том, завершен ли эпизод, и любую другую важную информацию, которую вы хотите добавить с помощью настройки. Метод step запускается внутри рабочего процесса на рис. 6.

Ранее я упоминал, что считаю самой интересной частью RLlib ее абстракции для работы с несколькими и иерархическими агентами. RLlib обеспечивает эту функциональность, расширяя класс OpenAI Gym Env для работы с несколькими агентами с помощью класса MultiAgentEnv. В пошаговом методе MultiAgentEnv действия из политик поступают в виде словаря с одним ключом для каждого имени агента. Точно так же передаваемая информация представляет собой словарь с единицами измерения в качестве ключей (подробнее об этом позже).

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

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

В частности, настройка для нашей среды показана на рис. 10. Это сопоставление указано в нашем конфигурационном файле your_rllib_config.py.

Тестирование вашей среды

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

Первоначально мы исключаем RLlib для тестирования, чтобы мы могли убедиться, что среда работает должным образом, как показано в demo/demo_your_rllib_env.py и выдержке ниже.

 env = YourEnvironment(config)
 env.reset()
 
 action_dict = {'robot_1_high': random.choice(range(NUM_CHICKENS)),
                 'robot_2_high': random.choice(range(NUM_CHICKENS))}
 
 obs, rew, done, info = env.step(action_dict)
 env.render()
 
 while not is_all_done(done):
     action_dict = {}
     assert 'robot_1_low' in obs or 'robot_2_low' in obs
     if 'robot_1_low' in obs and not done['robot_1_low']:
         action_dict['robot_1_low'] = \   
             random.choice(range(NUM_DIRECTIONS))
     if 'robot_2_low' in obs and not done['robot_2_low']:
         action_dict['robot_2_low'] = \
             random.choice(range(NUM_DIRECTIONS))
     obs, rew, done, info = env.step(action_dict)
     print("Reward: ", rew)
     time.sleep(.1)
     env.render()

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

Изучение политики

Чтобы обучить свою политику, вы выбираете тренер (алгоритм) и привязываете к нему свою среду. RLlib поставляется с тренажерами для большинства стандартных алгоритмов, таких как Proximal Policy Optimization (PPO) и Deep Q Networks (DQN). Есть два способа запустить трейнер, как показано в your_rllib_train.py и ниже.

if RUN_WITH_TUNE:
 
     tune.registry.register_trainable("YourTrainer", YourTrainer)
     stop = {
             "training_iteration": NUM_ITERATIONS  
             # Each iter is some # of episodes
         }
     results=tune.run("YourTrainer",stop=stop,
                     config=config,checkpoint_freq=10)
 
     # You can just do PPO or DQN but we wanted to show 
     # how to customize
     #results = tune.run("PPO",stop=stop,config=config,
     #       verbose=1,checkpoint_freq=10)
 
 else:
     from your_rllib_environment import YourEnvironment
     trainer = YourTrainer(config, env=YourEnvironment)
 
     # You can just do PPO or DQN but we wanted to show 
     # how to customize
     #from ray.rllib.agents.ppo import PPOTrainer
     #trainer = PPOTrainer(config, env=YourEnvironment)
 
     trainer.train()

Первый способ — с Ray Tune. Ray Tune изначально был разработан для настройки гиперпараметров, но хорошо работает для запуска алгоритмов RL. Второй способ — запустить трейнер напрямую.

С помощью Tune среда указывается в словаре конфигурации. При непосредственном запуске вы можете указать среду в качестве отдельного параметра. Как бы то ни было, конфигурация — это большая часть гибкости RLlib, и стоит потратить несколько минут на ее изучение. Конфигурация хранится в гигантском словаре, полученном из нескольких уровней наследования. Первый уровень – это общий тренерский уровень. Затем используемый вами тип тренера наследует его и добавляет к нему, например, PPO. Наконец, вы добавляете в конфигурацию свою конкретную реализацию; например, для сопоставления агентов с политиками.

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

Глядя на результаты тренировок

Как показано на рисунке 11, когда вы запускаете your_rllib_train.py, вы получаете 83 графика в TensorBoard.

Чтобы увидеть их на своем компьютере, перейдите в /Users/you/ray_results, найдите свой прогон и введите «tensorboard logdir=./».

Я позволил ему работать на моем ноутбуке около часа. Это долго для небольшой среды, но мы не добавили никаких интеллектуальных функций, и, если хотите, RLlib позволяет вам разместить это прямо на кластере машин, увеличив количество рабочих и отключив ray.init(локальный режим) local_mode=ложь).

На рис. 12 показано среднее вознаграждение за политику с течением времени. Два робота используют как политику высокого уровня, так и политику низкого уровня. Политика высокого уровня изучена в начале, но есть много случайностей (очевидно, найти правильную курицу сложно). На рис. 12 ось X — это временные шаги, а ось Y — вознаграждение.

Напомним, что роботы получают небольшое наказание на каждом временном шаге. Эта «награда» побуждает их все быстрее находить цыплят, как показано на рис. 13. На этом рисунке ось X — это временные шаги, а ось Y — количество временных шагов, которое требуется обоим роботам, чтобы найти цыпленка.

Загрузка и использование политик

Нет смысла тренироваться, если вы не можете использовать политику. После того, как политика изучена, мы можем загрузить ее и получить лучшее действие для любого состояния в demo/demo_after_training.py. В отрывке ниже мы видим, как загрузить трейнер с сохраненными параметрами.

from your_rllib_environment import YourEnvironment
trainer = ppo.PPOTrainer(config, env=YourEnvironment)
run ='YourTrainer_YourEnvironment_d9c79_00000_0_2022-08-18_21-37-21'
checkpoint = 'checkpoint_000500/checkpoint-500'
restore_point = os.path.join(YOUR_ROOT, run, checkpoint)
trainer.restore(restore_point)

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

robot_1_high_action = \
       trainer.compute_single_action(obs['robot_1_high'],   
       policy_id='high_level_policy', explore=False)
robot_2_high_action = \       
       trainer.compute_single_action(obs['robot_2_high'],  
       policy_id='high_level_policy', explore=False)
 
 action_dict = {'robot_1_high': robot_1_high_action,
                 'robot_2_high': robot_2_high_action}
 
 obs, rew, done, info = env.step(action_dict)
 
 env.render()
 
 def is_all_done(done: Dict) -> bool:
     for key, val in done.items():
         if not val:
             return False
     return True
 
 while not is_all_done(done):
     action_dict = {}
     assert 'robot_1_low' in obs or 'robot_2_low' in obs
     if 'robot_1_low' in obs and not done['robot_1_low']:
         action_dict['robot_1_low'] = \
             trainer.compute_single_action(obs['robot_1_low'], 
             policy_id='low_level_policy')
     if 'robot_2_low' in obs and not done['robot_2_low']:
         action_dict['robot_2_low'] = \
             trainer.compute_single_action(obs['robot_2_low'], 
             policy_id='low_level_policy')
     obs, rew, done, info = env.step(action_dict)
     print("Reward: ", rew)
     env.render()

Вы также можете посмотреть на саму политику, как мы видим в demo/demo_look_at_policies.py. Вы можете посмотреть реальные параметры и размер автоматически созданной нейросети.

from your_rllib_environment import YourEnvironment
trainer = ppo.PPOTrainer(config, env=YourEnvironment)
 
# Change these for your run
run = 'custom_execution_plan_2022-02-24'
checkpoint = 'checkpoint_000500/checkpoint-500'
 
restore_point = os.path.join(YOUR_ROOT, run, checkpoint)
trainer.restore(restore_point)
 
print("************** high level policy *************************")
# Note the output size of 10
policy: Policy = trainer.get_policy('high_level_policy')
#https://github.com/rayproject/ray/blob/releases/1.10.0/rllib/models#/torch/complex_input_net.py
model: ComplexInputNetwork = policy.model
for m in model.variables():
     print(m.shape)
 
print("**************** low level policy ***********************")
# Note the output size of 8
policy: Policy = trainer.get_policy('low_level_policy')
model: ComplexInputNetwork = policy.model
for m in model.variables():
    print(m.shape)

Заключение

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

Первоначально опубликовано по адресу https://deumbra.com/2022/08/rllib-for-deep-hierarchical-multiagent-reinforcement-learning/

Рекомендации

Торндайк, Э. Л. (1898 г.). Интеллект животных: экспериментальное исследование ассоциативных процессов у животных.

Скиннер, Б.Ф. (1953). Наука и поведение человека. Саймон и Шустер.

Саттон, Р.С., и Барто, А.Г. (1998). Обучение с подкреплением. Массачусетский технологический институт Пресс.

Кредиты

Иконки с сайта publicdomainvectors.org https://publicdomainvectors.org/

робот https://publicdomainvectors.org/en/free-clipart/Yellow-robot/81372.html

курица https://publicdomainvectors.org/en/free-clipart/Vector-illustration-of-cartoon-chicken-confused/24675.htm