衡水网站建设集团,网站服务类型怎么选,本地php网站搭建环境,手机企业网站程序1.1 多臂赌博机 一台拥有K个臂的机器#xff0c;玩家每次可以摇动K个臂中的一个#xff0c;摇动后#xff0c;会吐出数量不等的金币#xff0c;吐出金币的数量服从一定的概率分布#xff0c;而且不同臂的概率分布不同。 多臂赌博机的问题是#xff1a;假设玩家共有N次摇地…1.1 多臂赌博机 一台拥有K个臂的机器玩家每次可以摇动K个臂中的一个摇动后会吐出数量不等的金币吐出金币的数量服从一定的概率分布而且不同臂的概率分布不同。 多臂赌博机的问题是假设玩家共有N次摇地摇臂的机会每次如何选择摇动才能使N轮之后得到的金币最多 对于这个问题如果提前知道哪个臂吐的金币最多那么可以每次都摇动那个臂。但是问题使并不知道那个臂能获得最多金币该采取什么策略 1.1.1 -greedy策略 一个很直观的想法既然不知道哪个臂吐的金币最多那么可以先对每个臂都尝试几次如都10次找出那个臂吐出的金币最多然后一直摇动它。 其实这个最简单、最朴素的想法已经蕴含了算法学习最基本的两个过程采集数据和学习。首先对每个臂进行尝试就是采集数据其次学习就是利用这些数据知道哪个臂回吐出最多的金币。一个最简单的方法就是计算每个臂的平均吐钱数量然后一直摇那个臂。 我们可以将这个算法用形式化的代数来表示。用s表示当前赌博机用A表示可以选择的动作即A{123}。其中a1表示摇动第一个臂依次类推。用回报表示摇动赌博机的摇臂后获得的金币的数目。用Qa表示摇动动作a获得的金币的平均回报则,其中n为摇动动作的总次数。Ra为摇动动作a的总回报。 算法的伪代码 1-3行初始化每个动作的总回报Ra以及摇动该动作的次数Na。
4-6行每个臂都尝试次计算每个摇臂总的金币数。
7-9行算出使得总回报最大的那个臂然后一直摇动它。
这是一个简单、朴素的想法但并不是一个好的算法。原因如下缺点 1不应该以总回报最大为目的来选择当前哪个臂而是应该选择当前平均回报最大的臂。
2不应该只摇动当前平均回报最大的臂因为它不一定使最好的那个臂。所以我们除了关注当前平均回报最大的臂还要保留一定的概率去摇动其他的臂以便发现更好的臂。
以上两点对应着强化学习算法中最重要的概念利用策略和探索策略平衡。
利用exploitation,是利用当前的数据总结得到的最好的策略采用该策略我们可以得到较高的回报。
探索exploration该策略可以帮我们找到更好的臂甚至找到最优的臂。 强化学习算法在训练的过程中所用到的策略是平衡了利用和探索的策略最常见的是-greedy策略公式表示 该策略在每次选择摇动哪个臂时应该以1-的概率去摇动当前平均值最大的臂以的概率在所有动作中均匀随机地选择动作。这样可以在有限的次数中得到尽可能多的回报同时不失去找到最好的臂的机会。 第1-4行初始化总回报R(a)初始化每个动作的平均回报Qa,每个动作的次数Na.
第6行在每次摇臂之前采用-greedy策略选择要摇动的臂a。
第7行动作a的次数N(a)1.
第8行根据动作a和环境返回的回报(a),更新动作a的平均回报。
第9行计算总的收益。
第10行玩家尝试N次之后返回总的收益。
在多臂赌博机中平衡利用和探索的策略还有玻尔兹曼策略和UCB策略。 1.1.2 玻尔兹曼策略 e-greedy策略给对应值函数最大的那个动作一个比较大的概率而其他动作不管值函数的大小如何被采样的概率都是相等。 但这中概率的分配策略不太合理。按理说非贪婪的动作也有好坏之分那些对应值函数大的动作应该比那些对应值函数小的动作采样的概率大。于是玻尔兹曼策略根据值函数对动作的采样的概率进行了软处理表示下式1-2为 其中为温度调节参数可以用来调节探索和利用和比例。越小玻尔兹曼越接近贪婪策略利用所占的比例越大探索越少。反之探索越多。伪代码只需替换图1-3中的e-greedy策略为公式1-2. 1.1.3 UCB策略
UCBUpper Confidence Boundn置信上限。在统计学中常常用置信区间来表示不确定性。在这里我们用置信区间来表示探索。
UCB策略公式 其中t为当前摇臂动作的总次数Na为动作a的总次数。
下图为3种策略总回报和摇动次数之后的关系。e-greedy策略回报最低但却是形式最简单、最通用可广泛用于各种任务的学习和探索训练中。 1.2 多臂赌博机代码实现
基于上文提到的三种学习策略。
①首先我们先创建一个KB_Game类
②在类KB_Game中定义方法step用于模拟多臂赌博机如何给出回报。该方法的输入为动作输出为回报。用正态分布来模拟玩家在每次摇动摇臂后得到的回报。step方法实际上提供了多臂赌博机的模拟器。
③接下来实现3种选择动作的策略方法choose_action().该方法的输入参数为测量类别policy有3种对应上文的三种策略e_greedy,ucb和boltzmann.另外还有一个参数字典**kwargs,对应传递相应的策略的所对应超参数如e-greedy策略中的epsilonUCB策略中的超参数c_ratio,以及玻尔兹曼中的温度‘temperature.UCB算法的每一步是依次摇动每个臂因此在程序中对应的代码为判断每个动作的次数如果有等于零的那么选择该动作。
④有了模拟器和动作选择策略下面就可以通过交互进行学习训练。定义方法train().该方法的输入参数有play_total表示训练的总次数,policy训练的策略,**kwargs相应策略的超参数字典.
⑤智能体通过学习的策略选择动作然后将动作传给step()方法相当于跟多臂赌博机进行了一次交互从多臂赌博机中获得回报r,智能体根据立即回报更新每个动作的平均回报q,计算当前的累计回报并作相应的保存。
⑥在每次训练新的策略的时候我们需要将类KB_Game中的成员变量进行重置定义reset方法进行重置重置的变量有平均回报q,各动作的次数action_counts,当前的累积回报current_cumulative_reward,玩家尝试的次数counts,玩家尝试的历史counts_history、玩家累积回报的历史cumulative_rewards_history、动作a、回报reward。 ⑦为了更直观比较3种不同策略的学习性能需要画图展示我们用方法plot()来实现。得到如下的结果。显然ucb比其他两个策略要好。 代码如下
import numpy as np
import matplotlib.pyplot as plt
class KB_Game:def __init__(self,*args,**kwargs):self.qnp.array([0.0,0.0,0.0]) #每个臂的平均回报self.action_countsnp.array([0,0,0]) #摇动每个臂的次数self.current_cumulative_rewards0.0 #当前累积回报总和self.actions[1,2,3] #3个不同的摇臂self.counts0 #玩家玩游戏的次数self.counts_history[] #玩家而玩游戏的次数记录self.cumulative_rewards_history[] #累积回报的记录self.a1 #玩家当前动作初始化为1摇第一个摇臂self.reward0 #当前回报初始值为0def step(self,a):#模拟器r0if a1:rnp.random.normal(1,1) #正态分布均值为1方差为1if a2:rnp.random.normal(2,1)if a3:rnp.random.normal(1.5,1)return rdef choose_action(self,policy,**kwargs): #动作策略action0if policye_greedy:if np.random.random()kwargs[epsilon]:actionnp.random.randint(1,4)else:actionnp.argmax(self.q)1if policyucb:c_ratiokwargs[c_ratio]if 0 in self.action_counts:actionnp.where(self.action_counts0)[0][0]1else:valueself.qc_ratio*np.sqrt(np.log(self.counts)/self.action_counts)actionnp.argmax(value)1if policyboltzmann:taukwargs[temperature]pnp.exp(self.q/tau)/(np.sum(np.exp(self.q/tau)))actionnp.random.choice([1,2,3],pp.ravel())return actiondef train(self,play_total,policy,**kwargs):reward_1[]reward_2[]reward_3[]for i in range(play_total):action0if policye_greedy:actionself.choose_action(policy,epsilonkwargs[epsilon])if policyucb:actionself.choose_action(policy,c_ratiokwargs[c_ratio])if policyboltzmann:actionself.choose_action(policy,temperaturekwargs[temperature])self.aaction#print(self.a)#与环境交互一次self.rself.step(self.a)self.counts1#更新值函数self.q[self.a-1](self.q[self.a-1]*self.action_counts[self.a-1]self.r)/(self.action_counts[self.a-1]1)self.action_counts[self.a-1]1reward_1.append([self.q[0]])reward_2.append([self.q[1]])reward_3.append([self.q[2]])self.current_cumulative_rewardsself.rself.cumulative_rewards_history.append(self.current_cumulative_rewards)self.counts_history.append(i)def reset(self):self.qnp.array([0.0,0.0,0.0]) #每个臂的平均回报self.action_countsnp.array([0,0,0]) #摇动每个臂的次数self.current_cumulative_rewards0.0 #当前累积回报总和self.counts0 #玩家玩游戏的次数self.counts_history[] #玩家而玩游戏的次数记录self.cumulative_rewards_history[] #累积回报的记录self.a1 #玩家当前动作初始化为1摇第一个摇臂self.reward0 #当前回报初始值为0def plot(self,colors,policy,style):plt.figure(1) #创建画布plt.plot(self.counts_history,self.cumulative_rewards_history,colors,labelpolicy)plt.legend() #加上图列plt.xlabel(n,fontsize18)plt.ylabel(total rewards,fontsize18)if __name____main__:np.random.seed(0)k_gambleKB_Game()total2000k_gamble.train(play_totaltotal,policye_greedy,epsilon0.05)k_gamble.plot(colorsr,policye_greedy,style-.)k_gamble.reset()k_gamble.train(play_totaltotal,policyboltzmann,temperature1)k_gamble.plot(colorsb,policyboltzmann,style--)k_gamble.reset()k_gamble.train(play_totaltotal,policyucb,c_ratio0.5)k_gamble.plot(colorsg,policyucb,style-)plt.show()