强化学习是一种试错性学习,所以对于已有信息的利用和未知信息的探索之间的平衡一直是强化学习中一个重要的话题。
多臂老虎机(MAB)问题定义为:我们拥有K个拉杆的老虎机,每一根拉杆对应着不同的奖励分布,对于智能体来说是未知的。每次拉动拉杆会获得服从奖励分布的奖励,我们想要获得累计最多的奖励,但是奖励的分布未知,所以就要在已有信息的利用--根据经验选择获得奖励最多的拉杆和未知信息的探索--尝试更多非最优,探索拉杆的获奖概率之间进行平衡,以获得最多奖励
对于多臂老虎机问题,我们定义他的动作集(1:k)(k为总摇杆个数),奖励设置为0/1(按照概率分布随机给予奖励)代码如下:
class BernoulliBandit:
def __init__(self, K):
self.probs = np.random.uniform(size = K)
self.best_idx = np.argmax(self.probs)
self.best_prob = self.probs[self.best_idx]
self.K = K
def step(self, K):
if np.random.rand() < self.probs[K]:
return 1
else:
return 0
现在的问题是:如何在尽可能短的时间内实现收益的最大化。
关于收益,我们定义了REGRET,表示当前的总奖励与理想最大值之间的累计差距(理想最大值是摇杆玩家未知的)下面我们研究问题的解决。
摇杆问题中,环境的探索:通过尝试不同摇杆以获得每个摇杆的奖励情况;信息的利用:根据探索得到的摇杆奖励,选择预期收益最高的摇杆。为了在固定次数内获得较高奖励,探索过程不宜过长,因为探索的奖励较低,但是信息的利用又需要可靠的探索支撑,EpsilonGreedy算法解决了二者之间的均衡。
再进行操作时,我们会维护一个list,其中表示着不同摇杆的期望奖励,我们根据公式来更新其中的值。我们也可以通过增量形式更新,r为即时奖励,N为共拉动这一根摇杆的次数。
epsilon贪婪算法是指在进行动作的选择时,有的几率按照list中价值期望最高的动作执行,有较小的的几率随机进行动作的选择,这保证了我们大部分时间都在利用已有信息,仍有机会对未知环境进行探索。
下面代码表示这解决多臂摇杆问题的一个通用的解决框架,它定义了存储的数据结构与计数等流程,我们需要对其中的策略进行重写。
class Solver:
def __init__(self, bandit):
self.bandit = bandit
self.counts = np.zeros(self.bandit.K) #生成空列表储存每个拉杆拉几次
self.regret = 0
self.actions = []
self.regrets = []
def update_regret(self, k):
self.regret += self.bandit.best_prob - self.bandit.probs[k]
self.regrets.append(self.regret)
def run_one_step(self):
raise NotImplementedError
def run(self, num_steps):
for _ in range(num_steps):
k = self.run_one_step()
self.counts[k] += 1
self.actions.append(k)
self.update_regret(k)
class EpsilonGreedy(Solver):
def __init__(self, bandit, epsilon = 0.01, init_prob = 1.0):
super(EpsilonGreedy, self).__init__(bandit)
self.epsilon = epsilon
self.estimates = np.array([init_prob] * self.bandit.K)#估值
def run_one_step(self):
if np.random.random() < self.epsilon:
k = np.random.randint(0, self.bandit.K)#随机选择
else:
k = np.argmax(self.estimates)
r = self.bandit.step(k)
self.estimates[k] += 1. / (self.counts[k] + 1) *
(r - self.estimates[k])#增量形式更新估计值
return k
但是,我们发现,刚开始的时候,算法探索缓慢,而且完全探索之后regret仍然较快上升。该算法有很多点可以提升
首先,当我们开始的时候,探索不完全,所以已有的信息参考价值差,所以不应该以同等概率与之后更可信的信息一起被利用,在完全全探索了环境之后可以减少探索,所以我们设计了一个衰减的epsilon,他刚开始时候很大,对环境的探索效率也很高。
class DecayEpsilonGreedy2(Solver):
def __init__(self, bandit, init_prob = 1.0):
super(DecayEpsilonGreedy2, self).__init__(bandit)
self.estimates = np.array([init_prob] * self.bandit.K)#估值
self.total_count = 0
def run_one_step(self):
self.total_count += 1
if np.random.random() < 1 / self.total_count:
k = np.random.randint(0, self.bandit.K)#随机选择
else:
k = np.argmax(self.estimates)
r = self.bandit.step(k)
self.estimates[k] += 1. / (self.counts[k] + 1) * (r - self.estimates[k])#增量形式更新估计值
return k
对比可见,累计懊悔(regret)明显减少,且收敛加快
三.上置信界算法(占坑,先出去玩,明天来填坑)
四.汤姆森采样法(同上)