Как понять алгоритм оптимизации Proximal Policy в RL?

Я знаю основы обучения в области подкрепления, но какие термины необходимо понимать, чтобы научиться читать статьи PPO arxiv?

Какова дорожная карта для изучения и использования PPO?

Ответ 1

Чтобы лучше понять PPO, полезно взглянуть на основные вклады статьи: (1) ограниченная суррогатная цель и (2) использование "нескольких эпох" стохастического градиентного подъема для выполнения каждого обновления политики ".


First, to ground these points in the original Во-первых, чтобы обосновать эти точки в оригинальной [PPL] бумаге PPO:

Мы представили [PPO], семейство методов оптимизации политики, которые используют несколько эпох случайного градиентного подъема для выполнения каждого обновления политики. Эти методы обладают стабильностью и надежностью методов области доверия [TRPO], но их гораздо проще реализовать, требуя, чтобы изменилось всего несколько строк кода для реализации ванильного градиента политики, применимо в более общих настройках (например, при использовании совместной архитектуры для функции политики и значений) и имеют более высокую общую производительность.


1. Обрезанная суррогатная цель

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

Для градиентов ванильной политики (например, REINFORCE) - с которыми вы должны быть знакомы, или ознакомьтесь с до прочтения этого - цель, используемая для оптимизации нейронной сети, выглядит следующим образом:

PG objective

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

Метод градиента ванильной политики использует логарифмическую вероятность вашего действия (log π (a | s)) для отслеживания воздействия действий, но вы можете представить себе использование другой функции для этого. Другая такая функция, представленная в этой статьи, использует вероятность действия в соответствии с текущей политикой (π (a | s)), деленную на вероятность действия в соответствии с вашей предыдущей политикой (π_old (a | с)). Это похоже на выборку по важности, если вы знакомы с этим:

r eq

Это r (θ) будет больше 1, когда действие более вероятно для вашей текущей политики, чем для вашей старой политики; это будет между 0 и 1, когда действие менее вероятно для вашей текущей политики, чем для вашей старой.

Теперь, чтобы построить целевую функцию с этим r (θ), мы можем просто поменять ее на лог-член π (a | s). Вот что сделано в TRPO:

TRPO objective

Но что произойдет здесь, если ваши действия намного более вероятны (например, в 100 раз больше) для вашей текущей политики? r (θ) будет иметь тенденцию быть действительно большим и привести к большим шагам градиента, которые могут разрушить вашу политику. Для решения этой и других проблем TRPO добавляет несколько дополнительных функций (например, ограничения дивергенции KL), чтобы ограничить сумму, которую может изменить политика, и помочь гарантировать ее монотонное улучшение.

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

annotated clipped surrogate

Первый член (синий) внутри минимизации - это тот же (r (θ) A) термин, который мы видели в цели TRPO. Второе слагаемое (красный) - это версия, в которой (r (θ)) находится между (1 - e, 1 + e). (в статье утверждается, что хорошее значение для e составляет около 0,2, поэтому r может варьироваться между ~ (0,8, 1,2)). Затем, наконец, берется минимизация обоих этих терминов (зеленый).

Не спешите, внимательно посмотрите на уравнение и убедитесь, что вы знаете, что означают все символы, и математически, что происходит. Просмотр кода также может помочь; Вот соответствующий раздел в реализациях OpenAI baseline и anyrl-py.

Отлично.

Далее, давайте посмотрим, какой эффект создает функция L clip. Вот диаграмма из бумаги, которая показывает значение цели клипа, когда преимущество является положительным и отрицательным:

Clip intro

В левой половине диаграммы, где (A> 0), это то место, где действие оказало положительное влияние на результат. В правой половине диаграммы, где (A & lt; 0), это то, где действие оказало предполагаемое негативное влияние на результат.

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

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

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

Но почему мы позволяем r (θ) бесконечно расти в крайней правой части диаграммы? Сначала это кажется странным, но что может привести к тому, что r (θ) станет действительно большим в этом случае? Рост r (θ) в этой области будет вызван шагом градиента, который сделал наше действие намного более вероятным, и Оказалось, что наша политика ухудшается. Если бы это было так, мы бы хотели отменить этот шаг градиента. И так уж получилось, что функция L clip это позволяет. Функция здесь отрицательна, поэтому градиент скажет нам идти в другом направлении и сделает действие менее вероятным на величину, пропорциональную тому, насколько мы его облажали. (Обратите внимание, что в дальнем левом углу диаграммы есть похожая область, где действие хорошее, и мы случайно сделали его менее вероятным.)

Эти "отмененные" регионы объясняют, почему мы должны включить странный термин минимизации в целевую функцию. Они соответствуют тому, что unclipped r (θ) A имеет более низкое значение, чем урезанная версия, и возвращается при минимизации. Это потому, что они были шагами в неправильном направлении (например, действие было хорошим, но мы случайно сделали его менее вероятным). Если бы мы не включили min в целевую функцию, эти области были бы плоскими (градиент = 0), и мы не смогли бы исправить ошибки.

Вот схема, обобщающая это:

L Clip Diagram

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

2. Несколько эпох для обновления политики

В отличие от ванильных методов градиента политики и благодаря функции Clipped Surrogate Objective, PPO позволяет вам запускать несколько эпох градиентного всплытия на ваших образцах, не вызывая деструктивно больших обновлений политики. Это позволяет вам выжать больше из ваших данных и уменьшить неэффективность выборки.

PPO запускает политику, используя N параллельных участников, каждый из которых собирает данные, а затем отбирает мини-пакеты этих данных для подготовки к K эпохам с использованием функции Clipped Surrogate Objective. См. полный алгоритм ниже (приблизительные значения параметров: K = 3-15, M = 64-4096, T (горизонт) = 128-2048):

PPO Algo

Партия параллельных актеров была популяризирована в статье A3C и стала довольно стандартным способом сбора данных.

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

Для каждой итерации, после выборки из среды с помощью π_old (строка 3) и когда мы начнем оптимизацию (строка 6), наша политика π будет точно равна π_old. Итак, сначала ни одно из наших обновлений не будет вырезано, и мы гарантированно узнаем что-то из этих примеров. Однако, когда мы обновляем π, используя несколько эпох, цель начнет выходить за пределы ограничения, градиент для этих выборок будет равен 0, и обучение будет постепенно прекращаться... пока мы не перейдем к следующей итерации и не соберем новые выборки..

....

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

[edit: 2019/01/27]: Для лучшего понимания и того, как PPO связан с другими алгоритмами RL, я бы также настоятельно рекомендовал проверить ресурсы и реализации OpenAI Spinning Up.

Ответ 2

PPO - это простой алгоритм, который относится к классу алгоритмов оптимизации политики (в отличие от методов, основанных на значениях, таких как DQN). Если вы "знакомы" с основами RL (например, если вы хотя бы вдумчиво прочитали некоторые первые главы книги Саттона), то первым логическим шагом будет знакомство с алгоритмами градиента политики. Вы можете прочитать эту статью или главу 13 книги Саттона новой редакции. Кроме того, вы также можете прочитать эту статью о TRPO, которая является предыдущей работой первого автора PPO (эта статья имеет многочисленные ошибки обозначения; просто обратите внимание). Надеюсь, это поможет. --Mehdi

Ответ 3

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

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

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

С TRPO мы вычисляем ограничение KL во время обновления и обнаруживаем скорость обучения для этой проблемы (через Fisher Matrix и сопряженный градиент). Это довольно сложно реализовать.

С помощью PPO мы упрощаем задачу, поворачивая KL-расхождение от ограничения до штрафа, аналогично, например, L1, L2 (например, для снижения веса от больших значений). PPO делает дополнительные изменения, устраняя необходимость вычислить KL-расхождение все вместе, жестко обрезая соотношение политики (соотношение обновленной политики со старым), чтобы быть в пределах небольшого диапазона около 1,0, где 1.0 означает, что новая политика такая же, как и старая.

Ответ 4

Я думаю, что реализация для дискретного пространства действия, такого как Cartpole-v1, проще, чем для пространства непрерывного действия. Но для пространств с непрерывным действием это самая прямолинейная реализация, которую я нашел в Pytorch, так как вы можете ясно видеть, как они получают mu и std где я не мог с более известными реализациями, такими как Openai Baselines и Spinning up или Stable Baselines.

RL-Adventure PPO

Эти строки по ссылке выше:

class ActorCritic(nn.Module):
    def __init__(self, num_inputs, num_outputs, hidden_size, std=0.0):
        super(ActorCritic, self).__init__()

        self.critic = nn.Sequential(
            nn.Linear(num_inputs, hidden_size),
            nn.ReLU(),
            nn.Linear(hidden_size, 1)
        )

        self.actor = nn.Sequential(
            nn.Linear(num_inputs, hidden_size),
            nn.ReLU(),
            nn.Linear(hidden_size, num_outputs),
        )
        self.log_std = nn.Parameter(torch.ones(1, num_outputs) * std)

        self.apply(init_weights)

    def forward(self, x):
        value = self.critic(x)
        mu    = self.actor(x)
        std   = self.log_std.exp().expand_as(mu)
        dist  = Normal(mu, std)
        return dist, value

и отсечение:

def ppo_update(ppo_epochs, mini_batch_size, states, actions, log_probs, returns, advantages, clip_param=0.2):
    for _ in range(ppo_epochs):
        for state, action, old_log_probs, return_, advantage in ppo_iter(mini_batch_size, states, actions, log_probs, returns, advantages):
            dist, value = model(state)
            entropy = dist.entropy().mean()
            new_log_probs = dist.log_prob(action)

            ratio = (new_log_probs - old_log_probs).exp()
            surr1 = ratio * advantage
            surr2 = torch.clamp(ratio, 1.0 - clip_param, 1.0 + clip_param) * advantage

Я нашел ссылку над комментариями к этому видео на Youtube:

arxiv insights PPO