强化学习笔记(5)-回合策略梯度算法

2023-11-18

以下为阅读《强化学习:原理与python实现》这本书第七章的学习笔记。

在之前学习到的强度学习方法中,都是通过学习最优价值函数来获得最优策略。现在换一个角度来思考,我们可以通过用含参函数来近似最优策略,并在迭代中更新参数值,这就是策略梯度算法。

用函数近似方法估计最优策略\pi_{*}(a|s)的基本思想是用含参函数\pi(a|s;\theta )来近似最优策略。由于任意策略\pi都需要满足对于任意的状态s\in S,均有\sum_{a}^{}\pi(a|s)=1,我们也希望\pi(a|s;\theta )满足对于任意的s\in S,均有\sum_{a}^{}\pi(a|s;\theta)=1。为此我们可以引入动作偏好函数h(s,a;\theta),使得

\pi(a|s;\theta)=\frac{exp h(s,a;\theta)}{\sum_{a'}^{}exp h(s,a';\theta)} , s\in S, a\in A(s)

动作偏好函数可以具有线性组合或神经网络等多种形式,通过基于梯度的迭代算法来更新参数\theta,就可以得到最优状态估计。

策略梯度定理

策略梯度定理给出了期望回报和策略梯度之间的关系,是策略梯度方法的基础

在回合制任务中,策略\pi(\theta)期望回报可以表示为E_{\pi(\theta)}[G_{0}],策略梯度定理给出了它对策略参数\theta的梯度为

\triangledown E_{\pi(\theta)}[G_{0}]=E\left [\sum_{t=0}^{+\infty } \gamma^{t}G_{t}\triangledown ln\pi(A_{t}|S_{t};\theta) \right ]

 策略梯度定理告诉我们,只要知道了\triangledown ln\pi(A_{t}|S_{t};\theta)的值,就可以得到期望回报的梯度。因此我们可以顺着梯度的方向改变\theta以增大期望回报。

简单的策略梯度算法

在每一个回合结束后,我们可以就回合中的每一步用以下公式来更新参数\theta,这样的算法称为简单的策略梯度算法:

\theta_{t+1}\leftarrow \theta_{t}+\alpha \gamma^{t}G_{t}\triangledown ln\pi(A_{t}|S_{t};\theta), t=0,1,...

算法如下

输入:环境,策略\pi

输出:最优策略的估计\pi(\theta)

参数: 优化器(隐含学习率\alpha),折扣因子\gamma,控制回合数和回合内步数的参数

1. (初始化)\theta\leftarrow任意值

2.(时序差分更新)对每个回合执行以下操作

2.1(采样)用策略\pi(\theta)生成轨迹S_{0},A_{0},R_{1},S_{1},...,S_{T-1},A_{T-1},R_{T},S_{T}

2.2(初始化回报)G\leftarrow 0

2.3 对t=T-1, T-2,...,0,执行以下步骤:

2.3.1(更新回报)G\leftarrow \gamma G+R_{t+1}

2.3.2(更新策略)更新\theta以减小-\gamma^{t}Gln\pi(A_{t}|S_{t};\theta), 如\theta\leftarrow \theta+\alpha \gamma^{t}G\triangledown ln\pi(A_{t}|S_{t};\theta)

车杆平衡案例

以Gym库的车杆平稳问题为例,一个小车在直线滑轨上移动,一个杆一头连着小车,一头悬空。小车的初始位置和杆的初始角度都是在一定范围内随机选取的。智能体可以控制小车沿着滑轨左右移动。当出现以下任意一种情形时,回合结束:

1. 杆的倾斜角度超过12度

2. 小车移动超过2.4个单位长度

3. 回合到达200步

每进行一步得到1个单位的奖励。我们希望回合能够尽量地长。一般认为,如果在连续的100个回合中的平均奖励>=195,就认为问题解决了。

下面视频是以随机策略来进行,可以看到回合进行到21步就结束了,因为杆的倾斜角度超过了12度。

CartPole_random_trim

我们用策略梯度算法来解决这个问题,如以下的代码:

import gym
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import tensorflow as tf
import tensorflow.keras as keras
from keras.initializers import GlorotUniform
import tqdm
%matplotlib inline
from IPython import display

env = gym.make("CartPole-v0")

class VPGAgent:
    def __init__(self, env, policy_kwargs, baseline_kwargs=None, gamma=0.99):
        self.action_n = env.action_space.n
        self.gamma = gamma
        
        self.trajectory = []
        self.policy_net = self.build_network(
            output_size=self.action_n, 
            output_activation=tf.nn.softmax, 
            loss=keras.losses.categorical_crossentropy, 
            **policy_kwargs)
        if baseline_kwargs:
            self.baseline_net = self.build_network(
                output_size=1,
                **baseline_kwargs)
    
    def build_network(self, hidden_sizes, output_size, activation=tf.nn.relu, output_activation=None, loss=keras.losses.mse, learning_rate=0.01):
        model = keras.Sequential()
        for hidden_size in hidden_sizes:
            model.add(keras.layers.Dense(units=hidden_size, activation=activation))
        model.add(keras.layers.Dense(units=output_size, activation=output_activation))
        optimizer = keras.optimizers.Adam(learning_rate)
        model.compile(optimizer=optimizer, loss=loss)
        return model
    
    def decide(self, observation):
        probs = self.policy_net.predict(observation[np.newaxis])[0]
        action = np.random.choice(self.action_n, p=probs)
        return action
    
    def learn(self, observation, action, reward, done):
        self.trajectory.append((observation, action, reward))
        if done:
            df = pd.DataFrame(self.trajectory, columns=['observation', 'action', 'reward'])
            df['discount'] = self.gamma ** df.index.to_series()
            df['discounted_reward'] = df['discount'] * df['reward']
            df['discounted_return'] = df['discounted_reward'][::-1].cumsum()
            df['psi'] = df['discounted_return']
            
            x = np.stack(df['observation'])
            if hasattr(self, 'baseline_net'):
                df['baseline'] = self.baseline_net.predict(x)
                df['psi'] -= (df['baseline']*df['discount'])
                df['return'] = df['discounted_return']/df['discount']
                y = df['return'].values[:,np.newaxis]
                self.baseline_net.fit(x,y,verbose=0)
                
            sample_weight = df['psi'].values[:, np.newaxis]
            y = np.eye(self.action_n)[df['action']]
            self.policy_net.fit(x,y,sample_weight=sample_weight,verbose=0)
            self.trajectory = []

policy_kwargs = {
    'hidden_sizes': [10,], 
    'activation': tf.nn.relu,
    'learning_rate': 0.01
}
agent = VPGAgent(env, policy_kwargs=policy_kwargs)

def play_montecarlo(env, agent, render=False, train=False, random=False):
    episode_reward = 0
    observation = env.reset()
    step = 0
    img = plt.imshow(env.render(mode='rgb_array'))
    while True:
        step += 1
        if render:
            plt.title("%s | Step: %d" % ("Moutain Car",step))
            plt.axis('off')
            img.set_data(env.render(mode='rgb_array'))
            display.display(plt.gcf())
            display.clear_output(wait=True)
        if random:
            action = np.random.choice(agent.action_n)
        else:
            action = agent.decide(observation)
        next_observation, reward, done, _ = env.step(action)
        episode_reward += reward
        if train:
            agent.learn(observation, action, reward, done)
        if done:
            break
        observation = next_observation
    return episode_reward

episodes = 500
episode_rewards = []
for episode in tqdm.trange(episodes):
    episode_reward = play_montecarlo(env, agent, train=True)
    episode_rewards.append(episode_reward)
plt.plot(episode_rewards)

解释一下代码中的learn函数:

考虑一个回合总共进行了5步,每步的奖励值是1,Gamma是0.9,则:

\gamma^{0}G_{0}=1*(1+0.9*1+0.9^{2}*1+0.9^{3}*1+0.9^{4}*1)

\gamma^{1}G_{1}=0.9*(1+0.9*1+0.9^{2}*1+0.9^{3}*1)=0.9*1+0.9^{2}*1+0.9^{3}*1+0.9^{4}*1

\gamma^{2}G_{2}=0.9^{2}*(1+0.9*1+0.9^{2}*1)=0.9^{2}*1+0.9^{3}*1+0.9^{4}*1

\gamma^{3}G_{3}=0.9^{3}*(1+0.9*1)=0.9^{3}*1+0.9^{4}*1

\gamma^{4}G_{4}=0.9^{4}*(1)=0.9^{4}*1

对应代码中的

discounted_reward = [1, 1*0.9, 1*0.9**2, 1*0.9**3, 1*0.9**4]
discounted_return = [(1+1*0.9+...+1*0.9**4),(1*0.9+...+1*0.9**4),(1*0.9**2+...+1*0.9**4),(1*0.9**3+1*0.9**4),1*0.9**4]

可见discounted_return存储的是\gamma^{t}G_{t}的值

对于神经网络的输出函数是softmax,代表不同类型action的概率值。采用交叉熵作为损失函数,其公式为-ylna, a为softmax的输出值。

根据上面策略梯度算法提到的,我们的目标是更新\theta以减小-\gamma^{t}Gln\pi(A_{t}|S_{t};\theta),即交叉熵的损失函数的值乘以\gamma^{t}G_{t},我们只需要在训练神经网络的fit函数中指定sample_weight为\gamma^{t}G_{t}即可。

训练500步之后,每个回合的奖励值如下图,可见随着训练的回合数增加,策略逐渐得到了优化,后期很多回合的奖励值都去到了200:

 我们可以用训练好的模型来试玩一个回合,运行以下代码:

episode_reward = play_montecarlo(env, agent, render=True, train=False, random=False)

结果如以下视频:

CartPole_train_Trim

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

强化学习笔记(5)-回合策略梯度算法 的相关文章

随机推荐

  • 什么是RPC并实现一个简单的RPC

    1 基本的RPC模型 主要介绍RPC是什么 基本的RPC代码 RPC与REST的区别 gRPC的使用 1 1 基本概念 RPC Remote Procedure Call 远程过程调用 简单的理解是一个节点请求另一个节点提供的服务 本地过程
  • screen 使用

    screen 是一款能够实现多窗口远程控制的开源服务程序 基本使用 安装screen yum install screen 创建blackup会话 scrren S blackup 查看已有会话列表 screen ls 恢复会话 scree
  • RabbitMQ消息确认机制

    消息确认 基本流程 说明 生产者发送消息到RabbitMQ Server后 RabbitMQ Server需要对生产者进行消息Confirm确认 消费者消费消息后需要对 RabbitMQ Server进行消息ACK确认 消息确认模式 Rab
  • iterable java_如何在Java中将Iterable转换为Collection?

    iterable java There are various ways to convert Iterable to Collection in Java programming language 有多种方法可以用Java编程语言将Ite
  • BUUCTF--[第二章 web进阶]死亡ping命令

    BUUCTF 第二章 web进阶 死亡ping命令 本文只是对官方wp进行了一点修改 因为在测试过程中发现8080端口弹不回flag 在本地测试也是一样的结果 但是把端口修改成8089 其他端口应该也可以 并且nc监听方式为 nc lvp
  • C++ 之 常量成员函数

    常量成员函数 const member function 可读取类中的数据成员 但不能修改 1 声明 1 1 const 关键字 参数列表后 加 const 关键字 声明为常量成员函数 表明其不被允许修改类的数据成员 下面的类 以年 月 日
  • 【技术经验分享】计算机毕业设计Python+SparkML知识图谱新闻推荐系统 新闻数据分析 新闻爬虫 新闻大数据 新闻可视化 大数据毕业设计 大数据毕设 机器学习 深度学习

    开发技术 Python爬虫 springboot vue js SparkML SparkALS 机器学习 深度学习 协同过滤算法 说明 后端使用SpringBoot Mybatis Plus框架 前端使用Vue js Element Pl
  • Element UI 框架中Loading 区域加载的使用方法

    给自己打个小广告 有开发APP 小程序 网站 后台系统需求 或者 想学习前端的可以私信我哈 Loading 加载用于加载数据时显示动效 外链图片转存失败 源站可能有防盗链机制 建议将图片保存下来直接上传 img MgPFZSRk 16602
  • 怎样提升Java水平

    怎样提升Java水平 想更快更好地提高你的Java编程水平 除了在日常工作中积累经验外 你还可以在空闲时间通过学习来提高你的技术技能 首先Java 理论基础不会太差 一个Java基础理论知识都很差的Java程序员 那么你期望他的Java代码
  • docker安装rocketmq4.6.1(精简版)

    一 创建文件 mkdir p usr local rocketmq server logs usr local rocketmq server store usr local rocketmq broker logs usr local r
  • 黑白色老照片一键上色在线工具,让老照片漂亮起来

    每个人家中多少都有一些老旧的黑白照 或是当初拍照时只有拍黑白 跟彩色照片比虽然别有一番风味 但有时候还是会想看如果是彩色不知道会变怎样 会不会更好看 而这款 线上工具就能帮你实现 只要把你的黑白照上传 它就会透过 AI 技术自动帮你上色 我
  • idea中相同包不聚合

    idea中创建子包不折叠 项目场景 问题描述 原因分析 解决方案 项目场景 提示 idea使用中出现的问题 突然发现相同包不能聚合了 问题描述 提示 相同包不能聚合 突然出现很多路径相同的很多包下的文件 原因分析 提示 不小心将设置动了 解
  • 95-38-055-Buffer-UnpooledDirectByteBuf

    文章目录 1 总述 1 1 局部图 1 2 概述 1 总述 1 1 局部图 1 2 概述 Netty的UnpooledDirectByteBuf在NIO的DirectByteBuf上采用组合的方式进行了封装 屏蔽了对程序员不友好的地方 并使
  • 如何使用js创建一个构造函数及重写toString的方法

    在js中使用function可以创建一个函数 也可用创建一个构造函数 这个构造函数可用于实例化对象 代码如下
  • 解析Java-throw抛出异常详细过程

    首先 我们知道Java有3种抛出异常的形式 throw 执行的时候一定抛出某种异常对象 throws 出现异常的可能性 不一定会发生 系统自动抛出异常 throw用在一个语句抛出异常的时候 throw an instance of exce
  • MySQL最常用的二种存储引擎MyISAM和InnoDB的介绍

    1 MyISAM 默认表类型 它是基于传统的ISAM类型 ISAM是Indexed Sequential Access Method 有索引的顺序访问方法 的缩写 它是存储记录和文件的标准方法 不是事务安全的 而且不支持外键 如果执行大量的
  • 轻松拿结果-第二部分 同力 -第五章 用制度保障业绩

    第五章 用制度保障业绩 制度的保障 体现的是管理者的监管能力 也是守护胜利果实的有力保障 只有铁的纪律 才能拿到铁的结果 商场如战场 在公司您们就是带兵打仗的将军 有一个销售员踢球时伤到了腿 在他休息的两个月里 业绩却没有落下一点 都是整个
  • html5 悬停边框,Html,css:在悬停时更改行的边框颜色(Html,css: Change a row's border colow on hover)...

    Html css 在悬停时更改行的边框颜色 Html css Change a row s border colow on hover 我正在使用DataTables 我试图在行悬停时将行的顶部和底部边框更改为红色 以下没有改变颜色 tab
  • 消息的顺序消费

    首先 需要保证顺序的消息要发送到同一个messagequeue中 其次 一个messagequeue只能被一个消费者消费 这点是由消息队列的分配机制来保证的 最后 一个消费者内部对一个mq的消费要保证是有序的 我们要做到生产者 messag
  • 强化学习笔记(5)-回合策略梯度算法

    以下为阅读 强化学习 原理与python实现 这本书第七章的学习笔记 在之前学习到的强度学习方法中 都是通过学习最优价值函数来获得最优策略 现在换一个角度来思考 我们可以通过用含参函数来近似最优策略 并在迭代中更新参数值 这就是策略梯度算法