学习强化学习,码代码的能力必须要出众,要快速入门强化学习 搞清楚其中真正的原理,读源码是一个最简单的最直接的方式。最近创建了一系列该类型文章,希望对大家有多帮助。
传送门
另外,我会将所有的文章及所做的一些简单项目,放在我的个人网页上。
水平有限,可能有理解不到位的地方,希望大家主动沟通交流。
邮箱:[email protected]
Thanks for reading, and enjoy yourself。
GAIL是16年文章 “Generative Adversarial Imitation Learning”
https://arxiv.org/abs/1606.03476
文章中提出了
利用GAN 来提高 模仿学习和逆强化的算法,成功成为人们关注的焦点。
一些博客 简单介绍了
https://blog.csdn.net/weixin_37895339/article/details/82863379
https://zhuanlan.zhihu.com/p/69284460
https://zhuanlan.zhihu.com/p/69773693
https://zhuanlan.zhihu.com/p/60327435
抛开繁杂的数学推导了,这次主要是通过代码来进行理解算法。
首先,论文中的主要算法是在TRPO的基础上建立的,所以GAIL的主要算法也是TRPO,baseline的代码主要将GAIL的算法结合在了TRPO当中。
主要的程序是behavior_clone、adversary、trpo_mpi.
trpo_mpi是主程序,调用behavior_clone(如果需要预训练的话)、adversary
这个比较简单 其实就是将database从头到尾的读一遍。
然后看网络的输出和真实的输出之前的差距有多大。
ob_space = env.observation_space
ac_space = env.action_space
# bahavior
pi = policy_func("pi", ob_space, ac_space)
% policy 网络
ob = U.get_placeholder_cached(name="ob")
% 专家网络的action
ac = pi.pdtype.sample_placeholder([None])
stochastic = U.get_placeholder_cached(name="stochastic")
loss = tf.reduce_mean(tf.square(ac-pi.ac))
% 生成loss = 网络输出动作和专家网络差距
var_list = pi.get_trainable_variables()
adam = MpiAdam(var_list, epsilon=adam_epsilon)
lossandgrad = U.function([ob, ac, stochastic], [loss]+[U.flatgrad(loss, var_list)])
#####adverisary
这里主要建立的是一个类,该类主要的是建立GAN中的鉴别器。
该类调用类下的子方法build_graph建立2个DenseNet , 分别用于产生 生成器 和 专家网络的评分网络。
训练网络的loss主要是由3部分组成 生成器评分网络的loss 专家评分网络的loss 和交叉熵
self.total_loss = generator_loss + expert_loss + entropy_loss
生成器 loss是 生成器评分网络评分 与 0的差距
generator_loss = tf.nn.sigmoid_cross_entropy_with_logits(logits=generator_logits, labels=tf.zeros_like(generator_logits))
专家网络的loss 是 专家评分网络的评分 与1 的差距
expert_loss = tf.nn.sigmoid_cross_entropy_with_logits(logits=expert_logits, labels=tf.ones_like(expert_logits))
熵主要是将其拟合为伯努利分布之后 求其熵。
entropy_loss = tf.reduce_mean(logit_bernoulli_entropy(logits))
其中子函数get_reward 用于生成器训练的奖励
self.reward_op = -tf.log(1-tf.nn.sigmoid(generator_logits)+1e-8)
很明显 当 generator 输出 约接近于1 那么reward 越大。即生成对抗。
#####trpo_mpi
在更为规范的stable-baseline中,GAIL直接继承了TRPO的类,但是这里还是以标准的baseline为主。
这里还是以baseline为主。首先这里将adversary 传入trpo。
trpo 的 sample阶段,需要通过 判别器的子函数get_reward,得到 判别器输出的reward。
def traj_segment_generator(pi, env, reward_giver, horizon, stochastic):
ac, vpred = pi.act(stochastic, ob) # 51行
rew = reward_giver.get_reward(ob, ac) # 72 行
ob, true_rew, new, _ = env.step(ac) # 73 行
从316行 到327 对判别器进行训练
% 从记录读取 sample数据
for ob_batch, ac_batch in dataset.iterbatches((ob, ac),
include_final_partial_batch=False,
batch_size=batch_size):
ob_expert, ac_expert = expert_dataset.get_next_batch(len(ob_batch))
% 从数据库 读取专家数据
if hasattr(reward_giver, "obs_rms"): reward_giver.obs_rms.update(np.concatenate((ob_batch, ob_expert), 0))
*newlosses, g = reward_giver.lossandgrad(ob_batch, ac_batch, ob_expert, ac_expert)
d_adam.update(allmean(g), d_stepsize)
% 更新判别器
% adam的训练器 在 152行 由 d_adam = MpiAdam(reward_giver.get_trainable_variables()) 生成
d_losses.append(newlosses)
Policy的训练 和 TRPO的训练方式 是一样的 但是利用的reward是 由 判别器 get_reward得到的。其余是一样的 就不赘述了