关于多臂强盗演习的违反直觉的结果

时间:2017-01-06 12:01:49

标签: python machine-learning gradient-descent reinforcement-learning

我正在完成Sutton& Sons的第2章第7节。 Barto的强化学习:简介,它涉及多臂强盗问题中的梯度方法。 (我意识到第2版是草稿,似乎这些部分移动了一点,但我的文件有第2.7节标题为" Gradient Bandits"。)我设法使用2.3节中的方法-2.5没有问题,但我一直在使用令人困惑的梯度方法获得结果。我将浏览我的代码并展示一个例子。

只需在此初始化所有内容:

import random
import math
import numpy as np, numpy.random

# number of arms (k) and step-size (alpha)
k = 10
alpha = 0.1

# initialize preference function (H), and reward distribution (R)
H = {i: 0 for i in range(k)}
R = {i: [random.uniform(-100,100), 1] for i in range(k)}

我使用固定奖励分发,而我正在使用词典来表示这些分布。我假设每个奖励都是由高斯描述的,所以我用以下函数将行动映射到奖励:

def getReward(action, rewardDistribution):
  return random.gauss(rewardDistribution[action][0], rewardDistribution[action][1])

所谓的"偏好功能" H,用于确定动作概率,也由字典给出。我在很宽的范围内分散选择,因为每个奖励都是由高斯分布描述的,标准偏差1位于-100到100之间。我这样做是因为我的直觉告诉我它将使它变得更难确定次优选择的算法,但我发现正好相反。

此代码在每次迭代时选择我的操作:

def selectAction(policy):
  return np.random.choice(list(policy.keys()), p=list(policy.values()))

接下来是运行算法迭代的代码。请注意,pi是政策,并已初始化为每个操作提供概率1/k

avgReward = 0
for i in range(100000):
  pi = {i: math.exp(H[i])/sum([math.exp(H[j]) for j in range(k)]) for i in range(k)}
  A = selectAction(pi)
  R_A = getReward(A, R)
  avgReward += (R_A - avgReward)/(i + 1)
  H = {i: H[i] + alpha*(R_A - avgReward)*((i == A) - pi[i]) for i in range(k)}

注意我运行了100,000次迭代,对我来说似乎应该是矫枉过正。这是我第一次尝试这个问题,所以我的直觉可能已经关闭了,但我试图将其设置为使算法更容易找到最佳选择。所以我期望的是收集行动的过程,其中分布具有最高的期望值,并且随着迭代的进行将继续击中它。但是,当我打印出与强盗的每个可能动作相关的结果时,我就是这样:

for i in range(k):
  print("Expected reward: " + str(R[i][0]) + " | Selection probability: " + str(pi[i]) + " | Preference: " + str(H[i]))

Expected reward: -50.62506110888989 | Selection probability: 3.617077909489526e-13 | Preference: -7.82992533515
Expected reward: 11.866419726345484 | Selection probability: 1.2337498052271344e-10 | Preference: -1.99777839484
Expected reward: 75.41139657867947 | Selection probability: 1.5933517476231946e-09 | Preference: 0.560588358966
Expected reward: -72.44467653824414 | Selection probability: 3.4267025247257986e-13 | Preference: -7.88399339198
Expected reward: -43.466561447399 | Selection probability: 1.5933517476231946e-09 | Preference: 0.560588358966
Expected reward: -75.99171566420297 | Selection probability: 1.5933517476231946e-09 | Preference: 0.560588358966
Expected reward: -82.11920932060593 | Selection probability: 3.120658098513757e-13 | Preference: -7.97754791911
Expected reward: 95.00643386364632 | Selection probability: 1.5933517476231946e-09 | Preference: 0.560588358966
Expected reward: 31.384022070017835 | Selection probability: 1.2605442916195123e-08 | Preference: 2.62887724114
Expected reward: 49.83925652065625 | Selection probability: 0.9999999808967586 | Preference: 20.8180143641

最后一个动作的预期奖励为 49.8 ,强盗每次都会选择它。这是10个选项中的第3个选项,但是它忽略了一个期权奖励 75.4 的选项和另一个期望奖励 95.0 的选项。

所以,我的问题是:为什么这个强盗错过了最佳选择?这只是一个例子,当我运行程序时,这是在一个非常一致的基础上发生的。关于匪徒应该做什么,或者我对这个算法编码不正确,我的直觉是否正确?

1 个答案:

答案 0 :(得分:4)

问题在于,许多手臂(或动作;我正在使用手臂,因为这是MAB问题中最常见的术语)在您当前的设置中根本不会播放一次。您可以通过打印每个手臂的频率来轻松验证是否是这种情况。

这是因为您的奖励具有相当高的绝对值。在关于MAB问题的文献中,他们通常在[0,1]或[-1,1]中承担奖励。这不是绝对必要的(尽管它是针对与算法的理论性能相关的一些证据......但是现在可能对你来说并不感兴趣)。无论如何,有几种方法可以解决问题:

1)将首选项列表(H)初始化为较高的值,而不是0s。这与本书前面描述的epsilon - 贪婪的乐观初始化具有类似的效果,因为它促使算法在之前进行更多的探索。

2)大幅降低学习率alpha的值。尝试更像0.00001而不是0.1的内容。这种变化的影响是H中的偏好设置值以较小的速率远离0,因此pi中的概率也会从最初的1/k开始增长降低利率。​​

3)重新调整奖励值,例如,[-1,1](如果你不想要问题,这也需要适当减少奖励分配的标准差。变得更加复杂。