【科普】强化学习之多臂老虎机问题(bandit算法:softmax,random,UCB)

本博客上的文章分为两类:一类是科普性文章,以通俗易懂的语言风格介绍专业性的概念及其应用场景(公式极少或没有),适合入门阶段。另一类是专业性文章,在科普阶段上做出详细的专业性数学推导,深刻理解其概念的内涵,适合进阶。

本篇目录

  1. 什么是强化学习?
  2. 什么是K-摇臂赌博机问题?
  3. 什么是EE困境?
  4. 常见的解决EE困境办法的方法以及它们之间的差异?

1、 什么是强化学习?
近几年来,人工智能与大数据的概念逐渐“深入人心”,相关报道常见于微博、公众号等宣传媒介上,在人工智能这一个大的概念下,有许许多多的“学习”,比如,深度学习,模仿学习,强化学习等。那么有一个问题随之而来,什么是“学习”?百度百科上,对学习的解释为:“通过阅读、听讲、思考、研究、实践等途径获得知识或技能的过程”。上面的解释是基于人类学习来说的。类似的,机器的“学习”(或者说人工智能算法中的“学习”)是指通过大量的数据尝试或训练后,获得了学习算法中合理的参数值(算法中的参数值可以理解为人类的技能或知识),从而尽可能达到算法的目标。
如何理解强化学习的概念?强化学习是一种模拟人类学习知识技能的一种方式,它通过不断地获取周围环境的反馈来达到学习的目的。也就是说,指强化学习算法根据当前环境做出判断,并选择了相应的动作措施,从而带来了环境状态的改变,环境的改变带来了潜在的“奖赏值”,相应地,“奖赏值”反馈给算法,从而达到“学习”的目的,重复以上流程。我推荐西瓜书[1]的定性理解,我们设想这样一个场景:如何在现实世界里种出一个好西瓜?我们知道,从种瓜再到西瓜成熟,需要经历很多阶段和相应措施的联合作用后才能得到最优质的西瓜。我们先假定种瓜的生长过程要经历四个状态{缺水;溢水;健康;凋亡},为了使小西瓜能更好成长,我们能采取的措施包括:施肥,浇水,除草,杀虫等,为了简化处理流程,我们假定采取的措施仅仅包括{浇水;不浇水}。在完成了上述的假定的条件后,我们来模拟一下种植西瓜到最终获得优质西瓜所要经历的过程。
我们可以把强化学习的算法理解成一个“种瓜机器人”,强化学习算法的参数集合理解为种瓜的外部现实环境(也就是上面说的四种状态)。种瓜机器人先把西瓜种子种植到土壤里,根据其西瓜的成长状态来采取相应的措施,即如果缺水,则实施浇水的动作,浇水后,西瓜的成长状态有一定概率地发生转移(比如水过多,西瓜淹死了;水恰好,西瓜健康生长;水少了,西瓜依然缺水),根据原状态改变后的结果给予种瓜机器人某种奖赏(比如原状态为缺水,在种瓜机器人采取动作为浇水后,若状态转移为健康,种瓜机器人获得奖赏+10;若状态转移为溢水,奖赏-10),并将“奖赏值”反馈给“种瓜机器人”进行“反思”。综上所述,可以把种瓜机器人的行为方式流程归纳为:判断当前种瓜环境状态(原假设为4个状态)->采取相应动作(原假设为2个动作)->原状态有概率地发生转移->根据改变后的状态结果获得相应的奖赏值并反馈给“种瓜机器人”进行“反思”(也就是说,算法是通过“奖赏值”进行学习的),如此循环,从而在有限时间内,获得累计奖赏值。
我们了解到,强化学习的目标就是在有限的时间内获得累计奖赏值最大化。由于种瓜的外部环境状态随机,而且状态转移概率也不确定。因而,我们必须对种瓜的策略进行多次试验,才能有可能找到最佳的种瓜策略。策略的意思是在有限时间内,找到合理的种瓜机器人的行为方式。而强化学习的学习过程体现在对过去历史记录(指的是反馈的“奖赏值“)进行有效利用。

2. 什么是K-摇臂赌博机问题?
由上可知,强化学习任务的最终奖赏是在多步动作之后才能观察到。我们考虑一种简单的情形:最大化单步奖赏。也就是说,在当前时刻,我们的目标是在所有能采取的动作集合中,选择一个动作能使我们在此刻瞬时的奖赏值最大。单步强化学习任务对应的理论模型,即“K-摇臂赌博机”(K-armed bandit)。如图所示
在这里插入图片描述
K-摇臂赌博机有K个摇臂,赌徒在投入一个硬币后可随机选择其中一个臂摇下,每个摇臂以一定的概率吐出银币(也就是赌徒的奖赏),但每个臂获得硬币的概率赌徒并不知道。赌徒的目标是通过一定的策略来最大化自己的累计奖赏,即在有限的摇臂次数下,尽可能多的获得银币奖赏。
多臂老虎机问题(multi-armed bandits problems,MAB)也就是说,如何在有限时间内,获得摇臂机的累计奖赏值最大化?

3. 什么是EE困境?
由上面的分析可知,如果想要最大化单步奖赏需要考虑两个方面:一是需要知道动作集合中每个动作所带来的奖赏;二是要执行奖赏最大的那个动作。如果每个动作带来的奖赏值是确定的(以后时间内都不改变其奖赏值!),那么尝试一遍所有动作后就能发现奖赏值最大的那个动作,因此,如果以后一直选择执行该单步奖赏值最大的臂即可获得有限时间内最大的累计奖赏。然而现实是残酷的,一般情况下,每个动作的奖赏值是随机的,也就是说,它每个摇臂以符合某种概率分布的形式存在。因而,如果我们仅仅探索一轮(指遍历一次所有动作),我们无法获得真实的最大臂期望奖赏值。
什么是EE困境(Exploration-Exploitation dilemma)?仅探索(Exploration)指依次摇下每个臂,从而获得每个臂的奖赏值,这种方式能够很好估计每个臂的奖赏值,缺失去很多选择最优臂的机会。仅利用(Exploitation)指一直选择当前已知奖赏值最大的那个臂,这个方式不能很好估计每个臂的奖赏值,可能无法选择最优的臂。因此这两种方式都是不能获得累计奖赏最大值,也就是我们常说的EE困境。

4. 常见的解决EE困境办法的方法以及它们之间的差异?
由EE困境可知,“探索”(即估计每个臂的优劣)和“利用”(即选择当前最优的臂)这两者是矛盾的。这是因为总的尝试次数有限,加强一方势必会削弱另一方。因而我们必须在这两者之间进行有效折中,才可以尽可能获得最大累计奖赏。
(1)e-贪心
e-贪心法基于一个概率来对探索和利用进行折中。每次尝试时,以e概率来进行探索,即以均匀概率随机选取一个摇臂;以1-e的概率进行利用,即选择当前平均奖赏最高的摇臂。
(2)Softmax
Softmax算法是基于当前已知的平均奖赏概率来对探索和利用进行折中。也就是说,以每个臂的初始奖赏值的大小作为摇臂的策略,即奖赏值越高的臂,被选择摇下的概率就越高。
(3)UCB(Upper Confidence bound-置信上限)
在这里插入图片描述
上面是常规的UCB公式,x_j代表臂j估计的期望值,n代表当前为止,试验已经尝试的次数;n_j代表臂j被摇下的次数。
公式分为两个部分,左边部分代表现在臂j估计值,而右边可以理解为臂j的标准差。右边那个部分可以视为探索与利用的折中。因为当臂j探索次数很小时,n_j很小,那么右边式子很大,整个式子的值就很大,臂j被选中的概率很高,这是属于臂j的探索部分。当每个臂进行足够多的探索后,n_j的值较大了,右边的式子影响就降低,那么整个式子的值主要由左边的估计值决定,也就是说,估计值越大,臂j被选中的概率越高,这是属于臂j的利用部分。当尝试次数足够多的时候,估计值影响越大,越靠近真实臂的期望值。

后记
这是我第一次写强化学习的内容,可能存在某些概念理解不深刻,没有尽量用通俗易懂的语言讲解清楚,后续我会逐步改进行文思路(也会随时修改编辑文章),也希望读者能关注我的博客,有好的建议,我也会采纳。让我们一起学习!

参考资料
【1】 西瓜书,周志华

  • 13
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
以下是Python代码实现: 1. Softmax算法: ```python import numpy as np def softmax_action_selection(q_values, tau=1.0): """ Softmax action selection algorithm for multi-armed bandit problem. :param q_values: numpy array of shape (num_actions,) representing the estimated action values :param tau: float temperature parameter controlling the degree of exploration :return: selected action """ probabilities = np.exp(q_values / tau) / np.sum(np.exp(q_values / tau)) action = np.random.choice(len(q_values), p=probabilities) return action ``` 2. Epsilon-Greedy算法: ```python import numpy as np def epsilon_greedy_action_selection(q_values, epsilon=0.1): """ Epsilon-greedy action selection algorithm for multi-armed bandit problem. :param q_values: numpy array of shape (num_actions,) representing the estimated action values :param epsilon: float parameter controlling the degree of exploration :return: selected action """ if np.random.rand() < epsilon: action = np.random.choice(len(q_values)) else: action = np.argmax(q_values) return action ``` 3. BetaThompson sampling算法: ```python import numpy as np class BetaThompsonSampling: def __init__(self, num_actions): """ Beta Thompson sampling algorithm for multi-armed bandit problem. :param num_actions: number of actions (arms) """ self.alpha = np.ones(num_actions) self.beta = np.ones(num_actions) def action_selection(self): """ Select action according to the Beta distribution of each arm. :return: selected action """ samples = np.random.beta(self.alpha, self.beta) action = np.argmax(samples) return action def update(self, action, reward): """ Update the Beta distribution of the selected arm. :param action: selected action :param reward: observed reward """ if reward == 1: self.alpha[action] += 1 else: self.beta[action] += 1 ``` 4. UCB算法: ```python import numpy as np class UCB: def __init__(self, num_actions, c=1.0): """ Upper Confidence Bound (UCB) algorithm for multi-armed bandit problem. :param num_actions: number of actions (arms) :param c: exploration parameter """ self.num_actions = num_actions self.c = c self.N = np.zeros(num_actions) self.Q = np.zeros(num_actions) def action_selection(self): """ Select action according to the UCB upper confidence bound. :return: selected action """ upper_bounds = self.Q + self.c * np.sqrt(np.log(np.sum(self.N)) / (self.N + 1e-8)) action = np.argmax(upper_bounds) return action def update(self, action, reward): """ Update the estimated action value of the selected arm. :param action: selected action :param reward: observed reward """ self.N[action] += 1 self.Q[action] += (reward - self.Q[action]) / self.N[action] ``` 5. LinUCB算法: ```python import numpy as np class LinUCB: def __init__(self, num_actions, num_features, alpha=0.1): """ Linear Upper Confidence Bound (LinUCB) algorithm for multi-armed bandit problem. :param num_actions: number of actions (arms) :param num_features: number of features :param alpha: exploration parameter """ self.num_actions = num_actions self.num_features = num_features self.alpha = alpha self.A = np.array([np.eye(num_features) for _ in range(num_actions)]) self.b = np.zeros((num_actions, num_features)) self.theta = np.zeros((num_actions, num_features)) def action_selection(self, features): """ Select action according to the LinUCB upper confidence bound. :param features: numpy array of shape (num_features,) representing the features of the context :return: selected action """ upper_bounds = np.zeros(self.num_actions) for i in range(self.num_actions): A_inv = np.linalg.inv(self.A[i]) self.theta[i] = np.dot(A_inv, self.b[i]) upper_bounds[i] = np.dot(self.theta[i], features) + \ self.alpha * np.sqrt(np.dot(features.T, np.dot(A_inv, features))) action = np.argmax(upper_bounds) return action def update(self, action, features, reward): """ Update the estimated parameters of the selected arm. :param action: selected action :param features: numpy array of shape (num_features,) representing the features of the context :param reward: observed reward """ self.A[action] += np.outer(features, features) self.b[action] += reward * features ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值