学习笔记TF037:实现强化学习策略网络

强化学习(Reinforcement Learing),机器学习重要分支,解决连续决策问题。强化学习问题三概念,环境状态(Environment State)、行动(Action)、奖励(Reward),目标获得最多累计奖励。强化学习模型根据环境状态、行动和奖励,学习出最佳策略,以最终结果为目标,不能只看某个行动当下带来的利益,还要看行动未来带来的价值。

AutoEncoder属于无监督学习,MLP、CNN、RNN属于监督学习,强化学习目标变化、不明确,或不存绝对正确标签。

Google DeepMind结合强化学习和深度学习,提出DQN(Deep Q-Network,深度Q网络)。AlphaGo结合策略网络(Policy Network)、估值网络(Value Network,DQN)、蒙特卡洛搜索树(Monte Carlo Tree Search)。

无人驾驶是非常复杂、困难强化学习任务。无人驾驶汽车通过摄像头、雷达、激光测距仪、传感器观测环境,获取丰富环境信息,深度强化学习模型CNN、RNN处理、抽象、转化环境信息,结合强化学习算法框架预测最应执行动作(加速、减速、转换方向),实现自动驾驶。每次执行动作,到目的地路程更短,作为每次行动奖励。最终目标是安全顺利到达目的地,得到奖励最多。

强化学习两大类,Policy-Based(Policy Gradients)和Value-Based(Q-Learning)。Policy-Based直接预测环境状态下应采取Action,Value-Based预测环境状态下所有Action期望价值(Q值),选择Q值最高Action执行。Value-Based适合少量离散取值Action,Policy-Based适合Aciton种类多或连续取值Action环境。Policy Network、Value Network。

根据环境状态和采取行动预测后续环境状态,利用信息训练强化学习模型,是Model-Based RL。Model-Free RL直接对策略或Action期望价值预测,计算效率高。复杂环境,主要用Model-Free RL,供给更多样本训练,弥补没有Model预测环境状态问题。

环境中,强化学习模型载体Agent,负责执行模型行动。环境,Agent无法控制,可以观察。根据观察结果,模型给出行动,Agent执行。Reward,环境状态下执行Action获得,模型争取目标。Reward延迟获到Delayed。Action即时获得Reward,和未来获得Reward有很大关系。

策略网络,建立神经网络模型,通过观察环境状态,直接预测目前最应该执行策略(Policy),执行策略获得最大期望收益(包括现在、未来Reward)。没有绝对正确学习目标,样本feature不再和label对应。特定环境状态,不知道对应最好Action,只知道当前Action获得Reward,试验后获得未来Reward,强化学习模型通过试验样本学习环境状态下比较好的Action。样本没有绝对正确label,只有估算label。策略网络,不只用当前Reward作label,用Discounted Future Reward,所有未来奖励依次乘以衰减系数y。衰减系数,略小于但接近1,防止没有损耗积累导致Reward目标发散,代表未来奖励不确定性估计。

Policy Gradients方法训练策略网络。模型通过学习Action在Environment获得反馈,用梯度更新模型参数。训练过程,模型接触到好Action及高期价值,和差Action及低期望价值。通过样本学习,模型逐渐增加选择好Action概率,降低选择坏Action概率,完成策略学习。直接学习当前环境应该采取策略,如选择Actionc概率,或Action具体数值。策略网络是End-to-End(端对端)方法,直接产生最终策略。

Policy-Based比Value-Based,收敛性更好,通常可以保证收敛到局部最优,且不会发散。对高维、连续值Action,训练、输出结果都更高效。能学习出带有随机性的策略。

Gym辅助策略网络训练。Gym,OpenAI开源强化学习环境生成工具。OpenAI,Tesla、Space X CEO Elon Musk发起非营利人工智能研究机构。研究安全、开放人工智能技术,确保人工智能技术广泛、公平普及服务社会。Gym,提供方便强化学习任务环境,强化学习算法效率、性能比较。Gym提供大量标准化环境,用来公平横向对比强化学习模型性能。Gym用户上传模型效果、训练日志到OpenAI Gym Service接口,参与任务排名,比较模型效果,分享算法思路。

OpenAI Gym,对用户开发模型方式无限制,和其他机器学习库完全兼容(TensorFlow、Theano)。可以用Python语言、任何Python Library编写强化学习模型Agent。如创建简单经验规则,使用State-Action一一对应策略表,深度神经网络模型训练。

Gym,两个核心概念。Environment,任务、问题。Agent,策略、算法。Agent将执行Action传给Environment,Environment接受Action,结果Observation(环境状态)和Reward返回Agent。Gym提供完整Environment接口,Agent完全由用户编写。Gym包含环境,Algorithmic(算法)、Atari游戏(Arcade Learning Environment)、Board Games(棋牌类游戏 Pachi)、Box2D(二维物理引擎)、Classic Control(经典控制)、MuJoCo(高效处理引擎)、Toy Text(文本类型)任务。执行full install安装全部环境依赖程序。

Gym环境接口,Env类。env=gym.make('Copy-v0')创建任务环境。env.reset()初始化环境,返回初始observation state。evn.step(action)当前状态执行一步Action,返回observation、reward、done(完成标记)、info(调试信息)。env.render()渲染一帧任务图像,Agent直接从图像像素学习信息策略。

Gym CartPole环境,《Neuronlike Adaptive Elements That Can Solve Difficult Learning Control Problem》,经典可用强化学习解决控制问题。CartPole环境有小车,一维无阻力轨道,行动。车上绑连接不太结实杆,左右摇晃。环境信息observation 是有4个值数组,包含小车位置、速度,杆角度、速度。不需要知道数值物理含义。设计策略网络,从数值学习环境信息,制定最佳策略。Action,小车施加正向力、负向力。Action Space,Action离散数值空间。CartPole Action Space,Discrete(2),只有0、1。只要模型学习到采取Action后带来的影响。Action只是编码。CartPole任务,尽可能保持杆竖直不倾倒,小车偏离中心超过2.4个单位距离,杆倾角超过15度,任务失败,自动结束。每坚持一步,reward+1。Reward恒定。模型要考虑到长远利益,不只是学习当前Reward。

env.reset()方法初始化环境,获取环境第一个Observation。根据Observation预测应该采取Action,用env.step(action),在环境中执行Action,返回Observation(CartPole 4维抽象特征)、reward(当前Action即时奖励)、done(任务是否结束标记,True,reset任务)、info(额外诊断信息)。进入Action-Observation循环,期望任务结束时尽可能高奖励。Action在CartPole离散数值空间,有限几种可能。别的任务可能是连续数值空间。环境名称后带版本号,环境发生更新或变化,不修改之前环境,创建新版本,Agent性能公平比较。调用env.monitor方法,监控、记录模型训练过程。gym.upload,训练日志上传到gym service展示,与他人算法比较。简单问题评测标准,需要多少步训练可以稳定达到理想分数。复杂问题评测标准,获得分数越高越好。

TensorFlow创建基于策略网络Agent,解决CartPole问题。先安装OpenAI Gym。pip install gym 。载入Numpy、TensorFlow、gym。gym.make('CartPole-v0')创建CartPole问题环境env。

先测试CartPole环境随机Action表现,作对比baseline。env.reset()初始化环境,10次随机试验,env.render()渲染CartPole问题图像。np.random.randint(0,2)产生随机Action。env.step()执行随机Action,获取返回observation、reward、done。如done标记为True,一次试验结束,倾角超过15度或偏离中心过远,任务失败。展示试验累计奖励reward_sum,重启环境。

随机策略奖励总值在1040,均值在2030。任务完成目标设定200 Reward,通过尽量少次数试验完成。

策略网络用简带一个隐含层MLP。设置网络超参数,隐含节点数H设50,bactch_size设25,学习速率learning_rate 0.1,环境信息observation维度D 4,gamma Reward discount比例0.99。估算Action期望价值(估算样本学习目标),考虑Delayed Reward,Action之后获得所有Reward做discount累加,让模型学习未来可能出现的潜在Reward。discount比例小于1,防止Reward无损耗累加导致发散,可以区分当前Reward和未来Reward价值,Action直接带来的Reward不需要discount,未来Reward存在不确定性需要discount。

定义策略网络结构,网络接受observation 输入信息,输出概率值,用以选择Action,向左施加力,向右施加力。创建输入信息observation placeholder,维度D。tf.contrib.layers.xavier_initializer初始化算法创建隐含层权重W1,维度[D,H]。tf.matmul,环境信息observation乘W1,用ReLU激活函数处理得到隐含层输出layer1,不加偏置。xavier_initializer算法创建最后Sigmoid输出层权重W2,隐含层输出layer1乘W2,Sigmoid激活函数处理得到最后输出概率。

模型优化器用Adam算法。设置两层神经网络参数梯度placeholder,W1Grad、W2Grad。adam.apply_gradients定义更新模型参数操作updateGrads。计算参数梯度,积累一定样本量梯度,传入W1Grad和W2Grad,执行updateGrads更新模型参数。深度强化学习训练用batch training。不逐个样本更新参数,累计一个batch_size样本梯度再更新参数,防止单一样本随机扰动噪声对模型带来不良影响。

定义函数discount_rewards,估算每个Action对就潜在价值discount_r。CartPole问题每次获得Reward和前面Action有关,属于delayed reward。需要比较精准衡量每个Action实际带来价值,不能只看当前这步Reward,要考虑后面Delayed Reward。让Pole长时间保持在空中竖直Action,应该有较大期望价值。最终导致Pole倾例Action,有较小期望价值。越靠后Acion期望价值越小,越靠前Acion期望价值越大。倒推过程,最后Action开始计算所有Action应该对应期望价值。输入数据r ,每个Action实际获得Reward,CartPole,最后结束时Action 0,其余 1。定义每个Action除直接获得Reward外,潜在价值running_add。running_add,从后向前累计,经过discount衰减。每个Action潜在坐,后一Action潜在价值乘以衰减系数gamma,加直接获得reward,running_add*gamma+r[t]。从最后Action,向前累计计算,得到全部Action潜在价值。

定义人工设置虚拟label placeholder input_y。每个Action潜在价值placeholder advangtages。loglik,Action取值 1概率probability(策略网络输出概率),Action取值 0概率 1-probability。label取值,label=1-Action。Action 1,label 0,loglik=tf.log(probability),Action取值为1的概率对数。Action 0,label 1,loglik=tf.log(1-probability),Action取值为0的概率对数。loglik,当前Action对应概率对数。loglik与潜在坐advantages相乘,取负数作损失,优化目标。优化器优化,能获得较多advantages Action概率变大,能获得较少advantages Action概率变小,损失变小。不断训练,持续加大能获得较多advantages Action概率,学习到一个能获得更多潜在价值策略。tf.trainable_variables()获取策略网络全部可训练参数tvars,tf.gradients求解模型参数 loss梯度。

定义参数,xs环境信息observation列表,ys label列表,drs记录每个Action Reward,reward_sum累计Reward,总试验次数total_episodes10000。达到200 Reward停止训练。

创建默认Session,初始化全部参数,一开始render标志关闭。render较大延迟,一开始不太成熟模型没必要观察。初始化CartPole环境,获得初始状态。sess.run执行tvars获取所有模型参数,创建储存参数梯度缓冲器gradBuffer,gardBuffer全部初始化零。每次试验收集参数梯度存储到gradBuffer,直到完成一个batch_size试验,汇总梯度更新模型参数。

试验循环,最大循环次数total_episodes。batch 平均Reward达到100以上,Agent表现良好,调用env.render()展示试验环境。tf.reshape将observation变形策略网络输入格式,传入网络,sess.run执行probability获得网络输出概率tfprob,Action取值1的概率。(0,1)间随机抽样,随机值小于tfprob,令Action取1,否则取0,Action取值 1概率为tfprob。

输入环境信息添加到列表xs,制造虚拟label——y,取值与Action相反,y=1-Action,添加到列表ys。env.step执行一次Action,获取observation、reward、done、info,reward 累加到reward_sum,reward添加到列表drs。

done为True,一次试验结束,episode_number加1。np.vstack 将列表xs、ys、drs元素纵向堆叠,得到epx、epy、epr,将xs、ys、drs清空,下次试验用。epx、epy、epr,一次试验中获得的所有observation、label、reward列表。discount_rewards函数计算每步Action潜在价值,标准化(减去均值再除以标准差),得零均值标准差1分布。dicount_reward参与模型损失计算。

epx、epy、discounted_epr输入神经网络,newGrads求解梯度。获得梯度累加gradBuffer。

试验次数达到batch_size整倍数,gradBuffer累计足够梯度,用updateGrads将gradBuffer中梯度更新到策略网络模型参数,清空gradBuffer,计算下一batch梯度准备。一个batch梯度更新参数,每个梯度是使用一次试验全部样本(一个Action一个样本)计算,一个batch样本数 25(batch_size)次试验样本数和。展示当前试验次数episode_number,batch内每次试验平均reward。batch内每次试验平均reward大于200,策略网络完成任务终止循环。如没达目标,清空reward_sum,重新累计下一batch总reward。每次试验结束,任务环境env重置。

模型训练日志,策略网络200次试验,8个batch训练和参数更新,实现目标,batch内平均230 reward。可以尝试修改策略网络结构、隐含节点数、batch_size、学习速率参数优化训练,加快学习速度。

import numpy as np
import tensorflow as tf
import gym
env = gym.make('CartPole-v0')
env.reset()
random_episodes = 0
reward_sum = 0
while random_episodes < 10:
    env.render()
    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()
    
# hyperparameters
H = 50 # number of hidden layer neurons
batch_size = 25 # every how many episodes to do a param update?
learning_rate = 1e-1 # feel free to play with this to train faster or more stably.
gamma = 0.99 # discount factor for reward
D = 4 # input dimensionality        
tf.reset_default_graph()
#This defines the network as it goes from taking an observation of the environment to 
#giving a probability of chosing to the action of moving left or right.
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)
#From here we define the parts of the network needed for learning a good policy.
tvars = tf.trainable_variables()
input_y = tf.placeholder(tf.float32,[None,1], name="input_y")
advantages = tf.placeholder(tf.float32,name="reward_signal")
# The loss function. This sends the weights in the direction of making actions 
# that gave good advantage (reward over time) more likely, and actions that didn't less likely.
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)
# Once we have collected a series of gradients from multiple episodes, we apply them.
# We don't just apply gradeients after every episode in order to account for noise in the reward signal.
adam = tf.train.AdamOptimizer(learning_rate=learning_rate) # Our optimizer
W1Grad = tf.placeholder(tf.float32,name="batch_grad1") # Placeholders to send the final gradients through when we update.
W2Grad = tf.placeholder(tf.float32,name="batch_grad2")
batchGrad = [W1Grad,W2Grad]
updateGrads = adam.apply_gradients(zip(batchGrad,tvars))
def discount_rewards(r):
    """ take 1D float array of rewards and compute discounted reward """
    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

xs,ys,drs = [],[],[]
#running_reward = None
reward_sum = 0
episode_number = 1
total_episodes = 10000
init = tf.global_variables_initializer()
# Launch the graph
with tf.Session() as sess:
    rendering = False
    sess.run(init)
    observation = env.reset() # Obtain an initial observation of the environment
    # Reset the gradient placeholder. We will collect gradients in 
    # gradBuffer until we are ready to update our policy network. 
    gradBuffer = sess.run(tvars)
    for ix,grad in enumerate(gradBuffer):
        gradBuffer[ix] = grad * 0

    while episode_number <= total_episodes:
    
        # Rendering the environment slows things down, 
        # so let's only look at it once our agent is doing a good job.
        if reward_sum/batch_size > 100 or rendering == True : 
            env.render()
            rendering = True
        
        # Make sure the observation is in a shape the network can handle.
        x = np.reshape(observation,[1,D])
    
        # Run the policy network and get an action to take. 
        tfprob = sess.run(probability,feed_dict={observations: x})
        action = 1 if np.random.uniform() < tfprob else 0
    
        xs.append(x) # observation
        y = 1 if action == 0 else 0 # a "fake label"
        ys.append(y)
        # step the environment and get new measurements
        observation, reward, done, info = env.step(action)
        reward_sum += reward
        drs.append(reward) # record reward (has to be done after we call step() to get reward for previous action)
        if done: 
            episode_number += 1
            # stack together all inputs, hidden states, action gradients, and rewards for this episode
            epx = np.vstack(xs)
            epy = np.vstack(ys)
            epr = np.vstack(drs)
            xs,ys,drs = [],[],[] # reset array memory
            # compute the discounted reward backwards through time
            discounted_epr = discount_rewards(epr)
            # size the rewards to be unit normal (helps control the gradient estimator variance)
            discounted_epr -= np.mean(discounted_epr)
            discounted_epr /= np.std(discounted_epr)
        
            # Get the gradient for this episode, and save it in the gradBuffer
            tGrad = sess.run(newGrads,feed_dict={observations: epx, input_y: epy, advantages: discounted_epr})
            for ix,grad in enumerate(tGrad):
                gradBuffer[ix] += grad
            
            # If we have completed enough episodes, then update the policy network with our gradients.
            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
            
                # Give a summary of how well our network is doing for each batch of episodes.
                #running_reward = reward_sum if running_reward is None else running_reward * 0.99 + reward_sum * 0.01
                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()

参考资料:
《TensorFlow实战》

欢迎付费咨询(150元每小时),我的微信:qingxingfengzi

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容