【强化学习】PPO代码注释版本

# PPO主要通过限制新旧策略的比率,那些远离旧策略的改变不会发生# import tensorflow as tf
import tensorflow.compat.v1 as tf
tf.compat.v1.disable_eager_execution()
import numpy as np
import matplotlib.pyplot as plt
import gym# 定义一些超级参量
EP_MAX = 1000  # 最大步数
EP_LEN = 200
GAMMA = 0.9  # 折扣因子
A_LR = 0.0001  # A网络的学习速率
C_LR = 0.0002  # c网络的学学习速率
BATCH = 32  # 缓冲池长度
A_UPDATE_STEPS = 10  #
C_UPDATE_STEPS = 10
S_DIM, A_DIM = 3, 1  # 状态维度和动作维度
# 作者一共提出了两种方法,一种是Adaptive KL Penalty Coefficient, 另一种是Clipped Surrogate Objective,结果证明,clip的这个方法更好
METHOD = [dict(name='kl_pen', kl_target=0.01, lam=0.5),  # KL惩罚方法dict(name='clip', epsilon=0.2),  # clip方法,发现这个更好
][1]  # 选择优化的方法class PPO(object):def __init__(self):self.sess = tf.Session()# 状态变量的结构,多少个不知道,但是有S_DIM这么多维self.tfs = tf.placeholder(tf.float32, [None, S_DIM], 'state')# critic# https://blog.csdn.net/yangfengling1023/article/details/81774580/# 全连接层,曾加了一个层,全连接层执行操作 outputs = activation(inputs.kernel+bias) 如果执行结果不想进行激活操作,则设置activation=None# self.s:输入该网络层的数据  100:输出的维度大小,改变inputs的最后一维    tf.nn.relu6:激活函数,即神经网络的非线性变化with tf.variable_scope('critic'):  # tf.variable_scope:变量作用域l1 = tf.layers.dense(self.tfs, 100, tf.nn.relu)self.v = tf.layers.dense(l1, 1)  # 输出一个float32的数self.tfdc_r = tf.placeholder(tf.float32, [None, 1], 'discounted_r')  # discounted rewardself.advantage = self.tfdc_r - self.v  # 相当于td_error# c网络的loss也就是最小化advantage,先平方再取平均self.closs = tf.reduce_mean(tf.square(self.advantage))# critic 网络的优化器self.ctrain_op = tf.train.AdadeltaOptimizer(C_LR).minimize(self.closs)# actor# 建立了两个actor网络# actor有两个actor 和 actor_old, actor_old的主要功能是记录行为策略的版本。# 输入时state,输出是描述动作分布的mu和sigmapi, pi_params = self._build_anet('pi', trainable=True)oldpi, oldpi_params = self._build_anet('oldpi', trainable=False)with tf.variable_scope('sample_action'):# tf.squeeze函数返回一个张量,这个张量是将原始input中所有维度为1的那些维都删掉的结果# axis可以用来指定要删掉的为1的维度,此处要注意指定的维度必须确保其是1,否则会报错# 这里pi.sample是指从pi中取了样,会根据这个样本选择动作,网络优化之后会选择更好的样本出来self.sample_op = tf.squeeze(pi.sample(1), axis=0)  # 这里应该是只删掉了0维的1  TODO 不是很明白# print("pi.sample(1)", pi.sample(1))# print("self.sample_op", self.sample_op)with tf.variable_scope('update_oldpi'):# .assign的意思是增加新的一列self.update_oldpi_op = [oldp.assign(p) for p, oldp in zip(pi_params, oldpi_params)]# 动作占位, td_error占位self.tfa = tf.placeholder(tf.float32, [None, A_DIM], 'action')self.tfadv = tf.placeholder(tf.float32, [None, 1], 'advantage')with tf.variable_scope('loss'):  # 下面这些应该是在实现loss函数with tf.variable_scope('surrogate'):# surrogate目标函数:ratio = pi.prob(self.tfa) / (oldpi.prob(self.tfa) + 1e-5)surr = ratio * self.tfadv# 如果选择了KL惩罚方法,这种方法稍微复杂if METHOD['name'] == 'kl_pen':self.tflam = tf.placeholder(tf.float32, None, 'lambda')# tf.distributions.kl_divergence KL散度,也就是两个分布的相对熵,体现的是两个分布的相似程度,熵越小越相似kl = tf.distributions.kl_divergence(oldpi, pi)self.kl_mean = tf.reduce_mean(kl)self.aloss = -(tf.reduce_mean(surr - self.tflam * kl))# 如果选择的是clip方法,这个比较简单else:  # clipping method, find this is betterself.aloss = -tf.reduce_mean(tf.minimum(surr,tf.clip_by_value(ratio, 1. - METHOD['epsilon'], 1. + METHOD['epsilon']) * self.tfadv))# a网络优化器with tf.variable_scope('atrain'):self.atrain_op = tf.train.AdamOptimizer(A_LR).minimize(self.aloss)# 指定文件来保存图,tensorboard的步骤tf.summary.FileWriter("log/", self.sess.graph)# 运行会话self.sess.run(tf.global_variables_initializer())def update(self, s, a, r):  # 更新函数# print("fuction: update")# 先运行俩会话self.sess.run(self.update_oldpi_op)adv = self.sess.run(self.advantage, {self.tfs: s, self.tfdc_r: r})# update actorif METHOD['name'] == 'kl_pen':  # TODO 不懂for _ in range(A_UPDATE_STEPS):_, kl = self.sess.run([self.atrain_op, self.kl_mean],{self.tfs: s, self.tfa: a, self.tfadv: adv, self.tflam: METHOD['lam']})if kl > 4 * METHOD['kl_target']:  # this in in google's paperbreak# 这一块是在计算惩罚项的期望,并对系数进行自适应调整# 更新后的系数用于下一次策略更新。在这个方案中,我们偶尔会看到KL差异与target显著不同,但是这种情况很少,# 因为B会迅速调整。参数1.5和2是启发式选择的,但算法对它们不是很敏感。B的初值是另一个超参数,但在实际应用中# 并不重要,因为算法可以快速调整它。if kl < METHOD['kl_target'] / 1.5:  # adaptive lambda, this is in OpenAI's paperMETHOD['lam'] /= 2elif kl > METHOD['kl_target'] * 1.5:METHOD['lam'] *= 2METHOD['lam'] = np.clip(METHOD['lam'], 1e-4, 10)  # sometimes explode, this clipping is my solutionelse:  # clipping method, find this is better (OpenAI's paper)[self.sess.run(self.atrain_op, {self.tfs: s, self.tfa: a, self.tfadv: adv}) for _ in range(A_UPDATE_STEPS)]# update critic[self.sess.run(self.ctrain_op, {self.tfs: s, self.tfdc_r: r}) for _ in range(C_UPDATE_STEPS)]def choose_action(self, s):# print("fuction: choose_action")# print('state: ', s, "s.shape", s.shape)s = s[np.newaxis, :]# print('s[np.newaxis, :]: ', s, s.shape)a = self.sess.run(self.sample_op, {self.tfs: s})[0]print("action",a)print("np.clip(a, -2, 2)", np.clip(a, -2, 2))return np.clip(a, -2, 2)# np.clip: 是一个截取函数,用于截取数组中小于或者大于某值的部分,并使得被截取部分等于固定值。所有比a_min小的数都会强制变为a_min;def get_v(self, s):# print("fuction: get_v")if s.ndim < 2: s = s[np.newaxis, :]return self.sess.run(self.v, {self.tfs: s})[0, 0]def _build_anet(self, name, trainable):# print("fuction: _build_anet")with tf.variable_scope(name):# tf.nn.relu    激活函数#l1 = tf.layers.dense(self.tfs, 100, tf.nn.relu, trainable=trainable)# tf.nn.tanh 计算l1的双曲正切值  会把值压缩到(-1,1)之间     # 平均值mu = 2 * tf.layers.dense(l1, A_DIM, tf.nn.tanh, trainable=trainable)# tf.nn.softplus  这个函数的作用是计算激活函数softplus,即log( exp(l1) + 1)。sigma = tf.layers.dense(l1, A_DIM, tf.nn.softplus, trainable=trainable)  # 标准差# 该函数定义了一个正态分布。  mu是平均值   sigma是标准差norm_dist = tf.distributions.Normal(loc=mu, scale=sigma)print("norm_dist", norm_dist)params = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope=name)print("I am params", params)return norm_dist, paramsdef main():env = gym.make('Pendulum-v0').unwrappedppo = PPO()all_ep_r = []for ep in range(EP_MAX):s = env.reset()  # 状态初始化buffer_s, buffer_a, buffer_r = [], [], []  # 缓存区ep_r = 0  # 初始化回合for t in range(EP_LEN):  # 在规定的回合长度内env.render()  # 环境渲染a = ppo.choose_action(s)s_, r, done, _ = env.step(a)  # 执行动作获取需要的参量buffer_s.append(s)  # 把这些参量加到缓存区buffer_a.append(a)buffer_r.append((r + 8) / 8)  # 规范奖励,发现有用的东西s = s_ep_r += r# 更新PPO# 如果buffer收集一个batch或者episode完了if (t + 1) % BATCH == 0 or t == EP_LEN - 1:  # TODO 这里具体再解释一下v_s_ = ppo.get_v(s_)  # 计算 discounted rewarddiscounted_r = []for r in buffer_r[::-1]:  # print(a[::-1]) ### 取从后向前(相反)的元素[1 2 3 4 5]-->[ 5 4 3 2 1 ]v_s_ = r + GAMMA * v_s_  # 状态价值计算discounted_r.append(v_s_)discounted_r.reverse()  # 先反方向加入再逆转# 清空 bufferbs, ba, br = np.vstack(buffer_s), np.vstack(buffer_a), np.array(discounted_r)[:, np.newaxis]buffer_s, buffer_a, buffer_r = [], [], []ppo.update(bs, ba, br)  # 更新PPO TODO 这些定义具体是干什么用的呢?if ep == 0:all_ep_r.append(ep_r)else:all_ep_r.append(all_ep_r[-1] * 0.9 + ep_r * 0.1)print('Ep: %i' % ep,"|Ep_r: %i" % ep_r,("|Lam: %.4f" % METHOD['lam']) if METHOD['name'] == 'kl_pen' else '',)plt.plot(np.arange(len(all_ep_r)), all_ep_r)plt.xlabel('Episode')  # 回合数plt.ylabel('Moving averaged episode reward')  # 平均回报plt.show()if __name__ == '__main__':main()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/348159.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【强化学习】可视化学习tensorboard

tensorflow定义了一个图结构&#xff1a; 代码&#xff1a; a tf.constant(3.0, name"a")b tf.constant(4.0, name"b")c tf.add(a, b, name"add")var tf.Variable(tf.random_normal([2, 3], mean0.0, stddev1.0), name"variable"…

面向初学者的JSF 2.0教程

1.什么是JSF&#xff1f; JSF是Java Server Faces的首字母缩写。 它是一种服务器端处理技术&#xff0c;它允许将服务器端代码嵌入到网页中。 由于可以将服务器端处理和呈现代码嵌入网页本身&#xff0c;因此使项目的整体编码更加简单。 减少总体数量以及文件大小。 JSF包含2个…

篡改referer_HTTP_REFERER的用法及伪造

引言在php中&#xff0c;可以使用$_SERVER[‘HTTP_REFERER’]来获取HTTP_REFERER信息&#xff0c;关于HTTP_REFERER&#xff0c;php文档中的描述如下&#xff1a;“引导用户代理到当前页的前一页的地址(如果存在)。由 user agent 设置决定。并不是所有的用户代理都会设置该项&a…

华为nova7保密柜_华为发布nova8系列新品 轻松拍出Vlog黄金脸占比

2020年12月23日&#xff0c;华为nova8系列手机正式发布。作为深受年轻人喜爱的手机品牌之一&#xff0c;华为nova8系列此次延续其强大的前置视觉实力、强悍的设计性能以及独特的设计美学&#xff0c;带来业内首款专为Vlog拍摄设计的5G手机。随着短视频和Vlog的崛起&#xff0c;…

从拉格朗日乘数法到KKT条件

从拉格朗日乘数法到KKT条件 最近看论文遇到了Karush–Kuhn–Tucker &#xff08;KKT&#xff09;条件&#xff0c;想搞清楚这是个什么东东&#xff0c;因此就把这个东西认真学习一下并且分享出来&#xff0c;希望对大家有用。学习KKT就不得不先学习一下拉格朗日乘数法&#xf…

26.0.0-alpha1_WildFly 8.0.0.Alpha1的发布和一些历史

26.0.0-alpha1自从我们发布WildFly 8.0.0.Alpha1版本以来&#xff0c; 已经过去了大约2周。 该下载位于WildFly下载页面上 。 我敢肯定&#xff0c;你们中的许多人可能会想知道WildFly是什么&#xff0c;而其中一些知道它是什么的人可能不会知道已经发布了。 我将尝试回答其中的…

单机最大负载_分布式高可靠之负载均衡,今天看了你肯定会

到目前为止&#xff0c;我已经为你介绍了分布式起源、分布式协调与同步、分布式资源管理与负载调度、分布式计算技术、分布式通信技术和分布式数据存储。可以说&#xff0c;掌握了这些内容&#xff0c;基本上就掌握了分布式的关键技术。然而&#xff0c;只有可靠的分布式系统才…

【强化学习】一文带你理清强化学习

整理不易&#xff0c;希望留个赞再走哦&#xff01;&#xff01; 学习路线 这个图描述的比较清晰&#xff0c;蓝框里是整个强化学习的一些概念基础了&#xff0c;橙色是一些学习方法&#xff0c;可以针对性的选择一些&#xff0c;废话不多说&#xff0c;接下来就按照这个路线图…

了解Java缓冲池

了解Java缓冲池 缓冲池空间位于垃圾收集器管理的内存之外。 这是分配本地堆外内存的一种方法。 使用缓冲池有什么好处&#xff1f; 为了回答这个问题&#xff0c;让我们首先了解什么是字节缓冲区。 字节缓冲区 非直接缓冲区 ByteBuffer类附带了java.nio包。 它允许我们分配直接…

java 循环拼接字符串用分号隔开_Java 8中字符串拼接新姿势:StringJoiner

在为什么阿里巴巴不建议在for循环中使用””进行字符串拼接一文中&#xff0c;我们介绍了几种Java中字符串拼接的方式&#xff0c;以及优缺点。其中还有一个重要的拼接方式我没有介绍&#xff0c;那就是Java 8中提供的StringJoiner &#xff0c;本文就来介绍一下这个字符串拼接…

module ‘tensorflow_core.compat.v1‘ has no attribute ‘contrib‘问题的完美解决

问题描述&#xff1a; Instructions for updating: Use keras.layers.Dense instead. Traceback (most recent call last):File "run_cnn.py", line 200, in <module>model TextCNN(config)File "D:\MY DATA\学习资料\研究生\深度学习\text-classificat…

doctrine find的对象转换成数组_「ES6基础」Array数组的新方法(上)

在日常工作中我们经常会与数组打交道&#xff0c;因此需要熟练掌握数组操作的相关方法&#xff0c;ES6中关于数组的操作&#xff0c;又给我们带来了哪些惊喜呢&#xff0c;Array数组操作又添加了哪些新方法&#xff1f;本篇文章将从以下几个方面进行介绍&#xff1a;Array.from…

No module named ‘__main__.common‘; ‘__main__‘ is not a package

今天在调通代码时遇到一个难缠的bug,源代码如下&#xff1a; from .common import _FLOATX, _EPSILON结果报错&#xff1a; 问题原因&#xff1a; 也就是说&#xff0c;这是相对导入&#xff0c;只有在父模块在当前运行环境中被导入过才能用。 这揭示了报错的缘由&#xff0…

spring 异步返回结果_使用Spring Integration聚合异步结果

spring 异步返回结果嗨&#xff0c;我遇到了一个问题&#xff0c;该问题使用Spring Integration解决方案非常好。 很多时候&#xff0c;我们需要一种将消息分发到未知数量的目的地的方案。 为此&#xff0c;我们使用主题方法。 但是有时&#xff0c;我们还希望从收到消息的所有…

ValueError( Shape(4, ?, 1, 20) and () are incompatible

报错&#xff1a; 解决&#xff1a; 将文件中的return tf.concat(axis, tensors) 改为&#xff1a;return tf.concat(tensors, axis)问题完美解决

adadelta算法_对C++用户比较友好的机器学习算法库

由于疫情影响&#xff0c;这几天在家学习编程&#xff0c;整理了基于c语言的机器学习算法库。目前大部分机器学习库都是面向pyhton语言的&#xff0c;尽管很python包的底层语言是c&#xff0c;但c用户使用起来很麻烦&#xff0c;这里整理了一些对c比较优化的机器学习算法库&…

不解析,使用解析对象

将面向对象的后端与外部系统集成的传统方式是通过数据传输对象 &#xff0c;这些对象在外出之前先序列化为JSON&#xff0c;然后在返回时反序列化。 这种方法很流行&#xff0c;而且是错误的。 序列化部分应该由打印机代替&#xff0c;我在前面已经解释过。 这是我对反序列化的…

yaml报错TypeError: load() missing 1 required positional argument: ‘Loader‘

添加一下命令即可&#xff1a; 我的操作&#xff1a; return yaml.load(config)改为 return yaml.full_load(config)问题完美解决

3d制作中需要注意的问题_珠宝首饰工艺篇-戒指3D造型设计制作注意要点

1、戒指的常规手寸数据和戒指外围周长计算公式应用参考如下图&#xff1a;戒指手寸内直径大小说明图1、戒指手寸规格有14号、15号、16号、17号、18号、19号、20号、&#xff0c;但是从开发角度来说比较常见规格是17号18号19号这几种规格比较多&#xff0c;那我们电脑3D建模的时…

微信推送封面尺寸_连封面图都搞不明白,做什么新时代的新媒体人?

嘿&#xff0c;胖友们大家好呀&#xff0c;我是三儿。又是精(bu)神(xiang)满(shang)满(ban)的周一啦&#xff0c;胖友们准备好开始迎接新的一周了吗&#xff01;为了迎接这个崭新的周一&#xff0c;三儿特意为你们准备的一些实用的小工具教学&#xff0c;帮助你们快速的完成工作…