Я знаю основы обучения с подкреплением, но какие термины необходимо понимать, чтобы читать статью arxiv PPO?
Каков план изучения и использования PPO?
Я знаю основы обучения с подкреплением, но какие термины необходимо понимать, чтобы читать статью arxiv PPO?
Каков план изучения и использования PPO?
Чтобы лучше понять PPO, полезно ознакомиться с основными вкладами статьи, а именно: (1) усеченная суррогатная цель и (2) использование нескольких периоды стохастического подъема по градиенту для выполнения каждого обновления политики.
Из исходного документа PPO:
Мы представили [PPO], семейство методов оптимизации политики, которые используют несколько эпох стохастического подъема градиента для выполнения каждого обновления политики. Эти методы обладают стабильностью и надежностью [TRPO], но их намного проще реализовать. требуется изменить всего несколько строк кода для реализации градиента стандартной политики, применимы в более общих настройках (например, при использовании совместной архитектуры для функции политики и значения) и обладают более высокой общей производительностью.
Обрезанная суррогатная цель — это замена цели градиента политики, которая предназначена для повышения стабильности обучения за счет ограничения изменений, которые вы вносите в свою политику на каждом этапе.
Для стандартных градиентов политики (например, REINFORCE) --- с которыми вы должны быть знакомы, или ознакомьтесь с, прежде чем читать это --- цель, используемая для оптимизации нейронной сети, выглядит так:
Это стандартная формула, которую можно увидеть в книге Саттона, и другое resources, где A-hat может быть сниженная доходность (как в REINFORCE) или функция преимущества (как в GAE), например. Сделав шаг градиентного восхождения для этой потери по отношению к параметрам сети, вы будете стимулировать действия, которые привели к более высокому вознаграждению.
Метод градиента ванильной политики использует логарифмическую вероятность вашего действия (log π(a | s)) для отслеживания влияния действий, но вы можете представить себе использование другой функции для этого. Еще одна такая функция, представленная в этой статье, использует вероятность действия согласно действующей политике (π(a|s)), деленную на вероятность действия согласно вашей предыдущей политике (π_old(a |с)). Это выглядит немного похоже на выборку по важности, если вы знакомы с этим:
Это r(θ) будет больше 1, когда действие более вероятно для вашей текущей политики, чем для вашей старой политики; он будет между 0 и 1, когда действие менее вероятно для вашей текущей политики, чем для вашей старой.
Теперь, чтобы построить целевую функцию с этим r (θ), мы можем просто заменить его на член log π (a | s). Вот что делается в TRPO:
Но что произойдет, если ваше действие будет гораздо более вероятным (например, в 100 раз) для вашей текущей политики? r(θ) будет иметь тенденцию быть действительно большим и приводить к большим градиентным шагам, которые могут разрушить вашу политика. Чтобы справиться с этой и другими проблемами, TRPO добавляет несколько дополнительных наворотов (например, ограничения KL Divergence), чтобы ограничить величину, которую может изменить политика, и помочь гарантировать, что она монотонно улучшается.
Вместо того, чтобы добавлять все эти дополнительные навороты, что, если бы мы могли встроить эти стабилизирующие свойства в целевую функцию? Как вы могли догадаться, это то, что делает PPO. Он получает те же преимущества в производительности, что и TRPO, и избегает осложнений, оптимизируя эту простую (но довольно забавно выглядящую) обрезанную суррогатную цель:
Первый член (синий) внутри минимизации — это тот же член (r(θ)A), который мы видели в задаче TRPO. Второй член (красный) — это версия, в которой (r(θ)) обрезается между (1 — e, 1 + e). (в статье они утверждают, что хорошее значение e составляет около 0,2, поэтому r может варьироваться в пределах ~ (0,8, 1,2)). Затем, наконец, берется минимизация обоих этих членов (зеленый).
Не торопитесь и внимательно посмотрите на уравнение и убедитесь, что вы знаете, что означают все символы, и что происходит с математической точки зрения. Просмотр кода также может помочь; вот соответствующий раздел в обоих OpenAI базовых показателей и anyrl-py реализации.
Большой.
Далее давайте посмотрим, какой эффект создает функция L clip. Вот диаграмма из статьи, на которой показано значение цели клипа, когда Преимущество положительное и отрицательное:
В левой половине диаграммы, где (A > 0), это место, где действие оказало предполагаемое положительное влияние на результат. В правой половине диаграммы, где (A ‹ 0), это место, где действие оказало предполагаемое негативное влияние на результат.
Обратите внимание, как в левой половине значение r обрезается, если становится слишком высоким. Это произойдет, если действие станет намного более вероятным при текущей политике, чем при старой политике. Когда это происходит, мы не хотим жадничать и заходить слишком далеко (поскольку это всего лишь локальное приближение и образец нашей политики, так что это будет неточно, если мы зайдем слишком далеко), и поэтому мы обрезаем цель, чтобы предотвратить это от роста. (Это приведет к блокировке градиента при обратном проходе --- плоская линия приведет к тому, что градиент будет равен 0).
В правой части диаграммы, где действие оказало предполагаемое негативное влияние на результат, мы видим, что клип активируется около 0, когда действие в соответствии с текущей политикой маловероятно. Эта область отсечения также не позволит нам обновить слишком много, чтобы сделать действие гораздо менее вероятным после того, как мы уже сделали большой шаг, чтобы сделать его менее вероятным.
Таким образом, мы видим, что обе эти области отсечения не позволяют нам стать слишком жадными и попытаться обновить слишком много сразу и оставить область, в которой этот образец дает хорошую оценку.
Но почему мы позволяем r(θ) неограниченно расти в правой части диаграммы? Сначала это кажется странным, но что может привести к тому, что r(θ) станет действительно большим в этом случае? Рост r(θ) в этой области будет вызван шагом градиента, который сделал наше действие значительным. более вероятно, и получилось сделать нашу политику хуже. Если бы это было так, мы бы хотели иметь возможность отменить этот шаг градиента. И так уж получилось, что функция L clip это позволяет. Здесь функция отрицательна, поэтому градиент скажет нам идти в другом направлении и сделает действие менее вероятным на величину, пропорциональную тому, насколько мы его испортили. (Обратите внимание, что аналогичная область есть в крайней левой части диаграммы, где действие хорошее, но мы случайно сделали его менее вероятным.)
Эти области отмены объясняют, почему мы должны включать странный член минимизации в целевую функцию. Они соответствуют несрезанному r(θ)A, имеющему меньшее значение, чем усеченная версия, и возвращаются минимизацией. Это потому, что это были шаги в неправильном направлении (например, действие было хорошим, но мы случайно сделали его менее вероятным). Если бы мы не включили min в целевую функцию, эти области были бы плоскими (градиент = 0) и мы не смогли бы исправить ошибки.
Вот диаграмма, обобщающая это:
И в этом суть. Обрезанная суррогатная цель — это просто замена, которую вы можете использовать в ванильном градиенте политики. Отсечение ограничивает эффективное изменение, которое вы можете сделать на каждом шаге, чтобы повысить стабильность, а минимизация позволяет нам исправить наши ошибки, если мы что-то испортили. Одна вещь, которую я не обсуждал, — это то, что подразумевается под целью PPO, формирующей нижнюю границу, как обсуждалось в документе. Для получения дополнительной информации я бы предложил эту часть лекции, которую прочитал автор.
В отличие от ванильных методов градиента политик и благодаря функции Clipped Surrogate Objective, PPO позволяет запускать несколько эпох градиентного восхождения на ваших образцах, не вызывая деструктивно больших обновлений политик. Это позволяет вам выжать больше из ваших данных и снизить неэффективность выборки.
PPO запускает политику, используя N параллельных субъектов, каждый из которых собирает данные, а затем отбирает мини-пакеты этих данных для обучения K эпох, используя функцию Clipped Surrogate Objective. См. полный алгоритм ниже (приблизительные значения параметров: K = 3-15, M = 64-4096, T (горизонт) = 128 -2048):
Часть параллельных участников была популяризирована документом A3C и стала довольно стандартным способом сбора данных.
Новая часть заключается в том, что они могут запускать K эпох градиентного восхождения на образцах траектории. Как они утверждают в документе, было бы неплохо запустить градиентную оптимизацию ванильной политики для нескольких проходов по данным, чтобы вы могли узнать больше из каждого образца. Однако на практике это обычно не работает для ванильных методов, потому что они делают слишком большие шаги для локальных образцов, и это разрушает политику. PPO, с другой стороны, имеет встроенный механизм предотвращения слишком большого количества обновлений.
Для каждой итерации после выборки среды с π_old (строка 3) и когда мы запускаем оптимизацию (строка 6), наша политика π будет в точности равна π_old. Так что поначалу ни одно из наших обновлений не будет обрезано, и мы гарантированно чему-то научимся на этих примерах. Однако, когда мы обновляем π, используя несколько эпох, цель начнет достигать пределов отсечения, градиент для этих выборок станет равным 0, и обучение постепенно остановится... пока мы не перейдем к следующей итерации и не соберем новые выборки. .
....
И это пока все. Если вы заинтересованы в более глубоком понимании, я бы порекомендовал более подробно изучить исходный документ. реализовать его самостоятельно или погрузиться в базовую реализацию и играю с кодом.
[изменить: 27.01.2019]: Для лучшего понимания и того, как PPO соотносится с другими алгоритмами RL, я также настоятельно рекомендую ознакомиться с OpenAI Ресурсы и реализации Spin Up.
PPO, включая TRPO, пытается консервативно обновлять политику, не оказывая отрицательного влияния на ее производительность между каждым обновлением политики.
Для этого вам нужен способ измерить, насколько политика изменилась после каждого обновления. Это измерение выполняется путем просмотра расхождения KL между обновленной политикой и старой политикой.
Это становится проблемой оптимизации с ограничениями, мы хотим изменить политику в направлении максимальной производительности, следуя ограничениям, согласно которым расхождение KL между моей новой политикой и старой не превышает некоторого предварительно определенного (или адаптивного) порога.
С помощью TRPO мы вычисляем ограничение KL во время обновления и находим скорость обучения для этой проблемы (с помощью матрицы Фишера и сопряженного градиента). Это несколько грязно для реализации.
С помощью PPO мы упрощаем задачу, превращая расхождение KL из ограничения в штрафной член, аналогичный, например, штрафу за вес L1, L2 (для предотвращения роста весов до больших значений). PPO вносит дополнительные изменения, устраняя необходимость все вместе вычислять расхождение KL, путем жесткого ограничения коэффициента политики (соотношение обновленной политики и старой), чтобы он находился в пределах небольшого диапазона около 1,0, где 1,0 означает, что новая политика такая же, как и старая.
PPO — это простой алгоритм, который относится к классу алгоритмов оптимизации политик (в отличие от методов, основанных на значениях, таких как DQN). Если вы «знаете» основы RL (я имею в виду, если вы хотя бы вдумчиво прочитали несколько первых глав книгу Саттона), то первым логическим шагом будет знакомство с алгоритмами градиента политик. Вы можете прочитать эту статью. или глава 13 нового издания книги Саттона. Кроме того, вы также можете прочитать эту статью о TRPO, которая является предыдущей работой первого автора PPO ( в этой статье много ошибок в обозначениях; просто обратите внимание). Надеюсь, это поможет. --Мехди
Я думаю, что реализация для дискретного пространства действия, такого как Cartpole-v1, проще, чем для непрерывного пространства действия. Но для пространств с непрерывным действием это самая простая реализация, которую я нашел в Pytorch, поскольку вы можете ясно видеть, как они получают mu
и std
, чего я не мог с более известными реализациями, такими как Openai Baselines и Spinning up или Stable Baselines.
Эти строки из ссылки выше:
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: