OPENAI Baeslines 详解(十)GAIL

Zee带你看代码系列

学习强化学习,码代码的能力必须要出众,要快速入门强化学习 搞清楚其中真正的原理,读源码是一个最简单的最直接的方式。最近创建了一系列该类型文章,希望对大家有多帮助。
传送门

另外,我会将所有的文章及所做的一些简单项目,放在我的个人网页上。
水平有限,可能有理解不到位的地方,希望大家主动沟通交流。
邮箱:[email protected]

Thanks for reading, and enjoy yourself。

OPENAI Baeslines 详解(十)GAIL

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

程序(简略、重点版)

bahavior clone

这个比较简单 其实就是将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得到的。其余是一样的 就不赘述了

你可能感兴趣的:(强化学习-读代码懂原理系列)