K-Arms Bandit Epsilon-贪心策略

K-Arms Bandit Epsilon-Greedy Policy

我一直在尝试实现强化学习书籍练习 2.5

这段代码我是按照这个伪版本写的

class k_arm:
    def __init__(self, iter, method="incrementally"):

        # self.iter placeholder
        self.iter = iter
        self.k = 10
        self.eps = .1
        
        # here is Q(a) and N(a)
        self.qStar = np.zeros(self.k)
        self.n = np.zeros(self.k)
        
        # Method just for experimenting different functions
        self.method = method
        
    def pull(self):
        
        # selecting argmax(Q(A)) action with prob. (1 - eps)
        eps = np.random.uniform(0, 1, 1)
        if eps < self.eps or self.qStar.argmax() == 0:
            a = np.random.randint(10)
        else: a = self.qStar.argmax()
        
        # R bandit(A)
        r = np.random.normal(0, 0.01, 1)
        
        # N(A) <- N(A) + 1
        self.n[a] += 1
        
        # Q(A) <- Q(A) i / (N(A)) * (R - Q(A))
        if self.method == "incrementally":
            self.qStar[a] +=  (r - self.qStar[a]) / self.n[a] 
            return self.qStar[a]`

iter = 1000
rewards = np.zeros(iter)
c = k_arm(iter, method="incrementally")

for i in range(iter):    
    k = c.pull()
    rewards[i] = k

结果我得到了这个

我期待这种结果的地方。

我一直想弄清楚我到底在哪里失踪了,但我想不通。

您的平均奖励约为 0,因为这是正确的估计。您的奖励函数定义为:

 # R bandit(A)
 r = np.random.normal(0, 0.01, 1)

这意味着您的奖励分配的预期值为 0,方差为 0.01。在书中,作者使用了不同的奖励函数。虽然此仍然存在根本问题,但如果您将代码更改为

,您可以获得类似的奖励
 # R bandit(A)
 r = np.random.normal(1.25, 0.01, 1)

给每个强盗一个不同的奖励函数你所有的行动值都将是相同的是有意义的。所以你真正应该做的是从 k 具有不同期望值的不同分布中采样。否则动作选择是没有意义的。 将此添加到您的 init 函数中:

self.expected_vals = np.random.uniform(0, 2, self.k)

并更改奖励的计算方式,使其取决于操作:

r = np.random.uniform(self.expected_vals[a], 0.5, 1)

我还将方差增加到 0.5,因为 0.01 在强盗的背景下基本上是无意义的方差。如果你的代理工作正常,他的平均奖励应该大约等于 np.max(self.expected_vals)