我的编程空间,编程开发者的网络收藏夹
学习永远不晚

【强化学习PPO算法】

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

【强化学习PPO算法】

强化学习PPO算法


  最近再改一个代码,需要改成PPO方式的,由于之前没有接触过此类算法,因此进行了简单学习,论文没有看的很详细,重点看了实现部分,这里只做简单记录。
  这里附上论文链接,需要的可以详细看一下。
   Proximal Policy Optimization Algorithms.

一、PPO算法

  PPO算法本质上是一个On-Policy的算法,它可以对采样到的样本进行多次利用,在一定程度上解决样本利用率低的问题,收到较好的效果。论文里有两种实现方式,一种是结合KL的penalty的,另一种是clip裁断的方法。大部分都是采用的后者,本文记录的也主要是后者的实现。

二、伪代码

  在网上找了一下伪代码,大概两类,前者是Open AI的,比较精炼,后者是Deepmind的,写的比较详细,在这里同时附上.

在这里插入图片描述

在这里插入图片描述

三、相关的简单理论

1.ratio

在这里插入图片描述
  这里的比例ratio,是两种策略下动作的概率比,而在程序实现中,用的是对动作分布取对数,而后使用e指数相减的方法,具体实现如下所示:

action_logprobs = dist.log_prob(action)ratios = torch.exp(logprobs - old_logprobs.detach())

2.裁断

在这里插入图片描述
  其中,裁断对应的部分如下图所示:
在这里插入图片描述
  上述公式代表的含义如下:
  clip公式含义.
在这里插入图片描述
  这里我是这样理解的:
  (1)如果A>0,说明现阶段的(st,at)相对较好,那么我们希望该二元组出现的概率越高越好,即ratio中的分子越大越好,但是分母分子不能差太多,因此需要加一个上限;
  (2)如果A<0,说明现阶段的(st,at)相对较差,那么我们希望该二元组出现的概率越低越好,即ratio中的分子越小越好,但是分母分子不能差太多,因此需要加一个下限.

3.Advantage的计算

  论文里计算At的方式如下,在一些情况下可以令lamda为1;还有一种更常用的计算方式是VAE,这里不进行描述.。
在这里插入图片描述
  对应的代码块如下:

 def update(self, memory):        # Monte Carlo estimate of rewards:        rewards = []        discounted_reward = 0        for reward, is_terminal in zip(reversed(memory.rewards), reversed(memory.is_terminals)):            if is_terminal:                discounted_reward = 0            discounted_reward = reward + (self.gamma * discounted_reward)            rewards.insert(0, discounted_reward)

4.loss的计算

在这里插入图片描述
  这里的第一项,对应裁断项,需要计算ratio和Advantage,之后进行裁断;
  这里的第二项,对应的为对应的值的均方误差;
  这里的第三项,为交叉熵
  程序的实现如下所示:

surr1 = ratios * advantagessurr2 = torch.clamp(ratios, 1 - self.eps_clip, 1 + self.eps_clip) * advantagesloss = -torch.min(surr1, surr2) + 0.5 * self.MseLoss(state_values, rewards) - 0.01 * dist_entropy

四、算法实现

  这里算法的实现参考了一位博主
  PPO代码.

#!/usr/bin/python3# -*-coding:utf-8 -*-# @Time    : 2022/6/18 15:53# @Author  : Wang xiangyu# @File    : PPO.pyimport torchimport torch.nn as nnfrom torch.distributions import MultivariateNormalimport gymimport numpy as npdevice = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")class Memory:    def __init__(self):        self.actions = []        self.states = []        self.logprobs = []        self.rewards = []        self.is_terminals = []    def clear_memory(self):        # del语句作用在变量上,而不是数据对象上。删除的是变量,而不是数据。        del self.actions[:]        del self.states[:]        del self.logprobs[:]        del self.rewards[:]        del self.is_terminals[:]class ActorCritic(nn.Module):    def __init__(self, state_dim, action_dim, action_std):        super(ActorCritic, self).__init__()        # action mean range -1 to 1        self.actor = nn.Sequential(            nn.Linear(state_dim, 64),            nn.Tanh(),            nn.Linear(64, 32),            nn.Tanh(),            nn.Linear(32, action_dim),            nn.Tanh()        )        # critic        self.critic = nn.Sequential(            nn.Linear(state_dim, 64),            nn.Tanh(),            nn.Linear(64, 32),            nn.Tanh(),            nn.Linear(32, 1)        )        # 方差        self.action_var = torch.full((action_dim,), action_std * action_std).to(device)    def forward(self):        # 手动设置异常        raise NotImplementedError    def act(self, state, memory):        action_mean = self.actor(state)        cov_mat = torch.diag(self.action_var).to(device)        dist = MultivariateNormal(action_mean, cov_mat)        action = dist.sample()        action_logprob = dist.log_prob(action)        memory.states.append(state)        memory.actions.append(action)        memory.logprobs.append(action_logprob)        return action.detach()    def evaluate(self, state, action):        action_mean = self.actor(state)        action_var = self.action_var.expand_as(action_mean)        # torch.diag_embed(input, offset=0, dim1=-2, dim2=-1) → Tensor        # Creates a tensor whose diagonals of certain 2D planes (specified by dim1 and dim2) are filled by input        cov_mat = torch.diag_embed(action_var).to(device)        # 生成一个多元高斯分布矩阵        dist = MultivariateNormal(action_mean, cov_mat)        # 我们的目的是要用这个随机的去逼近真正的选择动作action的高斯分布        action_logprobs = dist.log_prob(action)        # log_prob 是action在前面那个正太分布的概率的log ,我们相信action是对的 ,        # 那么我们要求的正态分布曲线中点应该在action这里,所以最大化正太分布的概率的log, 改变mu,sigma得出一条中心点更加在a的正太分布。        dist_entropy = dist.entropy()        state_value = self.critic(state)        return action_logprobs, torch.squeeze(state_value), dist_entropyclass PPO:    def __init__(self, state_dim, action_dim, action_std, lr, betas, gamma, K_epochs, eps_clip):        self.lr = lr        self.betas = betas        self.gamma = gamma        self.eps_clip = eps_clip        self.K_epochs = K_epochs        self.policy = ActorCritic(state_dim, action_dim, action_std).to(device)        self.optimizer = torch.optim.Adam(self.policy.parameters(), lr=lr, betas=betas)        self.policy_old = ActorCritic(state_dim, action_dim, action_std).to(device)        self.policy_old.load_state_dict(self.policy.state_dict())        self.MseLoss = nn.MSELoss()    def select_action(self, state, memory):        state = torch.FloatTensor(state.reshape(1, -1)).to(device)        return self.policy_old.act(state, memory).cpu().data.numpy().flatten()    def update(self, memory):        # Monte Carlo estimate of rewards:        rewards = []        discounted_reward = 0        for reward, is_terminal in zip(reversed(memory.rewards), reversed(memory.is_terminals)):            if is_terminal:                discounted_reward = 0            discounted_reward = reward + (self.gamma * discounted_reward)            rewards.insert(0, discounted_reward)        # Normalizing the rewards:        rewards = torch.tensor(rewards, dtype=torch.float32).to(device)        rewards = (rewards - rewards.mean()) / (rewards.std() + 1e-5)        # convert list to tensor        # 使用stack可以保留两个信息:[1. 序列] 和 [2. 张量矩阵] 信息,属于【扩张再拼接】的函数;        old_states = torch.squeeze(torch.stack(memory.states).to(device), 1).detach()        old_actions = torch.squeeze(torch.stack(memory.actions).to(device), 1).detach()        old_logprobs = torch.squeeze(torch.stack(memory.logprobs), 1).to(device).detach()#这里即可以对样本进行多次利用,提高利用率        # Optimize policy for K epochs:        for _ in range(self.K_epochs):            # Evaluating old actions and values :            logprobs, state_values, dist_entropy = self.policy.evaluate(old_states, old_actions)            # Finding the ratio (pi_theta / pi_theta__old):            ratios = torch.exp(logprobs - old_logprobs.detach())            # Finding Surrogate Loss:            advantages = rewards - state_values.detach()            surr1 = ratios * advantages            surr2 = torch.clamp(ratios, 1 - self.eps_clip, 1 + self.eps_clip) * advantages            loss = -torch.min(surr1, surr2) + 0.5 * self.MseLoss(state_values, rewards) - 0.01 * dist_entropy            # take gradient step            self.optimizer.zero_grad()            loss.mean().backward()            self.optimizer.step()        # Copy new weights into old policy:        self.policy_old.load_state_dict(self.policy.state_dict())def main():    ############## Hyperparameters ##############    env_name = "Pendulum-v1"    render = False    solved_reward = 300  # stop training if avg_reward > solved_reward    log_interval = 20  # print avg reward in the interval    max_episodes = 10000  # max training episodes    max_timesteps = 1500  # max timesteps in one episode    update_timestep = 4000  # update policy every n timesteps    action_std = 0.5  # constant std for action distribution (Multivariate Normal)    K_epochs = 80  # update policy for K epochs    eps_clip = 0.2  # clip parameter for PPO    gamma = 0.99  # discount factor    lr = 0.0003  # parameters for Adam optimizer    betas = (0.9, 0.999)    #############################################    # creating environment    env = gym.make(env_name)    state_dim = env.observation_space.shape[0]    action_dim = env.action_space.shape[0]    memory = Memory()    ppo = PPO(state_dim, action_dim, action_std, lr, betas, gamma, K_epochs, eps_clip)    print(lr, betas)    # logging variables    running_reward = 0    avg_length = 0    time_step = 0    # training loop    for i_episode in range(1, max_episodes + 1):        state = env.reset()        for t in range(max_timesteps):            time_step += 1            # Running policy_old:            action = ppo.select_action(state, memory)            state, reward, done, _ = env.step(action)            # Saving reward and is_terminals:            memory.rewards.append(reward)            memory.is_terminals.append(done)            # update if its time            if time_step % update_timestep == 0:                ppo.update(memory)                memory.clear_memory()                time_step = 0            running_reward += reward            if render:                env.render()            if done:                break        avg_length += t+1        # stop training if avg_reward > solved_reward        if running_reward > (log_interval * solved_reward):            print("########## Solved! ##########")            torch.save(ppo.policy.state_dict(), './PPO_continuous_solved_{}.pth'.format(env_name))            break        # save every 500 episodes        if i_episode % 500 == 0:            torch.save(ppo.policy.state_dict(), './PPO_continuous_{}.pth'.format(env_name))        # logging        if i_episode % log_interval == 0:            avg_length = int(avg_length / log_interval)            running_reward = int((running_reward / log_interval))            print('Episode {} \t Avg length: {} \t Avg reward: {}'.format(i_episode, avg_length, running_reward))            running_reward = 0            avg_length = 0if __name__ == '__main__':    main()

五、效果

  可以看到经过一段时间的训练,奖励有了一定升高.

在这里插入图片描述
在这里插入图片描述

六、感悟

  感悟是对改的项目的总结,和本文没有什么关系。
  这次改的项目参考了PPO的代码,架子基本也是搭好的,所以改起来也没有想象的那么困难。但应该是我第一次改代码,之前只是看代码,从来没有尝试改过那么多,可以感觉到看代码和改代码这两个能力间差的真的很多,写代码就更困难了emm,可以说经过这一次,可以更好的看到和别人的差距,不过对自己也有很大提高。在以后的学习中,还是需要多看多写,逐步提高。

来源地址:https://blog.csdn.net/weixin_47471559/article/details/125593870

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

【强化学习PPO算法】

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

如何在PaddlePaddle框架中实现强化学习算法

在PaddlePaddle框架中实现强化学习算法通常可以通过以下步骤进行:安装PaddlePaddle框架:首先需要安装PaddlePaddle框架并确保环境配置正确。构建强化学习环境:根据具体的问题,可以自定义一个强化学习环境,例如一个游
如何在PaddlePaddle框架中实现强化学习算法
2024-03-08

什么是强化学习?

强化学习是一种机器学习技术,代理与环境交互以最大化累积奖励。它涉及探索新动作、学习最佳策略并利用策略获取最大奖励。关键概念包括探索与利用的权衡、时间差分学习、值函数和最优价值函数。强化学习应用于机器人、游戏、财务交易、医疗保健和交通优化等领域。优点包括无需领域知识、适应性强和处理复杂问题的能力,而缺点包括训练时间长、数据需求高和解释性差。
什么是强化学习?
2024-04-02

Golang在强化学习中的机器学习应用

Golang 在强化学习中的机器学习应用简介强化学习是一种机器学习方法,通过与环境互动并根据奖励反馈学习最优行为。Go 语言具有并行、并发和内存安全等特性,使其在强化学习中具有优势。实战案例:围棋强化学习在本教程中,我们将使用 Go
Golang在强化学习中的机器学习应用
2024-05-08

这个开源项目用Pytorch实现了17种强化学习算法

编程学习网:强化学习在过去的十年里取得了巨大的发展,如今已然是各大领域热捧的技术之一,今天,猿妹和大家推荐一个有关强化学习的开源项目。
这个开源项目用Pytorch实现了17种强化学习算法
2024-04-23

7个流行的Python强化学习算法及代码实现详解

目前流行的强化学习算法包括 Q-learning、SARSA、DDPG、A2C、PPO、DQN 和 TRPO。这些算法已被用于在游戏、机器人和决策制定等各种应用中,本文我们将对其做一个简单的介绍,感兴趣的可以学习一下
2023-01-28

Java多线程之锁的强化学习

Java多线程的锁都是基于对象的,Java中的每一个对象都可以作为一个锁。这篇文章主要来通过一下示例为大家强化一下锁的相关知识的掌握,希望对大家有所帮助
2023-02-26

如何优化数据库的数据强化学习

优化数据库的数据强化学习可以通过以下几个步骤来实现:数据预处理:对数据进行预处理是非常重要的步骤,可以包括数据清洗、数据去重、缺失值填充等操作,以确保数据质量和完整性。特征工程:在数据预处理的基础上,可以进行特征工程,包括特征选择、特征抽取
如何优化数据库的数据强化学习
2024-07-03

Torch中的强化学习模块是什么

在Torch中,强化学习模块是一个用于实现强化学习算法的工具包。强化学习是一种机器学习方法,其目标是让智能体通过与环境的交互学习如何做出最优的决策以获得最大的累积奖励。Torch中的强化学习模块包含了多种强化学习算法的实现,如深度Q网络(D
Torch中的强化学习模块是什么
2024-03-08

【数据科学系统学习】机器学习算法 #

本篇内容为《机器学习实战》第 6 章 支持向量机部分程序清单。所用代码为 python3。支持向量机优点:泛化错误率低,计算开销不大,结果易解释。 缺点:对参数调节和核函数的选择敏感,原始分类器不加修改仅适用于处理二分类问题。适用数据类型:
2023-01-31

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录