Tensorflow实例:实现深度强化学习--策略网络

来源:互联网 发布:什么叫编程 编辑:程序博客网 时间:2024/05/24 06:27

深度强化学习简介

强化学习(reinforcement Learning)是机器学习的一个重要分支,主要用来解决连续决策的问题。强化学习可以在复杂的、不确定的环境中学习如何实现我们设定的目标。
一个强化学习问题包括三个主要概念,即

  • 环境状态(Environment State)
  • 行动(Action)
  • 奖励(Reward)

而强化学习的目标就是获得最多的累计奖励。我们要让强化学习模型根据环境状态、行动和奖励,学习出最佳的策略,并以最终结果为目标,不能只看某个行动当下带来的利益,还要看到这个行动未来能带来的价值。
我们回顾一下,AutoEncoder属于无监督学习,而MLP、CNN和RNN都属于监督学习,但强化学习跟这两种都不同。它不像无监督学习那样完全没有学习目标,也不像监督学习那样有非常明确的目标(即label),强化学习的目标一般是变化的、不明确的,甚至可能不存在绝对正确的标签。
Google DeepMind结合强化学习与深度学习,提出了DQN(Deep Q-Network,深度Q网络)。DeepMind使用的这些深度强化学习模型(Deep Reinforcement Learning)本质上也是神经网络,主要分为策略网络和估值网络两种
无人驾驶是一个非常复杂、非常困难的强化学习任务,在深度学习出现之前,几乎不可能实现。

这里写图片描述

在深度学习方法中,无人驾驶汽车通过摄像头、雷达、激光测距仪、传感器等对环境进行观测,获取到许多丰富的环境信息,然后通过深度强化学习模型中的CNN、RNN等对环境信息进行处理、抽象和转化,再结合强化学习算法框架预测出最应该执行的动作(加速、减速、转换方向等),来实现自动驾驶。

深度强化学习最具代表性的一个里程碑自然是AlphaGo。AlphaGo中使用了快速走子(Fast Rollout)、策略网络、估值网络和蒙特卡洛搜索树等技术。

Policy-Based(或者Policy Gradients)Valued-Based(或者Q-Learning)是强化学习中最重要的两类方法:

  • Policy-Based的方法直接预测在某个环境状态下应该采取的Action
  • Value Based的方法则预测某个环境状态下所有Action的期望价值(Q值),之后可以通过选择Q值最高的Action执行策略。

这两种方法的出发点和训练方式都不同,一般来说,Value Based方法适合仅有少量离散取值的Action的环境,而Policy Based方法则更通用,适合Action种类非常多或者连续取值的Action的环境。而结合深度学习后,Policy-Based的方法就成了Policy Network,而Value-Based的方法则成了Value Network。

Tensorflow实现策略网络

所谓策略网络,即建立一个神经网络模型,它可以通过观察环境状态,直接预测出目前最应该执行的策略(Policy),执行这个策略可以获得最大的期望收益(包括现在的和未来的Reward)。
与普通的监督学习不同,在强化学习中,可能没有绝对正确的学习目标,样本的feature不再和label一一对应。对某个特定的环境状态,我们并不知道它对应的最好的Action是什么,只知道当前Action获得的Reward还有试验后获得的未来的Reward。我们需要让强化学习模型通过试验样本自己学习什么才是某个环境状态下比较好的Action,而不是告诉模型什么才是比较好的Action,因为我们也不知道正确的答案。
为了更好地让策略网络理解未来的、潜在的Reward,策略网络不只是使用当前的Reward作为label,而是使用Discounted Future Reward,即把所有未来奖励依次乘以衰减系数Υ。这里的衰减系数一般是一个略小于但接近1的数,防止没有损耗地累积导致Reward目标发散,同时也代表了对未来奖励地不确定性地估计

r=r1+Υr2+Υ2r3+...+Υn1rn

我们使用被称为Policy Gradients的方法来训练策略网络。Policy Gradients指的是模型通过学习Action在Environment中获得的反馈,使用梯度更新模型参数的过程。在训练过程中,模型会接触到好的Action及它们带来的高期望价值,和差Action及它们带来的低期望价值,因此通过对这些样本的学习,我们的模型会逐渐增加选择好Action的概率,并降低选择坏Action的概率,这样就逐渐完成了我们对策略的学习。
和Q-Learning或估值网络不同,策略网络学习的不是某个Action对应的期望价值Q,而是直接学习在当前环境应采取的策略。因此,策略网络是一种End-to-End(端对端)的方法,可以直接产生最终的策略。

Gym:强化学习环境生成工具

我们需要使用Gym辅助我们进行策略网络的训练。Gym是OpenAI推出的开源的强化学习的环境生成工具,让用户可以和其他人的强化学习算法进行效率、性能上的比较。Gym提供了大量的标准化的环境,可以用来公平地横向对比强化学习模型地性能。
在Gym中,有两个核心的概念,一个是Environment,指我们的任务或者问题,另一个就是Agent,即我们编写的策略或算法。Agent会将执行的Action传给Environment,Environment接受某个Action后,再将结果Observation(即环境状态)和Reward返回给Agent。

以Gym中的CartPole环境作为具体例子

这里写图片描述

CartPole的环境中有一辆小车,在一个一维的无阻力轨道上行动,在车上绑着一个连接不太结实的杆,这个杆会左右摇晃。我们的环境信息并不是图像像素,而只是一个有4个值的数组,包含了环境中的各种信息,比如小车的位置、速度、杆的角度、速度等。我们要设计一个策略网络让它自己从这些数值中学习到环境信息,并制定最佳策略。我们可以采用的策略非常简单,给小车施加一个正向的力或负向的力。

import numpy as npimport tensorflow as tfimport gym# 创建CartPole问题的环境envenv = gym.make('CartPole-v0')# 先测试在CartPole环境中使用随机Action的表现,作为接下来对比的baseline。env.reset() # 初始化环境random_episodes = 0reward_sum = 0while random_episodes < 10:    env.render() # 将CartPole问题的图像渲染出来    observation, reward, done, _ = env.step(np.random.randint(0, 2))    reward_sum += reward    if done:        random_episodes += 1        print("Reward for this episode was:", reward_sum)        reward_sum = 0        env.reset()# 我们的策略网络使用简单的带有一个隐含层的MLP。H = 50 # 隐含层节点数batch_size = 25learning_rate = 1e-1D = 4 # 环境信息observation的维度为4gamma = 0.99 # reward的discount比例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)# 这里模型的优化器使用Adam算法。我们分别设置两层神经网络参数的梯度:W1Grad和W2Grad,并使用# adam.apply_gradients定义我们更新模型参数的操作updateGrads。之后计算参数的梯度,当累积到一# 定样本量的梯度,就传入W1Grad和W2Grad,并执行updateGrads更新模型参数。我们不逐个样本地更新# 参数,而是累计一个batch_size的样本的梯度再更新参数,防止单一样本随机扰动的噪声对模型带来# 不良影响adam = tf.train.AdamOptimizer(learning_rate=learning_rate)W1Grad = tf.placeholder(tf.float32, name='batch_grad1')W2Grad = tf.placeholder(tf.float32, name='batch_grad2')tvars = tf.trainable_variables()batchGrad = [W1Grad, W2Grad]updateGrads = adam.apply_gradients(zip(batchGrad, tvars))# 下面定义discount_rewards,用来估算每一个Action对应的潜在价值discount_rdef discount_rewards(r):    discounted_r = np.zeros_like(r)    running_add = 0    for t in reversed(range(r.size)):        running_add = running_add * gamma + r[t]        discounted_r[t] = running_add    return discounted_r# 我们定义人工设置的虚拟label的placeholder---input_y,以及每个Action的潜在价值的placeholder---# advangtages.input_y = tf.placeholder(tf.float32, [None, 1], name="input_y")advantages = tf.placeholder(tf.float32, name="reward_signal")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, ys, drs = [], [], []reward_sum = 0episode_number = 1total_episodes = 10000with tf.Session() as sess:    rendering = False    init = tf.global_variables_initializer()    sess.run(init)    obervation = 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:            env.render()            rendering = True        x = np.reshape(observation, [1, D])        tfprob = sess.run(probability, feed_dict={observations: x})        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()
阅读全文
0 0