深度学习—策略网络

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

深度学习—策略网络_第1张图片

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

import gym
import numpy as np
import tensorflow as tf
env=gym.make('CartPole-v0')#先创造一个环境
env.reset()#初始化环境
random_episodes=0
reward_sum=0
while 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#隐含节点数为50
batch_size=25
learning_rate=0.1
D=4#observation的维度D为4
gamma=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 reward
def 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-advangtages
tvars=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的reward
xs,ys,drs=[],[],[]
reward_sum=0
episode_number=1
total_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()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


你可能感兴趣的:(机器学习,TensorFlow)