从学会站立到迈出第一步,强化学习 PPO 算法的直观训练

Published on with 584 views

前言

最近更新的比较慢,因为需要处理的事务太多,而且也想不好的选题。想到之前写过一期 让 DQN 玩个锤子试试,这次准备再写一篇强化学习的拓展文章。也是因为之前刷到国外大佬写的倒车入库的强化学习视频,一直想着复现,它是基于 Unity 开发的,好不容易把 Unity 装起来,才发现他的素材还要付费,就没再继续往下做了,我还是基于 OpenAI 的 Gym 玩玩免费的好了。

这次玩的是 PPO 算法,近端策略梯度算法,收敛会比较稳定,不会向 DDPG 那样难以收敛,而且,我一直觉得 DDPG 有点笨重了,使用 PPO 算法,甚至 Double DQN 都能解决大部分场景,虽然 DQN 不太适合连续动作空间的场景。

PPO 算法

PPO 算法是 OpenAI 在 2017 年提出的算法。网上争议比较大的是:PPO 是属于 On-Policy 还是 Off-Policy,如果去搜会发现两种答案都有,实际 PPO 也都支持这两种模式,但从大部分实现的代码来看,基本都属于 Off-Policy。

而离线策略的优势是显而易见的,不需要过多的环境数据,采用小批量更新,减少采样频率。

我这里将的 PPO,实际上是 PPO2。PPO1 是 DeepMind 提出的,用 KL 散度控制裁剪幅度,而 PPO2 优化后根据 clip 函数控制裁剪幅度,当优势 A > 0 时,决定其上界,当 A < 0 时,决定其下届,简单粗暴。

PPO 的网络结构比较简单,只有一组 Actor-Critic,而 DDPG 有两组 AC,结构的简单也意味着收敛速度的提高。

class ActorCritic(nn.Module):
    def __init__(self, state_dim, action_dim, has_continuous_action_space, action_std_init):
        super(ActorCritic, self).__init__()

        self.has_continuous_action_space = has_continuous_action_space

        if has_continuous_action_space:
            self.action_dim = action_dim
            self.action_var = torch.full((action_dim,), action_std_init * action_std_init).to(device)

        # Actor
        if has_continuous_action_space:
            self.actor = nn.Sequential(
                nn.Linear(state_dim, 64),
                nn.Tanh(),
                nn.Linear(64, 64),
                nn.Tanh(),
                nn.Linear(64, action_dim),
                nn.Tanh()
            )
        else:
            self.actor = nn.Sequential(
                nn.Linear(state_dim, 64),
                nn.Tanh(),
                nn.Linear(64, 64),
                nn.Tanh(),
                nn.Linear(64, action_dim),
                nn.Softmax(dim=-1)
            )

        # Critic
        self.critic = nn.Sequential(
            nn.Linear(state_dim, 64),
            nn.Tanh(),
            nn.Linear(64, 64),
            nn.Tanh(),
            nn.Linear(64, 1)
        )

代码参考了 Nikhil Barhate 大佬的 PPO-PyTorch,可以看到他还对连续和离散动作空间的输出做了兼容处理。

class PPO:
    def __init__(self, state_dim, action_dim, lr_actor, lr_critic, gamma, K_epochs, eps_clip,
                 has_continuous_action_space, action_std_init=0.6):

        self.has_continuous_action_space = has_continuous_action_space

        if has_continuous_action_space:
            self.action_std = action_std_init

        self.gamma = gamma
        self.eps_clip = eps_clip
        self.K_epochs = K_epochs

        self.buffer = ReplayBuffer()

        self.policy = ActorCritic(state_dim, action_dim, has_continuous_action_space, action_std_init).to(device)
        self.optimizer = torch.optim.Adam([
            {'params': self.policy.actor.parameters(), 'lr': lr_actor},
            {'params': self.policy.critic.parameters(), 'lr': lr_critic}
        ])

        self.policy_old = ActorCritic(state_dim, action_dim, has_continuous_action_space, action_std_init).to(device)
        self.policy_old.load_state_dict(self.policy.state_dict())

        self.MseLoss = nn.MSELoss()

训练过程

尝试了用 PPO 算法训练 RoboschoolWalker2d,小人行走。为了能够直观的看到强化学习的训练过程,我将过程截取录屏,能够看到一个从不会站立的小人,逐渐成长为能够勇敢迈出第一步到最后健步如飞的样子。

这里我把这小人的整个强化学习训练过程直观的录成了视频,一起见证一下他的成长吧!

我想,每个人的成长过程也是与这个小人无二的,都是一次次跌倒,又一次次站起,只要有信念,困难就会成为我们的垫脚石,而非绊脚石!继续努力前行吧!


参考链接:
https://arxiv.org/pdf/1707.06347.pdf
https://di-engine-docs.readthedocs.io/en/latest/12_policies/ppo.html
https://blog.csdn.net/BruceXee/article/details/128486224
https://zhuanlan.zhihu.com/p/670659452
https://blog.csdn.net/fangchenglia/article/details/125725093


标题:从学会站立到迈出第一步,强化学习 PPO 算法的直观训练
作者:Jeffrey

Responses
取消