鼠哥day

导航

tensorflow2 DPG PG算法 强化学习玩乒乓球

 使用确定性策略梯度玩乒乓球,网上很多案例抄写下来,实际使用发现都无法收敛,花了很多时间纠错,然后从parl提供的代码作为核心参考,收集了其他案例中的优点,自己在tensorflow2中实现了算法,并测试成功收敛

 

0.99累计奖励 + 0.01 最新奖励 = -1.0 时的训练结果图片

 

 

环境:

CPU: AMD Ryzen 9 5900X

GPU: NVIDIA GeForce RTX 3090

 

备注: 实际上本次测试对设备性能要求并不高,在本人3070ti笔记本和3090差距不大,这就像请一个书法家抄书不会比一个小学生快多少一样,每次学习数据量是非常少的,时间都消耗在运行游戏收集数据上了

 

常态CPU占用对比

 训练时CPU占用对比

 常态时GPU占用对比

 

训练时GPU占用对比

 

版本:

python 3.9

tensorflow-gpu 2.6.0

 

除上述代码意外,其他环境准备

# 解决 tensorflow2 加载模型时报错的问题
# pip install keras==2.6.0 -i https://pypi.tuna.tsinghua.edu.cn/simple

# 游戏环境完善
# pip install gym -i https://pypi.tuna.tsinghua.edu.cn/simple
# pip install ale-py  -i https://pypi.tuna.tsinghua.edu.cn/simple
# pip install gym[accept-rom-license] -i https://pypi.tuna.tsinghua.edu.cn/simple

# 安装后会报一些错,但测试已经可以运行
# pip install gym[all] -i https://pypi.tuna.tsinghua.edu.cn/simple

 

 

部分训练日志:

......

 

 

此处使用的是蒙特卡洛法,积累一定数据以后在更新数据,更多信息注释在代码中

代码核心

from tensorflow.keras import layers, optimizers, Model
import tensorflow as tf

# 1. 构建模型
class PG(Model):

    # 构造器
    def __init__(self, act_dim, lr):
        super(PG, self).__init__()
        self.lr = lr
        self.act_dim = act_dim
        self.ds1 = layers.Dense(256, activation='relu')
        self.ds2 = layers.Dense(64, activation='relu')
        self.ds3 = layers.Dense(act_dim, activation=tf.nn.softmax)

    # 前向传播  : 通过输入的游戏画面,进行预测
    # inputs   : 游戏画面 obs
    def call(self, obs):
        # 根据层构建模型输出
        obs = self.ds1(obs)
        obs = self.ds2(obs)
        obs = self.ds3(obs)
        return obs

    # 反向传播 : 按照策略梯度算法进行更新参数
    # obs_list      : obs数组,shape :                 (None,6400)
    # act_list      : 经过obs数组预测得到的行为数组,    (None,1)
    # reward_list   : 行为获得的经过gama衰减的奖励,     (None,1)
    def learn(self, obs_list, act_list, reward_list):
        # 初始化学习率
        self.optimizer_ = optimizers.Adam(learning_rate=self.lr)
        obs_list = tf.cast(obs_list, dtype=tf.float32)
        reward_list = tf.cast(reward_list, dtype=tf.float32)
        # 求导过程,策略梯度算法的核心
        # 下列运算步骤可能还可以简化,调试没有达到提速的效果,有兴趣的自己试着再优化
        with tf.GradientTape() as tape:
            """
            表示预测的obs画面对应的action行为概率,其概率之和为1
            self(obs_list) 等价于 self.call(obs_list)
            案例 :
            predict_action_list :
            [
                [ 0.1 , 0.2 , 0.3 , 0.4],
                [ 0.1 , 0.5 , 0.2 , 0.2],
                ....
            ]

            """
            predict_action_list = self(obs_list)
            # 这一步 one_hot 是将预测到的action编码为热编码
            # 比如预测行为是 [ [1],... ] ,热编码 [ [0,1,0,0,0...],... ]
            one_hot_ = tf.one_hot(act_list, depth=self.act_dim, axis=1)
            """
                
            这一步是将热编码对应的行为的概率取出,其他行为概率抹除,然后求和得到结果
            比如  
                [0.1,  0.2,   0.3, ...]
            和热编码相乘得到 
                [0,           0.2,    0, ...]

            再进行求和,就得到 [ 0.2 ] 

            """
            predict_action_list *= one_hot_
            predict_action_list = tf.reduce_sum(predict_action_list, axis=1)
            
            """
            tf.math.log(0.1) 等价于 ln(0.1)
            假设 

                predict_action_list : [ 0.1 , 0.2 , 0.3 , 0.4 , 0.5 , 0.6 , 0.7 , 0.8 , 0.9]

            那么的结果如下
            tf.math.log(predict_action_list) : 
                tf.Tensor(
                [ -2.3025851  -1.609438   -1.2039728  -0.9162907  -0.6931472  -0.5108256
                -0.35667497 -0.22314353 -0.10536055     ], shape=(9,), dtype=float32)

            通过上面的结果可以明白,这一步实际就是一个缩放的过程,使得概率越小的越小,概率越大的更加的大
            预测概率越小 log((obs,action)) = 0.1 的结果越小 -2.3025851
            预测概率越大 log((obs,action)) = 0.9 的结果越大 -0.10536055

            """
            log_ = tf.math.log(predict_action_list)
            """
            reward_list : 是经过gama处理以后的权重奖励,
            log_和reward_list相乘得到权重结果,再加一个负号,得到梯度上升的损失
            """
            loss = -log_ * reward_list
        gradient_ = tape.gradient(loss, self.trainable_variables)
        self.optimizer_.apply_gradients(zip(gradient_, self.trainable_variables))

 

 

代码训练日志:

 

完整代码

MouseDay/policy gradient tensoflow2.0

代码结构:

 

策略梯度\...                         // 模型权重和偏执,以及完整模型保存地
策略梯度_算法原生实现.py               // 代码执行入口
cjs_util.py                         // 工具类
pg_.py                              // 模型
train.log                           // 完整训练日志

                            

 

 

posted on 2022-02-18 18:39  鼠哥day  阅读(201)  评论(0编辑  收藏  举报