Python 中的多臂老虎机问题

n 臂强盗问题是一个强化学习问题,其中给代理一个有 n 个强盗/臂的老虎机。老虎机的每个臂都有不同的获胜机会。拉动任何手臂都会奖励或惩罚智能体,即成功或失败。

代理的目标是一次拉一个强盗/武器,以使操作后收到的总奖励最大化。此外,问题描述指出特工不知道武器成功的可能性。它最终通过反复试验以及价值评估来学习。

本教程将教我们如何利用策略梯度方法,该方法使用 TensorFlow 构建一个基本神经网络,该网络由与每个可用臂获得老虎机奖金的可能性成比例的权重组成。在此策略中,智能体基于 e-greedy 方法选择机器臂。

这意味着智能体通常会选择期望值最高的动作,但它也会随机选择。

通过这种方式,间谍测试了几把枪中的每一把,以更多地了解它们。当智能体采取行动时,例如选择老虎机的一个臂,它会得到 1 或 -1 的奖励。


用 Python 实现强盗问题

下面是用Python编写的n-arm/multi-arm bandit问题的简单实现:

对于我们的代码实现,我们选择 n=6(老虎机的 6 个臂),它们的编号为 [2,0,0.2,-2,-1,0.8]。

我们将逐渐发现代理学习并有效地选择具有最高收益的强盗。


第 1 步:导入模块

该方法tf.disable_v2_behavior(顾名思义)会禁用TensorFlow 1.x 和 2.x 之间更改的任何全局行为,并使它们按照 1.x 的预期运行。

1
2
3
import numpy as np
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()

第 2 步:计算武器奖励

我们在槽臂数组中指定我们的强盗。数组的长度存储在 中len_slot_arms该方法发现reward() 根据正态分布创建一个均值为 0 的随机整数。

手臂/强盗数量越低,代理返回正奖励的可能性就越大 (1)。

1
2
3
4
5
6
7
8
9
10
slot_arms = [2,0,0.2,-2,-1,0.8]
len_slot_arms = len(slot_arms)
def findReward(arm):
    result = np.random.randn(1)
    if result > arm:
        #returns a positive reward
        return 1
    else:
        #returns a negative reward
        return -1

第 3 步:设置神经代理

TensorFlow 库的方法tf.rese_default_graph清除默认图堆栈并重置全局默认图。第 2 行和第 3 行将特定老虎机的权重设置为 1,然后进行实际的臂选择。

1
2
3
tf.reset_default_graph()
weights = tf.Variable(tf.ones([len_slot_arms]))
chosen_action = tf.argmax(weights,0)

训练由下面的代码处理。它最初向网络提供奖励和指定的动作(arm)。然后神经网络使用如下所示的算法计算损失。然后利用这种损失通过更新网络来提高网络性能。

1
2
3
4
5
6
7
8
reward_holder = tf.placeholder(shape=[1],dtype=tf.float32)
action_holder = tf.placeholder(shape=[1],dtype=tf.int32)
responsible_weight = tf.slice(weights,action_holder,[1])
loss = -(tf.log(responsible_weight)*reward_holder)
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001)
update = optimizer.minimize(loss)
 
Loss = -log(weight for action)*A(Advantage from baseline(here it is 0)).

第 4 步:训练 Agent 并找到最佳的手臂/强盗

我们通过进行随机活动并获得激励来训练代理。上面的代码启动一个 TensorFlow 网络,然后选择一个随机动作,并从其中一个臂中选择一个奖励。这种激励有助于网络更新,并且也会显示在屏幕上。

total_episodes = 1000
total_reward = np.zeros(len_slot_arms) #output reward array
e = 0.1 #chance of taking a random action.
init = tf.initialize_all_variables()
with tf.Session() as sess:
  sess.run(init)
  i = 0
 
  while i < total_episodes:
    if np.random.rand(1) < e:
      action = np.random.randint(len_slot_arms)
    else:
      action = sess.run(chosen_action)
    reward = findReward(slot_arms[action])
    _,resp,ww = sess.run([update,responsible_weight,weights], feed_dict={reward_holder:[reward],action_holder:[action]})
    total_reward[action] += reward
    if i % 50 == 0:
      print ("Running reward for the n=6 arms of slot machine: " + str(total_reward))
    i+=1
 
print ("The agent thinks bandit " + str(np.argmax(ww)+1) + " has highest probability of giving poistive reward")
if np.argmax(ww) == np.argmax(-np.array(slot_arms)):
  print("which is right.")
else:
  print("which is wrong.")

结论

恭喜!您刚刚学习了如何使用 Python 编程语言解决多臂老虎机问题。我希望你喜欢它!😇

喜欢该教程吗?无论如何,我建议您查看下面提到的教程:

  1. FizzBu​​zz 问题 – 在 Python 中实现 FizzBu​​zz 算法
  2. 用 Python 解决梯子问题
  3. 使用递归解决 Python 中的 0-1 背包问题
  4. 解决 Python 中的平铺问题

感谢您抽出宝贵时间!希望你学到新东西!😄