假设有一个老虎机有 n n 个握把,每个握把 i i 有 Pi P i 的概率可以中奖,每次可以选择一个握把进行尝试,老虎机只会返回是否中奖。尝试者不知道中奖概率,需要通过有策略的尝试,选出中奖概率最高的那一个握把。
共有 n n 个arm,每个arm的成功概率为 Pi P i 玩家可以对每个arm进行尝试,每次尝试后,若成功则得到1,若失败则得到0。玩家不知道每个arm的概率,需要调整尝试策略(policy),最终找到成功概率最大的arm
采用最简单的 ϵ−greedy ϵ − g r e e d y 策略,通过尝试调整每一个arm对应的估计成功概率(value)。即有两种操作,explore与exploit,exploit选择当前value最大的arm尝试,explore随机选择一个arm尝试。在每次尝试完成后,均根据中奖结果更新对应arm的value。更新value的策略如下:
其中,a表示尝试(action), Qk(a) Q k ( a ) 表示尝试的估计成功率(value),k表示该尝试被试过的次数, Rk(a) R k ( a ) 表示该次尝试的结果(reward)。
经过许多次尝试后,即可得到预期的结果,对应部分的代码如下
while i <= self.training_epochs:
if random.uniform(0, 1) < self.explore_rate:
index, reward = self.explore()
else:
index, reward = self.exploit()
self.times[index] += 1
self.values[index] += 1.0 / (self.times[index]+1) * (reward - self.values[index])
i += 1
import numpy as np
import random
class Bandit:
def __init__(self, arms_prob):
self.arms_prob = arms_prob
self.size = len(self.arms_prob)
def play(self, i):
if not 0 <= i < self.size:
return -1
else:
if random.uniform(0, 1) < self.arms_prob[i]:
return 1
else:
return 0
class Model:
def __init__(self, bandit, explore_rate=0.2, training_epochs=10000):
self.bandit = bandit
self.explore_rate = explore_rate
self.training_epochs = training_epochs
self.values = np.zeros(bandit.size)
self.times = np.zeros(bandit.size)
self.size = bandit.size
self.result = 0
def explore(self):
index = random.randint(0, self.size - 1)
return index, self.bandit.play(index)
def exploit(self):
index = self.values.argmax(axis=0)
return index, self.bandit.play(index)
def train(self):
i = 1
while i <= self.training_epochs:
if random.uniform(0, 1) < self.explore_rate:
index, reward = self.explore()
else:
index, reward = self.exploit()
assert reward >= 0 and index >= 0
self.times[index] += 1
self.values[index] += 1.0 / (self.times[index]+1) * (reward - self.values[index])
i += 1
print("Round %d, choose %d, reward %d " % (i, index, reward))
print(repr(self.values))
self.result = self.values.argmax(axis=0)
bandit = Bandit([0.5, 0.6, 0.8, 0.9, 0.3, 0.95, 0.96, 0.45, 0.93, 0.22, 0.65])
model = Model(bandit, explore_rate=0.15, training_epochs=30000)
model.train()
print("Best choice is %d." % model.result)
原先设置的各个握把的成功率为:
[0.5, 0.6, 0.8, 0.9, 0.3, 0.95, 0.96, 0.45 0.93, 0.22, 0.65]
设置explore_rate(explore的概率)为0.15,进行30000次尝试后,得到的各个握把估计成功率为:
[0.511, 0.577, 0.807, 0.888, 0.282, 0.949, 0.959, 0.510, 0.945, 0.238, 0.625]
可以观察到,已经与估计值的差距已经比较接近,最终选择的最大值均为第7个握把(实际概率0.96,估计概率0.959),训练结果较为理想。