Обратное распространение градиентов между агентами для изучения протоколов обмена сообщениями

Обучение с подкреплением - популярная область исследований. Это главным образом потому, что он нацелен на моделирование систем, которые в противном случае кажутся неразрешимыми. От знаменитой статьи об Atari от Deepmind мы далеко ушли. Следующий пост основан на том, что я узнал из следующей статьи:

Https://arxiv.org/pdf/1605.06676.pdf

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

Такая среда, в которой передаются сообщения, будет иметь некоторые важные требования. Представьте, что агент A отправляет сообщение m другому агенту B. Протокол, который они разрабатывают для связи, как они узнают, должны будут обладать определенными свойствами.

  1. Учитывая архитектуру системы, этот протокол обмена сообщениями должен быть оптимальным. Очевидно, что система, в которой агенты передают друг другу случайные векторы, бесполезна. Эти обмениваемые векторы (m) должны содержать много информации.
  2. Сообщение, отправленное A, должно быть понято B.

Учитывая, что у нас несколько агентов, мы можем выбрать следующие варианты (возможно, даже средние):

  1. Совместное использование параметров: получите общий набор параметров для всех агентов. То есть использовать единую сеть для всех агентов, но использовать эти параметры отдельно во время выполнения, при этом каждый агент подключает свое собственное наблюдение и полученные сообщения в сеть. Этот метод, как правило, более стабилен и прост в освоении, поскольку при извлечении полезных функций они используются для всех агентов. Их не нужно изучать отдельно.
  2. Без совместного использования параметров: используйте разные веса для каждой сети и позвольте им изучать функции независимо. Это менее стабильно, чем предыдущий вариант.

Был разработан один из первых алгоритмов RIAL. Идея RIAL проста: просто предоставляйте сообщения как варианты действий в селекторе действий каждого агента. Это сообщение передается другим агентам. Вот и все. Каждый агент обучается отдельно. Эта структура следует за децентрализованным выполнением, а также за независимым обновлением параметров, то есть градиенты передаются через каждый агент независимо и обновляются. Они не проходят сквозную передачу через несколько агентов.

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

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

Здесь важно отметить, что каждое сообщение может быть дискретным или непрерывным. Определением проблемы могут быть наложены ограничения, позволяющие передавать только дискретные сообщения, например однобитовые сообщения. Как мы можем дискретизировать сообщения? Давайте представим единицу под названием DRU (Discretize / Regularize Unit), определяемую как:

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

Попробуем реализовать это. Рассмотрим загадку Сотни узников. Цитирую загадку прямо из бумаги:

Сто заключенных недавно отправили в тюрьму. Смотритель сообщает им, что с завтрашнего дня каждый из них будет помещен в изолированную камеру, не имея возможности общаться друг с другом. Каждый день надзиратель будет выбирать одного из заключенных наугад с заменой и помещать его в центральную комнату для допросов, в которой есть только лампочка с тумблером. Заключенный сможет наблюдать за текущим состоянием лампочки. При желании он может включить лампочку. У него также есть возможность объявить, что, по его мнению, все заключенные посещали комнату для допросов в какой-то момент времени. Если это объявление верно, то все заключенные выпускаются на свободу, а если это ложь, все заключенные будут казнены. Надзиратель уходит, и заключенные собираются вместе, чтобы обсудить свою судьбу. Могут ли они договориться о протоколе, который будет гарантировать их свободу

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

Давайте теперь разгадываем загадку. Мы будем использовать TensorFlow, в частности 2.0. Нам придется решить эту проблему для небольшого числа заключенных, например 3 или 4, поскольку пространство для маневра увеличивается экспоненциально с количеством агентов. Эту проблему можно смоделировать как заключенных, которых каждый день случайным образом выбирают из своей камеры и разрешают передавать 1-битное сообщение в следующую. Этот однобитный заключенный - состояние лампочки. Следовательно, заключенный в комнате получает 1 бит от предыдущего заключенного (случайный бит, если это первый заключенный) и может отправить бит следующему заключенному. Ведя счет дней и используя этот бит для отправки следующему заключенному, им придется решить проблему.

За этой статьей обратитесь к моей реализации.

Окружающая среда

Обратитесь к классу Jail, который реализует среду, которую мы будем использовать. Для каждого шага выбираются случайные заключенные. Действия можно выполнить, вызвав метод step (). Когда выполняется действие Объявить, каждому заключенному дается награда в размере 0,5 или -0,5, в зависимости от того, является ли заявление правильным или нет.

Определение DRU

В следующем фрагменте кода показано определение DRU, которое будет использоваться только на этапе обучения (я непосредственно дискретизировал его для тестирования):

Агентская сеть

Воспроизведение серии

Теперь основная часть. Сначала несколько важных переменных и инициализаций:

Используя их, давайте запустим цикл, пока мы не закончим:

Эта первая часть пропускает сообщения через агентов. Если агент находится в комнате, текущее состояние лампочки передается агенту, в противном случае - DUMMY_MESSAGE, указывающий, что агент находится в своей комнате и прошел день. Не зная, что прошел день, агенты не смогут отслеживать время, которое кодируется в скрытом состоянии ГРУ, когда мы отправляем этот DUMMY_MESSAGE. Мы заносим все полезные переменные в списки, чтобы позже можно было вычислить потери, просто просматривая их. Цель вычисляется с использованием того же известного уравнения Беллмана, которое дает нам один член в функции потерь:

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

Основной цикл обучения

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

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