基于tensorflow的最简单的强化学习入门-part1.5: 基于上下文老虎机问题(Contextual Bandits)

封面

本文翻译自 Simple Reinforcement Learning with Tensorflow Part 1.5: Contextual Bandits, 作者是 Arthur Juliani, 原文链接

介绍

在这个系列的前一部分文章中,我们介绍了增强学习的一些概念,并且演示了如何通过建立一个agent来解决多臂老虎机问题(Multi-arm bandits)。多臂老虎机可以当作一种特殊的增强学习问题,没有状态(state),只需要采取行动(action)并获取最大的奖励(reward)即可。由于没有给定的状态,那么任意时刻的最佳动作始终都是最佳的动作。而在第二部分的文章展示了完整的强化学习问题,其中包括环境状态延迟奖励

事实上,在无状态问题和完整的强化学习问题上还存在着一些不同,我想提供一个这样的例子来展示如何解决它。我希望对强化学习不太了解的朋友们可以通过在逐步的学习中有所收获。这这篇文章中,作为第一篇文章和第二篇文章的过渡,我将展示如何解决有状态的问题,但是我们不会考虑延迟奖励,所有这些都将出现在第二部分的文章中。这种简化的强化学习问题称为上下文老虎机问题。

多臂老虎机问题(只有行动和回报),上下文老虎机问题(有状态,行动和回报):完全RL问题(奖励有可能在时间上延迟)

上下文老虎机问题

在第一部分讨论多臂老虎机问题中,我们可以认为只有一个老虎机。agent可能的动作就是拉动老虎机中一个机臂,通过这种方式以不同的频率得到+1或者-1的奖励。在这个问题中,agent会永远选择同一个机械臂,该臂带来的回报最多。因此,我们设计的agent完全忽略环境状态,环境状态不会影响我们采取的动作和回报,所以对于所有的动作来说只有一种给定的状态

上下文老虎机问题中带来了状态的概念。状态包含agent能够利用的一系列环境的描述和信息。在这个例子中,有多个老虎机而不是一个老虎机,状态可以看做我们正在操作哪个老虎机。我们的目标不仅仅是学习单一老虎机的操作方法,而是很多老虎机。在每一个老虎机中,转动每一个机臂带来的回报都会不一样,我们的agent需要学习到在不同状态下(老虎机)执行动作所带来的回报。为了实现这个功能,我们会基于tensorflow构造一个简单的神经网络,输入状态并且得到动作的权重。通过策略梯度更新方法,我们的agent就可以学习到不同状态下如何获得最大的回报。下面是实现上述过程的python的代码:

定义上下文老虎机

这里我们定义上下文老虎机,在这个例子中,我们使用三个多臂老虎机,不同的老虎机有不同的概率分布,因此需要执行不同的动作获取最佳结果。getbandit函数随机生成一个数字,数字越低就越可能产生正的回报。我们希望agent可以一直选择能够产生最大收益的老虎机臂

import tensorflow as tf
import tensorflow.contrib.slim as slim
import numpy as np


class contextual_bandit():
    def __init__(self):
        self.state = 0
        #List out our bandits. Currently arms 4, 2, and 1 (respectively) are the most optimal.
        self.bandits = np.array([[0.2,0,-0.0,-5],[0.1,-5,1,0.25],[-5,5,5,5]])
        self.num_bandits = self.bandits.shape[0]
        self.num_actions = self.bandits.shape[1]
        
    def getBandit(self):
        self.state = np.random.randint(0,len(self.bandits)) #Returns a random state for each episode.
        return self.state
        
    def pullArm(self,action):
        #Get a random number.
        bandit = self.bandits[self.state,action]
        result = np.random.randn(1)
        if result > bandit:
            #return a positive reward.
            return 1
        else:
            #return a negative reward.
            return -1

策略梯度的agent

这段代码建立了一个简单的基于神经网络的agent,其中输入为当前的状态,输出为执行的动作。这使得agent可以根据当前的状态执行不同的动作。agent使用一组权重,每一个作为在给定状态下执行特定动作的回报的估计。

class agent():
    def __init__(self, lr, s_size,a_size):
        #These lines established the feed-forward part of the network. The agent takes a state and produces an action.
        self.state_in= tf.placeholder(shape=[1],dtype=tf.int32)
        state_in_OH = slim.one_hot_encoding(self.state_in,s_size)
        output = slim.fully_connected(state_in_OH,a_size,\
            biases_initializer=None,activation_fn=tf.nn.sigmoid,weights_initializer=tf.ones_initializer())
        self.output = tf.reshape(output,[-1])
        self.chosen_action = tf.argmax(self.output,0)

        #The next six lines establish the training proceedure. We feed the reward and chosen action into the network
        #to compute the loss, and use it to update the network.
        self.reward_holder = tf.placeholder(shape=[1],dtype=tf.float32)
        self.action_holder = tf.placeholder(shape=[1],dtype=tf.int32)
        self.responsible_weight = tf.slice(self.output,self.action_holder,[1])
        self.loss = -(tf.log(self.responsible_weight)*self.reward_holder)
        optimizer = tf.train.GradientDescentOptimizer(learning_rate=lr)
        self.update = optimizer.minimize(self.loss)
    
tf.reset_default_graph() #Clear the Tensorflow graph.

训练

cBandit = contextual_bandit() #Load the bandits.
myAgent = agent(lr=0.001,s_size=cBandit.num_bandits,a_size=cBandit.num_actions) #Load the agent.
weights = tf.trainable_variables()[0] #The weights we will evaluate to look into the network.

total_episodes = 10000 #Set total number of episodes to train agent on.
total_reward = np.zeros([cBandit.num_bandits,cBandit.num_actions]) #Set scoreboard for bandits to 0.
e = 0.1 #Set the chance of taking a random action.

init = tf.initialize_all_variables()

# Launch the tensorflow graph
with tf.Session() as sess:
    sess.run(init)
    i = 0
    while i < total_episodes:
        s = cBandit.getBandit() #Get a state from the environment.
        
        #Choose either a random action or one from our network.
        if np.random.rand(1) < e:
            action = np.random.randint(cBandit.num_actions)
        else:
            action = sess.run(myAgent.chosen_action,feed_dict={myAgent.state_in:[s]})
        
        reward = cBandit.pullArm(action) #Get our reward for taking an action given a bandit.
        
        #Update the network.
        feed_dict={myAgent.reward_holder:[reward],myAgent.action_holder:[action],myAgent.state_in:[s]}
        _,ww = sess.run([myAgent.update,weights], feed_dict=feed_dict)
        
        #Update our running tally of scores.
        total_reward[s,action] += reward
        if i % 500 == 0:
            print "Mean reward for each of the " + str(cBandit.num_bandits) + " bandits: " + str(np.mean(total_reward,axis=1))
        i+=1
for a in range(cBandit.num_bandits):
    print "The agent thinks action " + str(np.argmax(ww[a])+1) + " for bandit " + str(a+1) + " is the most promising...."
    if np.argmax(ww[a]) == np.argmin(cBandit.bandits[a]):
        print "...and it was right!"
    else:
        print "...and it was wrong!"

希望本教程能够有助于你直观的理解强化学习如何解决不同的问题。如果你已经掌握了这个方法,并且已经准备好探索完整的深度强化问题,你可以直接看第二部分或者以后的文章。

如果你觉得这篇文章对你有帮助,可以关注原作者。

如果你想要继续看到我的文章,也可以专注专栏。第一次翻译,希望能和大家一起交流。

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

推荐阅读更多精彩内容