- 莫烦机器学习教程
- 有趣的机器学习
- 机器学习 (Machine Learning)
- 神经网络 (Neural Network)
- 卷积神经网络 CNN (Convolutional Neural Network)
- 循环神经网络 RNN (Recurrent Neural Network)
- LSTM RNN 循环神经网络 (LSTM)
- 自编码 (Autoencoder)
- 检验神经网络 (Evaluation)
- 特征标准化 (Feature Normalization)
- 选择好特征 (Good Features)
- 激励函数 (Activation Function)
- 过拟合 (Overfitting)
- 加速神经网络训练 (Speed Up Training)
- 处理不均衡数据 (Imbalanced data)
- 批标准化 (Batch Normalization)
- L1 / L2 正规化 (Regularization)
- 强化学习 (Reinforcement Learning)
- 强化学习方法汇总 (Reinforcement Learning)
- Q Leaning
- Sarsa
- Sarsa(lambda)
- DQN
- Policy Gradients
- Actor Critic
- Deep Deterministic Policy Gradient (DDPG)
- Asynchronous Advantage Actor-Critic (A3C)
- 强化学习教程
- Why?
- 课程要求
- 小例子
- Q-learning 算法更新
- Q-learning 思维决策
- Sarsa 算法更新
- Sarsa 思维决策
- Sarsa-lambda
- DQN 算法更新 (Tensorflow)
- DQN 神经网络 (Tensorflow)
- DQN 思维决策 (Tensorflow)
- OpenAI gym 环境库 (Tensorflow)
- Double DQN (Tensorflow)
- Prioritized Experience Replay (DQN) (Tensorflow)
- Dueling DQN (Tensorflow)
- Policy Gradients 算法更新 (Tensorflow)
- Policy Gradients 思维决策 (Tensorflow)
- Actor Critic (Tensorflow)
- Deep Deterministic Policy Gradient (DDPG) (Tensorflow)
- Asynchronous Advantage Actor-Critic (A3C) (Tensorflow)
- TensorFlow 教程
- 为什么选 Tensorflow
- 安装
- 神经网络在干嘛
- 处理结构
- 例子 2
- Session 会话控制
- Variable 变量
- Placeholder 传入值
- 激励函数 Activation Function
- 例子 3 添加层 def add_layer()
- 例子 3 建造神经网络
- 例子 3 结果可视化
- 优化器 optimizer
- Tensorboard 可视化好帮手 1
- Tensorboard 可视化好帮手 2
- Classification 分类学习
- Dropout 解决 overfitting
- CNN 卷积神经网络 1
- CNN 卷积神经网络 2
- CNN 卷积神经网络 3
- Saver 保存读取
- RNN 循环神经网络
- RNN LSTM 循环神经网络 (分类例子)
- RNN LSTM (回归例子)
- RNN LSTM (回归例子可视化)
- 自编码 Autoencoder (非监督学习)
- scope 命名方法
- Batch Normalization 批标准化
- PyTorch 教程
- Why?
- 安装
- Torch 或 Numpy
- 变量 (Variable)
- 激励函数 (Activation)
- 关系拟合 (回归)
- 区分类型 (分类)
- 快速搭建法
- 保存提取
- 批训练
- Optimizer 优化器
- CNN 卷积神经网络
- RNN 循环神经网络 (分类)
- RNN 循环神经网络 (回归)
- AutoEncoder (自编码/非监督学习)
- DQN 强化学习
- GAN (Generative Adversarial Nets 生成对抗网络)
- 为什么 Torch 是动态的
- GPU 加速运算
- Dropout 缓解过拟合
- Batch Normalization 批标准化
- Theano 教程
- Why?
- 安装
- 神经网络在做什么
- 基本用法
- Function 用法
- Shared 变量
- Activation function 激励函数
- 定义 Layer 类
- Regression 回归例子
- 可视化结果 回归例子
- Classification 分类学习
- Regularization 正规化
- Save 保存 提取
- 总结和更多
- Keras 教程
- Why?
- 安装
- 兼容 backend
- Regressor 回归
- Classifier 分类
- CNN 卷积神经网络
- RNN Classifier 循环神经网络
- RNN Regressor 循环神经网络
- Autoencoder 自编码
- Save & reload 保存提取
- Scikit learn 教程
- Why?
- 安装
- 选择学习方法
- 通用学习模式
- sklearn 强大数据库
- sklearn 常用属性与功能
- 正规化 Normalization
- 交叉验证 1 Cross-validation
- 交叉验证 2 Cross-validation
- 交叉验证 3 Cross-validation
- 保存模型
Policy Gradients 思维决策 (Tensorflow)
作者: Morvan 编辑: Morvan
接着上节内容,我们来实现 RL_brain
的 PolicyGradient
部分,这也是 RL 的大脑部分,负责决策和思考。
本节内容包括:
代码主结构
用基本的 Policy gradient 算法,和之前的 value-based 算法看上去很类似。
class PolicyGradient:
# 初始化 (有改变)
def __init__(self, n_actions, n_features, learning_rate=0.01, reward_decay=0.95, output_graph=False):
# 建立 policy gradient 神经网络 (有改变)
def _build_net(self):
# 选行为 (有改变)
def choose_action(self, observation):
# 存储回合 transition (有改变)
def store_transition(self, s, a, r):
# 学习更新参数 (有改变)
def learn(self, s, a, r, s_):
# 衰减回合的 reward (新内容)
def _discount_and_norm_rewards(self):
初始化
初始化时,我们需要给出这些参数,并创建一个神经网络。
class PolicyGradient:
def __init__(self, n_actions, n_features, learning_rate=0.01, reward_decay=0.95, output_graph=False):
self.n_actions = n_actions
self.n_features = n_features
self.lr = learning_rate # 学习率
self.gamma = reward_decay # reward 递减率
self.ep_obs, self.ep_as, self.ep_rs = [], [], [] # 这是我们存储 回合信息的 list
self._build_net() # 建立 policy 神经网络
self.sess = tf.Session()
if output_graph: # 是否输出 tensorboard 文件
# $ tensorboard --logdir=logs
# http://0.0.0.0:6006/
# tf.train.SummaryWriter soon be deprecated, use following
tf.summary.FileWriter("logs/", self.sess.graph)
self.sess.run(tf.global_variables_initializer())
建立 Policy 神经网络
这次我们要建立的神经网络是这样的:
因为这是强化学习,所以神经网络中并没有我们熟知的监督学习中的 y label. 取而代之的是我们选的 action.
class PolicyGradient:
def __init__(self, n_actions, n_features, learning_rate=0.01, reward_decay=0.95, output_graph=False):
...
def _build_net(self):
with tf.name_scope('inputs'):
self.tf_obs = tf.placeholder(tf.float32, [None, self.n_features], name="observations") # 接收 observation
self.tf_acts = tf.placeholder(tf.int32, [None, ], name="actions_num") # 接收我们在这个回合中选过的 actions
self.tf_vt = tf.placeholder(tf.float32, [None, ], name="actions_value") # 接收每个 state-action 所对应的 value (通过 reward 计算)
# fc1
layer = tf.layers.dense(
inputs=self.tf_obs,
units=10, # 输出个数
activation=tf.nn.tanh, # 激励函数
kernel_initializer=tf.random_normal_initializer(mean=0, stddev=0.3),
bias_initializer=tf.constant_initializer(0.1),
name='fc1'
)
# fc2
all_act = tf.layers.dense(
inputs=layer,
units=self.n_actions, # 输出个数
activation=None, # 之后再加 Softmax
kernel_initializer=tf.random_normal_initializer(mean=0, stddev=0.3),
bias_initializer=tf.constant_initializer(0.1),
name='fc2'
)
self.all_act_prob = tf.nn.softmax(all_act, name='act_prob') # 激励函数 softmax 出概率
with tf.name_scope('loss'):
# 最大化 总体 reward (log_p * R) 就是在最小化 -(log_p * R), 而 tf 的功能里只有最小化 loss
neg_log_prob = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=all_act, labels=self.tf_acts) # 所选 action 的概率 -log 值
# 下面的方式是一样的:
# neg_log_prob = tf.reduce_sum(-tf.log(self.all_act_prob)*tf.one_hot(self.tf_acts, self.n_actions), axis=1)
loss = tf.reduce_mean(neg_log_prob * self.tf_vt) # (vt = 本 reward + 衰减的未来 reward) 引导参数的梯度下降
with tf.name_scope('train'):
self.train_op = tf.train.AdamOptimizer(self.lr).minimize(loss)
选行为
这个行为不再是用 Q value 来选定的,而是用概率来选定. 即使不用 epsilon-greedy, 也具有一定的随机性。
class PolicyGradient:
def __init__(self, n_actions, n_features, learning_rate=0.01, reward_decay=0.95, output_graph=False):
...
def _build_net(self):
...
def choose_action(self, observation):
prob_weights = self.sess.run(self.all_act_prob, feed_dict={self.tf_obs: observation[np.newaxis, :]}) # 所有 action 的概率
action = np.random.choice(range(prob_weights.shape[1]), p=prob_weights.ravel()) # 根据概率来选 action
return action
存储回合
这一部很简单,就是将这一步的 observation
, action
, reward
加到列表中去. 因为本回合完毕之后要清空列表,然后存储下一回合的数据,所以我们会在 learn()
当中进行清空列表的动作。
class PolicyGradient:
def __init__(self, n_actions, n_features, learning_rate=0.01, reward_decay=0.95, output_graph=False):
...
def _build_net(self):
...
def choose_action(self, observation):
...
def store_transition(self, s, a, r):
self.ep_obs.append(s)
self.ep_as.append(a)
self.ep_rs.append(r)
学习
本节的 learn()
很简单,首先我们要对这回合的所有 reward
动动手脚,使他变得更适合被学习. 第一就是随着时间推进,用 gamma
衰减未来的 reward
, 然后为了一定程度上减小 policy gradient 回合 variance, 我们标准化回合的 state-action value 依据在 Andrej Karpathy 的 blog .
class PolicyGradient:
def __init__(self, n_actions, n_features, learning_rate=0.01, reward_decay=0.95, output_graph=False):
...
def _build_net(self):
...
def choose_action(self, observation):
...
def store_transition(self, s, a, r):
...
def learn(self):
# 衰减,并标准化这回合的 reward
discounted_ep_rs_norm = self._discount_and_norm_rewards() # 功能再面
# train on episode
self.sess.run(self.train_op, feed_dict={
self.tf_obs: np.vstack(self.ep_obs), # shape=[None, n_obs]
self.tf_acts: np.array(self.ep_as), # shape=[None, ]
self.tf_vt: discounted_ep_rs_norm, # shape=[None, ]
})
self.ep_obs, self.ep_as, self.ep_rs = [], [], [] # 清空回合 data
return discounted_ep_rs_norm # 返回这一回合的 state-action value
我们再来看看这个 discounted_ep_rs_norm
到底长什么样,不知道大家还记不记得上节内容的这一段:
vt = RL.learn() # 学习,输出 vt, 我们下节课讲这个 vt 的作用
if i_episode == 0:
plt.plot(vt) # plot 这个回合的 vt
plt.xlabel('episode steps')
plt.ylabel('normalized state-action value')
plt.show()
我们看看这一段的输出, vt
也就是 discounted_ep_rs_norm
, 看他是怎么样诱导我们的 gradient descent.
可以看出,左边一段的 vt
有较高的值,右边较低,这就是 vt
在说:
“请重视我这回合开始时的一系列动作,因为前面一段时间杆子还没有掉下来. 而且请惩罚我之后的一系列动作,因为后面的动作让杆子掉下来了” 或者是
“我每次都想让这个动作在下一次增加被做的可能性 ( grad(log(Policy))
), 但是增加可能性的这种做法是好还是坏呢? 这就要由 vt
告诉我了,所以后段时间的 增加可能性
做法并没有被提倡,而前段时间的 增加可能性
做法是被提倡的.”
这样 vt
就能在这里 loss = tf.reduce_mean(log_prob * self.tf_vt)
诱导 gradient descent 朝着正确的方向发展了。
如果你玩了下 MountainCar
的模拟程序,你会发现 MountainCar
模拟程序中的 vt
长这样:
这张图在说: “请重视我这回合最后的一系列动作,因为这一系列动作让我爬上了山. 而且请惩罚我开始的一系列动作,因为这些动作没能让我爬上山”.
也是通过这些 vt
来诱导梯度下降的方向。
最后是如何用算法实现对未来 reward 的衰减。
class PolicyGradient:
def __init__(self, n_actions, n_features, learning_rate=0.01, reward_decay=0.95, output_graph=False):
...
def _build_net(self):
...
def choose_action(self, observation):
...
def store_transition(self, s, a, r):
...
def learn(self):
...
def _discount_and_norm_rewards(self):
# discount episode rewards
discounted_ep_rs = np.zeros_like(self.ep_rs)
running_add = 0
for t in reversed(range(0, len(self.ep_rs))):
running_add = running_add * self.gamma + self.ep_rs[t]
discounted_ep_rs[t] = running_add
# normalize episode rewards
discounted_ep_rs -= np.mean(discounted_ep_rs)
discounted_ep_rs /= np.std(discounted_ep_rs)
return discounted_ep_rs
如果想一次性看到全部代码,请去我的 Github
如果你觉得这篇文章或视频对你的学习很有帮助,请你也分享它,让它能再次帮助到更多的需要学习的人。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论