首页 > 其他分享 >多臂老虎机——入门强化学习

多臂老虎机——入门强化学习

时间:2024-11-03 17:46:11浏览次数:5  
标签:入门 self arms 多臂 num np arm 老虎机

目录

什么是多臂老虎机?

强化学习中的多臂老虎机问题

解决多臂老虎机问题的常见方法

强化学习中的重要性

代码实现

结果与分析


        多臂老虎机(Multi-Armed Bandit,MAB)问题是强化学习的经典入门例子,也是理解探索与利用(exploration-exploitation)平衡的重要案例。

什么是多臂老虎机?

        设想你在一个赌场里,面前有一排老虎机,每台老虎机都有一个不同的中奖概率。你可以选择拉任意一个老虎机的“手臂”,但你不知道每台机器的中奖概率是多少。你的目标是在有限的操作次数内,最大化你的收益。

        每台老虎机(也称“臂”)对应一种概率分布,投币后会产生不同的奖励(例如赢得不同数量的筹码),但每台机器的奖励分布是固定的。问题的核心是如何选择拉哪台老虎机的手臂,以便在不确定每台机器的中奖概率的情况下获得最高收益。

强化学习中的多臂老虎机问题

        多臂老虎机问题在强化学习中是“探索与利用”平衡的基础案例。你面临着两个选择:

  1. 探索:选择不熟悉的手臂,以获取更多的信息。
  2. 利用:选择已知奖励较高的手臂,以获取更大的即时收益。

        探索过多会浪费资源,而利用过多则可能错过更优的选项。多臂老虎机问题提供了一个简单的框架来研究和测试不同的探索与利用策略。

解决多臂老虎机问题的常见方法

        以下是几种常见的解决策略:

  1. 贪心策略(Greedy)
    只选择当前预期奖励最高的臂。缺点是完全不探索,可能会错过最优臂。

  2. ε-贪心策略(ε-Greedy)
    在大部分时间(概率为 1−ϵ )选择当前最好的臂,但偶尔(概率为 ϵ )随机探索其他臂。通常,ϵ 会设为一个小值,比如 0.1,以平衡探索与利用。

  3. 上置信界(UCB,Upper Confidence Bound)
    基于统计学的原理,每个臂的奖励期望值上加上一个置信区间。随着臂的拉动次数增加,置信区间逐渐减小,最终可以更可靠地选择最优臂。UCB能在拉得较少的臂上探索更多次,从而加快找到最优臂的速度。

  4. 汤普森采样(Thompson Sampling)
    使用贝叶斯方法来选择臂。每次尝试时,依据历史奖励数据生成不同臂的奖励概率分布,然后从中采样选择最优臂。汤普森采样在很多情况下表现优于 ε-贪心和 UCB,尤其是分布已知的情况。

强化学习中的重要性

        多臂老虎机问题帮助我们了解如何在有不确定性和有限资源的情况下选择行动,这种探索与利用的平衡思想在更复杂的强化学习任务中非常重要。例如,在训练深度 Q 网络(DQN)或策略梯度(Policy Gradient)算法时,探索与利用的权衡直接影响收敛速度和策略的优劣。

        通过多臂老虎机问题,初学者可以更直观地理解强化学习中的策略选择与优化方式,为进一步学习复杂的环境奠定基础。

代码实现

        以下是这些策略的Python实现。首先,我们定义多臂老虎机环境,然后实现不同策略的代理。

import numpy as np

class MultiArmedBandit:
    def __init__(self, num_arms):
        # 每个老虎机臂的奖励分布是正态分布,均值在0到1之间,标准差为1
        self.probabilities = np.random.rand(num_arms)
        self.num_arms = num_arms
    
    def pull_arm(self, arm):
        # 模拟拉动臂的过程,返回一个奖励
        return np.random.normal(self.probabilities[arm], 1)

        1. 贪心策略

class GreedyAgent:
    def __init__(self, num_arms):
        self.num_arms = num_arms
        self.arm_counts = np.zeros(num_arms)  # 每个臂的拉动次数
        self.arm_rewards = np.zeros(num_arms)  # 每个臂的累计奖励
    
    def select_arm(self):
        # 选择当前期望奖励最高的臂
        return np.argmax(self.arm_rewards / (self.arm_counts + 1e-5))
    
    def update(self, arm, reward):
        # 更新该臂的奖励和次数
        self.arm_counts[arm] += 1
        self.arm_rewards[arm] += reward

        2. ε-贪心策略

class EpsilonGreedyAgent:
    def __init__(self, num_arms, epsilon=0.1):
        self.num_arms = num_arms
        self.epsilon = epsilon
        self.arm_counts = np.zeros(num_arms)
        self.arm_rewards = np.zeros(num_arms)
    
    def select_arm(self):
        if np.random.rand() < self.epsilon:
            # 以 ε 概率随机选择一个臂
            return np.random.randint(self.num_arms)
        else:
            # 否则选择期望奖励最高的臂
            return np.argmax(self.arm_rewards / (self.arm_counts + 1e-5))
    
    def update(self, arm, reward):
        self.arm_counts[arm] += 1
        self.arm_rewards[arm] += reward

        3. 上置信界(UCB)

class UCBAgent:
    def __init__(self, num_arms, c=2):
        self.num_arms = num_arms
        self.arm_counts = np.zeros(num_arms)
        self.arm_rewards = np.zeros(num_arms)
        self.c = c  # 控制置信区间大小的参数
    
    def select_arm(self):
        total_counts = np.sum(self.arm_counts)
        if total_counts == 0:
            return np.random.randint(self.num_arms)
        
        ucb_values = self.arm_rewards / (self.arm_counts + 1e-5) + \
                     self.c * np.sqrt(np.log(total_counts + 1) / (self.arm_counts + 1e-5))
        return np.argmax(ucb_values)
    
    def update(self, arm, reward):
        self.arm_counts[arm] += 1
        self.arm_rewards[arm] += reward

        4. 汤普森采样(Thompson Sampling)

class ThompsonSamplingAgent:
    def __init__(self, num_arms):
        self.num_arms = num_arms
        self.successes = np.zeros(num_arms)  # 记录每个臂成功的次数
        self.failures = np.zeros(num_arms)   # 记录每个臂失败的次数
    
    def select_arm(self):
        # 对每个臂从 beta 分布中采样
        samples = [np.random.beta(1 + self.successes[arm], 1 + self.failures[arm]) for arm in range(self.num_arms)]
        return np.argmax(samples)
    
    def update(self, arm, reward):
        # 更新成功或失败的次数
        if reward > 0:
            self.successes[arm] += 1
        else:
            self.failures[arm] += 1

        运行模拟实验

# 定义老虎机数量和步骤
num_arms = 10
num_steps = 1000
bandit = MultiArmedBandit(num_arms)

# 选择一个策略,初始化相应的Agent
agent = EpsilonGreedyAgent(num_arms, epsilon=0.1)  # 可以换成其他策略

# 记录奖励
rewards = []
for step in range(num_steps):
    arm = agent.select_arm()
    reward = bandit.pull_arm(arm)
    agent.update(arm, reward)
    rewards.append(reward)

# 计算平均奖励
average_reward = np.mean(rewards)
print(f"平均奖励: {average_reward:.2f}")

结果与分析

        不同策略的平均奖励可能不同。一般来说:

  • ε-贪心策略在长时间内能获得较高奖励。
  • UCB 和汤普森采样往往能更快找到最优臂,尤其在前期有较明显优势。

实验可以帮助直观地理解这些策略的特点,以及如何在不确定环境中平衡探索与利用。

标签:入门,self,arms,多臂,num,np,arm,老虎机
From: https://blog.csdn.net/qq_56683019/article/details/143466997

相关文章

  • MyBatis-Plus快速入门:从安装到第一个Demo
    一、前言在现代Java应用程序中,数据访问层的效率与简洁性至关重要。MyBatis-Plus作为MyBatis的增强工具,旨在简化常见的数据操作,提升开发效率。它提供了丰富的功能,如自动生成SQL、条件构造器和简单易用的CRUD操作,极大地减少了代码的冗余。本文将带你从零开始,快速入门MyBa......
  • 梁山派入门指南4——定时器使用详解,包括定时器中断、PWM产生、输入捕获测量频率
    梁山派入门指南4——定时器使用详解,包括定时器中断、PWM产生、输入捕获测量频率1.定时器概览2.基本定时器2.1基本定时器介绍2.2梁山派上的基本定时器开发2.2.1.了解梁山派上的基本定时器资源(实际上我们以及在上面了解过了)2.2.2.配置定时器2.2.3.编写定时器中断服务......
  • Jest生命周期方法全解析从入门到精通!
    Jest中的生命周期方法在Jest测试框架中,生命周期方法用于在测试用例执行前后执行特定的操作。这些方法可以帮助你在测试前设置环境、清理资源等。Jest提供了两类生命周期方法:重复性的生命周期方法beforeEachafterEach一次性的生命周期方法beforeAllafterAll这些方......
  • PostgreSQL11从入门到精通
    书:pan.baidu.com/s/1IVTI-jQveSb4Cdrio6XkBw?pwd=ijykPostgreSQL11是一个功能强大的开源关系型数据库管理系统,以下是对PostgreSQL11从入门到精通的技术分享:一、PostgreSQL11简介PostgreSQL起源于加利福尼亚的伯克利大学,经历了无数次开发升级,现已成为世界上最先进的开源关......
  • 【JQuery】基础从零入门操作,简单详细
    阿华代码,不是逆风,就是我疯你们的点赞收藏是我前进最大的动力!!希望本文内容能够帮助到你!!目录一:JQuery介绍1:引入依赖2:src3:下载说明4:版本说明二:JQuery使用三:JQuery语法1:起手式2:选中元素四:JQuery选择器五:JQuery事件1:事件的组成六:获取、设置元素内容1:获取元素内......
  • 【NOI】C++函数入门二(自定义函数)
    文章目录前言一、概念1.导入1.1首先什么是函数呢?2.函数分类3.为什么要定义函数呢?4.函数结构5.函数使用注意事项二、例题讲解问题:1137-纯粹素数问题:1258-求一个三位数问题:1140-亲密数对问题:1149-回文数个数三、总结四、感谢前言在这一章节中,我们将深入探......
  • 从递归到递推--入门篇
    从递归到递推–入门篇一.1.什么是递归递归是指一种通过重复将问题分解为子问题而解决问题的方法。具体到使用上来,就是指对函数自身的调用。本文所讨论的递归,都是基于函数对自身的调用。但是,递归并非仅对函数而言,递归是种思想,例如C语言中的链表的实现同样依托递归思想,本文......
  • Lambda表达式从入门到精通
    Lambda表达式一.入门Lambda表达式1.1概述1.2核心原则:1.3基本格式:二.使用Lambda表达式例一例二例三例四例五三.总结一.入门Lambda表达式1.1概述Lambda表达式是JDK8中的一个语法糖,他可以对某些匿名内部类的写法进行化简.它是函数式编程思想的一个重要体......
  • 书生大模型实训营第4期—入门岛第4关:玩转HF/魔搭/魔乐社区
    书生大模型实训营第4期—入门岛第4关:玩转HF/魔搭/魔乐社区任务一:模型下载1.使用HuggingFace平台下载模型1.1HuggingFace平台1.2InternLM模型下载1.3GitHubCodeSpace的使用1.3.1下载internlm2_5-7b-chat的配置文件1.3.2下载internlm2_5-chat-1_8b并打印示例输出......
  • Ubuntu零基础入门到精通【4.4讲】:️ 用户和权限管理
    目录:......