Multi-Armed Bandit: UCB (Upper Bound Confidence)
转自:https://zhuanlan.zhihu.com/p/32356077
假设我们开了一家叫Surprise Me的饭馆
- 客人来了不用点餐,由算法从N道菜中选择一道菜推荐给客人
- 每道菜都有一定的失败概率:以1-p的概率不好吃,以p的概率做得好吃
- 算法的目标是让满意的客人越多越好
解决方法:
算法:
- 以
的概率从N道菜中随机选择(概率为
)一个让客人试吃
- 以
的概率选择N道菜中选择好吃的概率最高的菜推荐给客
充分利用历史信息进行选择
生硬的将选择过程分成探索阶段 (Exploration) 和 利用阶段(Exploitation),在探索时对所有物品进行以同样的概率 (概率为
) 进行探索,并不会利用任何历史信息,包括
(1)某道菜被探索的次数,
(2)某道菜获得好吃反馈的比例。
让我们忘记探索阶段和利用阶段,仔细想想如何充分利用历史信息,找到最值得被推荐的菜:
观测 1: 如果一道菜已经推荐了k遍(获取了k次反馈),我们就可以算出菜做的好吃的概率:
当k趋近正无穷时, 会趋近于真实的菜做的好吃的概率
观测 2: 现实当中一道菜被试吃的次数k不可能无穷大,因此估计出的好吃的概率 和真实的好吃的概率
总会存在一个差值
,即
基于上面两个观测,我们可以定义一个新的策略:每次推荐时,总是乐观地认为每道菜能够获得的回报是 ,这便是著名的Upper Confidence Bound (UCB) 算法,代码如下所示。
def UCB(t, N):
upper_bound_probs = [avg_rewards[item] + calculate_delta(t, item) for item in range(N)]
item = np.argmax(upper_bound_probs)
reward = np.random.binomial(n=1, p=true_rewards[item])
return item, reward
for t in range(1, T): # T个客人依次进入餐馆
# 从N道菜中推荐一个,reward = 1 表示客人接受,reward = 0 表示客人拒绝并离开
item, reward = UCB(t, N)
total_reward += reward # 一共有多少客人接受了推荐
真实的概率和估计的概率之间的差值
最后只需解决一个问题,真实的概率和估计的概率之间的差值 到底怎么计算呢?
在进入公式之前,让我们直观的理解影响 的因素:
- 对于被选中的菜,多获得一次反馈会使
变小,最终会小于其他没有被选中的菜
- 对于没被选中的菜,
会随着轮数的增大而增大,最终会大于其他被选中的菜
下面我们正式介绍如何计算 ,首先介绍Chernoff-Hoeffding Bound:
[Chernoff-Hoeffding Bound] 假设 是在[0, 1]之间取值的独立同分布
随机变量,用 表示样本均值,用
表示分布的均值,那么有
当 取值为
时 (其中T表示有T个客人,n表示菜被吃过的次数),可以得到
也就是说 是以
的概率成立的:
- 当T=2时,成立的概率为0.875
- 当T=3时,成立的概率为0.975
- 当T=4时,成立的概率为0.992
可以看出 是一个不错的选择。
最后,我们附上完整的代码,跟第一讲不一样的地方已经重点加粗标注。
import numpy as np T = 1000 # T个客人 N = 10 # N道菜 true_rewards = np.random.uniform(low=0, high=1, size=N) # 每道菜好吃的概率 estimated_rewards = np.zeros(N) # 每道菜好吃的估计概率 chosen_count = np.zeros(N) #各个菜被选中的次数 total_reward = 0 def calculate_delta(T, item): if chosen_count[item] == 0: return 1 else: return np.sqrt(2 * np.log(T) / chosen_count[item]) def UCB(t, N): upper_bound_probs = [estimated_rewards[item] + calculate_delta(t, item) for item in range(N)] item = np.argmax(upper_bound_probs) reward = np.random.binomial(n=1, p=true_rewards[item]) return item, reward for t in range(1, T): # T个客人依次进入餐馆 # 从N道菜中推荐一个,reward = 1 表示客人接受,reward = 0 表示客人拒绝并离开 item, reward = UCB(t, N) total_reward += reward # 一共有多少客人接受了推荐 # 更新菜的平均成功概率 estimated_rewards[item] = ((t - 1) * estimated_rewards[item] + reward) / t chosen_count[item] += 1

浙公网安备 33010602011771号