多臂老虎机

Python 中的 Gymnasium 强化学习

Fouad Trad

Machine Learning Engineer

多臂老虎机

 

  • 赌徒面对多台老虎机
  • 目标 → 最大化胜率
  • 解法 → 探索-利用权衡

图片:一名男子面对一排老虎机

Python 中的 Gymnasium 强化学习

老虎机

图片:4 台老虎机的真实胜率不同:45%、35%、85%、62%,用户未知。

  • 每次拉杆回报为 0 或 1
  • 目标 → 累积最大奖励
Python 中的 Gymnasium 强化学习

解决思路

 

  • 衰减的 ε-贪婪
  • ε → 随机选机器

图示:以概率 ε,智能体随机探索选择机器。

Python 中的 Gymnasium 强化学习

解决思路

 

  • 衰减的 ε-贪婪
  • ε → 随机选机器
  • 1 - ε → 选择当前最优
  • ε 随时间递减

图示:以概率 ε 随机探索;以 1-ε 的概率利用,选择当前最优机器。

Python 中的 Gymnasium 强化学习

初始化

n_bandits = 4  
true_bandit_probs = np.random.rand(n_bandits)

n_iterations = 100000 epsilon = 1.0 min_epsilon = 0.01 epsilon_decay = 0.999
counts = np.zeros(n_bandits) # 每个拉杆被选择的次数
values = np.zeros(n_bandits) # 每个拉杆的估计胜率
rewards = np.zeros(n_iterations) # 回报历史
selected_arms = np.zeros(n_iterations, dtype=int) # 选择记录
Python 中的 Gymnasium 强化学习

交互循环

for i in range(n_iterations):
    arm = epsilon_greedy()

reward = np.random.rand() < true_bandit_probs[arm]
rewards[i] = reward selected_arms[i] = arm counts[arm] += 1
values[arm] += (reward - values[arm]) / counts[arm]
epsilon = max(min_epsilon, epsilon * epsilon_decay)
Python 中的 Gymnasium 强化学习

选择分析

selections_percentage = np.zeros((n_iterations, n_bandits))


图示:第一步,创建形状为 (iterations, n_bandits) 的全零数组。

Python 中的 Gymnasium 强化学习

选择分析

selections_percentage = np.zeros((n_iterations, n_bandits))

for i in range(n_iterations): selections_percentage[i, selected_arms[i]] = 1

图示:第二步,在每次迭代中将被选中的拉杆位置标记为 1。

Python 中的 Gymnasium 强化学习

选择分析

selections_percentage = np.zeros((n_iterations, n_bandits))

for i in range(n_iterations): selections_percentage[i, selected_arms[i]] = 1
selections_percentage = np.cumsum(selections_percentage, axis=0) / np.arange(1, n_iterations + 1).reshape(-1, 1)

图示:最后一步,对选择进行累加并除以迭代次数,得到每轮各拉杆的选择比例。

Python 中的 Gymnasium 强化学习

选择分析

  图:各拉杆的 selection_percentage 曲线。随迭代推进,智能体更常选择第 2 个拉杆。

for arm in range(n_bandits):
    plt.plot(selections_percentage[:, arm], label=f'Bandit #{arm+1}')
plt.xscale('log')
plt.title('Bandit Action Choices Over Time')
plt.xlabel('Episode Number')
plt.ylabel('Percentage of Bandit Selections (%)')
plt.legend()
plt.show()

for i, prob in enumerate(true_bandit_probs, 1): print(f"Bandit #{i} -> {prob:.2f}")
Bandit #1 -> 0.37
Bandit #2 -> 0.95
Bandit #3 -> 0.73
Bandit #4 -> 0.60
  • 智能体学会选择最高胜率的拉杆
Python 中的 Gymnasium 强化学习

Vamos praticar!

Python 中的 Gymnasium 强化学习

Preparing Video For Download...