深度学习—策略网络

来源:互联网 发布:大连seo搜索排名 编辑:程序博客网 时间:2024/05/22 03:43

      我们前面已经稍微地介绍了强化学习的内容,这一篇我们将简单地介绍一下使用TF和强化学习的方法解决CartPole问题。CartPole的环境中有一辆小车,在一个一维的无阻力轨道上运动,在车上绑着一个连接不太结实的杆,这个杆会左右摇晃。环境信息是一个有4个值的数组,包含了环境的各种信息,包括小车位置,速度,杆的角速度,速度。我们能采取的Action非常简单,就是给小车施加一个正向的或者负向的力。当小车偏离中心偏离中心2.4个单位的距离,或者杆的倾角超过15度时,我们的任务就自动结束。每坚持一步,我们就获得+1的reward。我们的模型要有远见,要考虑到长久的利益,而不是只学习到当前的reward。


      我们将使用gym这个库。总所皆知,强化学习事实上最难的部分在于构建环境,这涉及到的知识太多,我们直接使用gym里面的环境,根据其返回的状态来决定我们的action。为了做一个对比,我们先给小车施加一个随机的力,做十次实验,观察获得的奖励,以作对比。

import gymimport numpy as npimport tensorflow as tfenv=gym.make('CartPole-v0')#先创造一个环境env.reset()#初始化环境random_episodes=0reward_sum=0while random_episodes<10:    env.render()#将CartPole问题的图像渲染出来
    observation,reward,done,_=env.step(np.random.randint(0,2))#产生随机的Action,并返回,如果Done标记为True,则实验结束

    reward_sum+=reward    if done:        random_episodes+=1        print('Reward for this episode was:',reward_sum)        reward_sum=0        env.reset()
运行程序,我们可以看到采用随机策略获得的reward差不多在10-35之间。那么我们的目标是使用策略网络,拿200左右的分数。

我们的策略网络使用简单的带有一个隐藏层的MLP,先设置网络的各个超参数H=50#隐含节点数为50batch_size=25learning_rate=0.1D=4#observation的维度D为4gamma=0.99#reward的discount比例(衰减比例)为0.99,当前的reward不需要discount,而未来的reward需要
#下面定义策略网络的具体结构,这个网络将接收observation为输入信息,最后输出一个概率值用于选择action

tf.reset_default_graph()observations=tf.placeholder(tf.float32,[None,D],name='input_x')w1=tf.get_variable('w1',shape=[D,H],initializer=tf.contrib.layers.xavier_initializer())layer1=tf.nn.relu(tf.matmul(observations,w1))#注意,这里我们不加偏置w2=tf.get_variable('w2',shape=[H,1],initializer=tf.contrib.layers.xavier_initializer())score=tf.matmul(layer1,w2)probability=tf.nn.sigmoid(score)#使用sigmoid激活函数作为输出#模型使用Adam算法adam=tf.train.AdagradOptimizer(learning_rate=learning_rate)W1Grad=tf.placeholder(tf.float32,name='batch_grad1')W2Grad=tf.placeholder(tf.float32,name='batch_grad2')#设置两层神经网络参数的梯度的placeholder,累计一个batch_size的梯度才更新参数batchGrad=[W1Grad,W2Grad]tvars=tf.trainable_variables()updateGrads=adam.apply_gradients(zip(batchGrad,tvars))#下面定义函数discount_rewards,用来估算每一个action对应的潜在价值discount_r#因为cartpole问题中每次获得的reward都与前面的action有关,输入delayed reward,因此需要比较精确地衡量每一个action实际带来的价值时,不能只看这一步的reward,还要考虑后面的delayed rewarddef discount_rewards(r):#r为每一个action实际获得的reward    discounted_r=np.zeros_like(r)    running_add=0#定义其为出直接获得的reward之外的潜在价值    for t in reversed(range(r.size)):        running_add=running_add*gamma+r[t]        discounted_r[t]=running_add    return discounted_r#接下来我们要定义人共设置的虚拟labelde placeholder-input_y,以及每个action潜在价值的placeholder-advangtagestvars=tf.trainable_variables()input_y=tf.placeholder(tf.float32,[None,1],name='input_y')advantages=tf.placeholder(tf.float32,name='reward_signal')#定义loglik,action取值为1的的概率为probability,取值为0的概率为1-probability#而label的取值与action相反loglik=tf.log(input_y*(input_y-probability)+(1-input_y)*(input_y+probability))loss=tf.reduce_mean(loglik*advantages)newGrads=tf.gradients(loss,tvars)#正式进入训练之前,先定义一些参数,xs为observation的列表,ys为我们定义的label的列表,drs为我们记录的每一个action的rewardxs,ys,drs=[],[],[]reward_sum=0episode_number=1total_episodes=10000#最大循环次数with tf.Session() as sess:    rendering=False    init=tf.global_variables_initializer()    sess.run(init)    observation=env.reset()    gradBuffer=sess.run(tvars)    for ix,grad in enumerate(gradBuffer):        gradBuffer[ix]=grad*0    while episode_number<=total_episodes:        if reward_sum/batch_size>100 or rendering==True:#当某个action表现良好时,调用env.render()对环境进行展示                env.render()            rendering=True        x=np.reshape(observation,[1,D])        tfprob=sess.run(probability,feed_dict={observations:x})#传网络中,获得action取值为1的概率

        action=1 if np.random.uniform()<tfprob else 0        xs.append(x)        y=1-action        ys.append(y)        observation,reward,done,info=env.step(action)        reward_sum+=reward        drs.append(reward)        if done:            episode_number+=1            epx=np.vstack(xs)            epy=np.vstack(ys)            epr=np.vstack(drs)            xs,ys,drs=[],[],[]            discounted_epr=discount_rewards(epr)            discounted_epr-=np.mean(discounted_epr)            discounted_epr/=np.std(discounted_epr)            tGrad=sess.run(newGrads,feed_dict={observations:epx,input_y:epy,advantages:discounted_epr})            for ix,grad in enumerate(tGrad):                gradBuffer[ix]+=grad            if episode_number%batch_size==0:                sess.run(updateGrads,feed_dict={W1Grad:gradBuffer[0],W2Grad:gradBuffer[1]})                for ix,grad in enumerate(gradBuffer):                    gradBuffer[ix]=grad*0                print('Average reward for episode %d:%f.'%(episode_number,reward_sum/batch_size))                if reward_sum/batch_size>200:                    print('Task solved in',episode_number,'episodes!')                    break                reward_sum=0            observation=env.reset()

      看完这段程序,就会突然觉得一开始说的良好的数学基础有多么重要!在接触策略网络之前,最好还是把具体的算法和原理看一看,这样思路就比较清晰。无论是自动驾驶,还是AlphaGo,都是建立在深度强化学习的基础上的,而要学好它,良好的数学基础和严谨的思维逻辑实在太重要了!不过博主的研究领域不在强化学习这一块,因此也并不用过多地深究。做到这里,我强烈建议有条件的同学使用linux进行编程,因为博主本想介绍估值网络和tensorboard(可视化工具),但是由于软件和硬件方面的区别,在多个方面都遇到了比较麻烦的问题,这些问题我想等入学之后用实验室的电脑来处理,因此此处暂时不表。

     TF中还有两个比较重要的组成部分,就是tf.learn和tf.contrib模块。learn模块可以理解为是类似于sklearn模块,用于更加简单地上手机器学习;contrib模块则集中了许多开源社区的成果,特别是一些比较新的功能,google将代码放在这里供用户们测试,根据反馈进行修改,等到API较为稳定的时候,就能被移到TF的核心模块。总之,TF是一个开源的模块,因此它的内容和知识点永远也学不完。我们选择我们所需要的进行学习即可。关于使用TF进行机器学习的篇幅到这里就结束了,我把所有涉及到的代码都放在下面链接中链接:http://pan.baidu.com/s/1hr9GO40 密码:krfk


原创粉丝点击