强化学习总结(有具体代码实现)

文章目录

  • 第一部分 强化学习基础
    • 第1章 强化学习概述
      • 1.1 强化学习概念
      • 1.2 强化学习的环境
      • 1.3 强化学习的目标
      • 1.4 强化学习的数据
    • 第2章 多臂老虎机问题(MAB问题)
      • 2.1 问题描述
        • 2.1.1 问题定义
        • 2.1.2 形式化描述
        • 2.1.3 累积懊悔
        • 2.1.4 估计期望奖励
      • 2.2 解决方法
        • 2.2.1 ϵ-贪婪算法
        • 2.2.2 上置信界算法
        • 2.2.3 汤普森采样算法
        • 2.2.4 小结
    • 第3章 马尔可夫决策过程
      • 3.1 马尔可夫过程
      • 3.2 马尔可夫奖励过程
        • 3.2.1 定义
        • 3.2.2 回报
        • 3.2.3 价值函数
      • 3.3 马尔可夫决策过程
      • 3.4 蒙特卡洛方法
      • 3.5 占用度量
      • 3.6 最优策略
    • 第4章 动态规划算法
    • 第5章 时序差分算法
    • 第6章 Dyna-Q 算法
  • 第二部分 强化学习进阶
    • 第7章 DQN 算法
    • 第8章 DQN 改进算法
    • 第9章 策略梯度算法
    • 第10章 Actor-Critic 算法
    • 第11章 TRPO 算法
    • 第12章 PPO 算法
    • 第13章 DDPG 算法
    • 第14章 SAC 算法
  • 第三部分 强化学习前沿
    • 第15章 模仿学习
    • 第16章 模型预测控制
    • 第17章 基于模型的策略优化
    • 第18章 离线强化学习
    • 第19章 目标导向的强化学习
    • 第20章 多智能体强化学习入门
    • 第21章 多智能体强化学习进阶

第一部分 强化学习基础

第1章 强化学习概述

1.1 强化学习概念

  1. 定义:强化学习是机器通过与环境交互来实现目标的一种计算方法。
    机器与环境的一轮交互:机器在环境的一个状态下做一个动作决策,动作执行后,环境发生改变并把相应的奖励反馈和下一轮状态传回机器。
  2. 交互
    在这里插入图片描述
    • 感知:智能体在某种程度上感知环境的状态
    • 决策:智能体根据当前状态计算出到达目标需要采取的动作的过程;
      策略是智能体最终体现的智能形式,是不同智能体之间的核心区别
    • 奖励:环境根据状态和智能体采取的动作,产生一个标量信号作为奖励反馈;
      最大化累计奖励期望是智能体提升策略的目标,也是衡量智能体策略好坏的关键指标

1.2 强化学习的环境

  环境的下一刻状态的概率分布由当前状态和智能体的动作共同决定,公式如下:

环境的下一刻状态 ∼ P ( ⋅ ∣ 当前状态,智能体的动作 ) 环境的下一刻状态 \sim P(\cdot | 当前状态,智能体的动作) 环境的下一刻状态P(当前状态,智能体的动作)

1.3 强化学习的目标

  • 整体回报:整个交互过程的每一轮获得的奖励信号的累加,类似一盘游戏最后的得分。
  • 价值:回报的期望,也是智能体学习的优化目标。
    计算方式:需要对交互过程中每一轮智能体采取动作的概率分布和环境相应的状态转移的概率分布做积分运算。

1.4 强化学习的数据

  在强化学习中,数据是智能体与环境交互的过程中得到的。如果智能体不采取某个决策动作,那么该动作对于的数据就无法被观测到,所以当前智能体的训练数据来自之前智能体的决策结果。因此,策略不同,得到的数据分布就不同。

  强化学习中有一个关于数据分布的概念,叫作占用度量。归一化的占用度量用于衡量在交互过程中,采样到一个具体的状态动作对的概率分布。

  占用度量的一个重要性质:占用度量相同当且仅当策略相同。因此,寻找最优策略对应寻找最优占用度量。

第2章 多臂老虎机问题(MAB问题)

2.1 问题描述

2.1.1 问题定义

  有一个用于 K 根拉杆的老虎机,每一根拉杆都对应一个关于奖励的概率分布 R 。每拉动一个拉杆,就可以从该拉杆的奖励概率分布中获得一个奖励 r 。在各拉杆的奖励概率分布未知的情况下,从头开始尝试,目标是在操作 T 次拉杆后获得尽可能高的累积奖励。

  由于奖励的概率分布是未知的,因此我们需要在“探索拉杆的获奖概率”和“根据经验选择获奖多的拉杆”中进行权衡。

【通俗易懂:有 K 个机器,你不知道每个机器的奖励概率分布,你只有 T 次机会选择机会,探索机器的奖励概率分布也算在 T 次内,然后尽可能获得最多的奖励。】

【示例:有 1 个 10 臂老虎机,你有 20 次选择机会,你可以花 10 次机会探索前 5 臂,根据获得的奖励,选择奖励期望最大的一个,剩下 10 次都选择最大的那 1 臂。(有可能奖励期望最大在没有探索的 5 臂中,也有可能在前 5 臂中,但是不是你选择的那个)】

2.1.2 形式化描述

  多臂老虎机问题可以表示为一个元组 < A ,    R > <A,\;R> <A,R>,其中:

  • A 为动作集合,其中一个动作表示拉动一根拉杆,若多臂老虎机有 K 个拉杆,则动作空间就是集合 { a 1 , a 2 , . . . , a K } \{a_1,a_2,...,a_K\} {a1,a2,...,aK},用 a t ∈ A a_t \in A atA 表示任意一个动作;
  • R 为概率分布,拉动每一根拉杆的动作 a 都对应一个奖励概率分布 R ( r ∣ a ) R(r|a) R(ra),拉动不同拉杆的奖励分布通常是不同。

  假设每个时间步只能拉动 1 根拉杆,多臂老虎机的目标为最大化一段时间步 T 内累积的奖励: m a x ∑ t = 1 T r t ,    r t ∼ R ( ⋅ ∣ a t ) max\sum^T_{t=1}r_t,\;r_t\sim R(\cdot|a_t) maxt=1Trt,rtR(at)。其中 a t a_t at 表示在第 t 时间步拉动某一拉杆的动作, r t r_t rt 表示动作 a t a_t at 获得的奖励。

2.1.3 累积懊悔

  对于每一个动作 a ,我们定义其期望奖励为 Q ( a ) = E r ∼ R ( ⋅ ∣ a ) [ r ] Q(a)=E_{r\sim R(\cdot | a)}[r] Q(a)=ErR(a)[r] 。于是,至少存在一根拉杆,它的期望奖励不小于任意一根拉杆,将该最优期望奖励表示为 Q ∗ = max ⁡ a ∈ A Q ( a ) Q^*=\max_{a\in A}Q(a) Q=maxaAQ(a)

  • 懊悔:当前动作 a 与最优拉杆期望奖励的差距,即 R ( a ) = Q ∗ − Q ( a ) R(a)=Q^*-Q(a) R(a)=QQ(a)
  • 累积懊悔:操作 T 次拉杆后累积的懊悔总量,对于一次完整的 T 步决策 { a 1 , a 2 , . . . , a T } \{a_1,a_2,...,a_T\} {a1,a2,...,aT} ,累积懊悔为: σ R = ∑ t = 1 T R ( a t ) \sigma_R=\sum^T_{t=1}R(a_t) σR=t=1TR(at)

  所以求解 MAB 问题等价于最小化累积懊悔

2.1.4 估计期望奖励

  为了知道拉动哪一根拉杆可以获得更高的奖励,所以我们需要估计这根拉杆的期望奖励。

算法流程:

对于 ∀ a ∈ A \forall a\in A aA ,初始化计算器 N ( a ) = 0 N(a)=0 N(a)=0 和 期望奖励估值 Q ^ ( a ) = 0 \hat{Q}(a)=0 Q^(a)=0
for t = 1 → T t=1 \rightarrow T t=1T do
  选取某根拉杆,该动作记为 a t a_t at
  得到奖励 r t r_t rt
  更新计数器: N ( a t ) + = 1 N(a_t)+=1 N(at)+=1
  更新期望奖励估值: Q ^ ( a t ) + = 1 N ( a t ) [ r t − Q ^ ( a t ) ] \hat{Q}(a_t)+=\frac{1}{N(a_t)}[r_t-\hat{Q}(a_t)] Q^(at)+=N(at)1[rtQ^(at)]

示例:

  编写一个拉杆为 10 的多臂老虎机。其中每个拉杆的奖励服从伯努利分布,即每次有 p 的概率获得奖励 1 ,有 1-p 的概率获得奖励 0 。【0 表示没有获奖,1 表示获奖。】

在 MAB 目录下新建 BernoulliBandit.py 文件
在这里插入图片描述
代码如下:

import numpy as np
import matplotlib.pyplot as plt


class BernoulliBandit:
    """伯努利多臂老虎机,输入 K 表示拉杆个数"""

    def __init__(self, K):
        self.probs = np.random.uniform(size=K)  # 随机生成 K 个 0-1 的数,表示每个拉杆的获奖概率
        self.best_idx = np.argmax(self.probs)  # 获奖概率最大的拉杆
        self.best_prob = self.probs[self.best_idx]  # 最大的获奖概率
        self.K=K

    def step(self, k):
        if np.random.rand() < self.probs[k]:
            return 1
        else:
            return 0


np.random.seed(1)
K = 10
bandit = BernoulliBandit(K)
print("随机生成了一个 %d 臂的伯努利多臂老虎机" % K)
print("获奖概率最大的拉杆为 %d 号,其获奖概率为 %.4f" % (bandit.best_idx, bandit.best_prob))

运行结果如下:

D:\RL\MAB\.venv\Scripts\python.exe D:\RL\MAB\BernoulliBandit.py 
随机生成了一个10臂的伯努利多臂老虎机
获奖概率最大的拉杆为1 号,其获奖概率为0.7203

进程已结束,退出代码为 0

  接下来编写 Solver 基础类来解决 MAB 问题。具体的解决策略由每个继承 Solver 的类来实现。

  新建 Solver.py 文件,文件代码如下:

import numpy as np


class Solver:
    """多臂老虎机解决方案抽象类"""

    def __init__(self, bandit):
        self.bandit = bandit
        self.counts = np.zeros(self.bandit.K) # 每根拉杆的尝试次数
        self.regret = 0 # 当前步的累积懊悔
        self.actions = []   # 记录每一步的动作
        self.regrets = []   # 记录每一步的累积懊悔

    def update_regret(self, k):
        # 记录累积懊悔并保存,k为本次动作选择的拉杆的编号
        self.regret += self.bandit.best_prob - self.bandit.probs[k]
        self.regrets.append(self.regret)

    def run_one_step(self):
        # 返回当前动作选择的拉杆,由具体的策略实现
        raise NotImplementedError

    def run(self, num_steps):
        # 运行一定次数,num_steps为总运行次数
        for _ in range(num_steps):
            k = self.run_one_step()
            self.counts[k] += 1
            self.actions.append(k)
            self.update_regret(k)

可能遇到的问题与解决方案

  1. 没有配置 numpy 的模块
    在这里插入图片描述
    解决方案:
    点击设置
    在这里插入图片描述
    在项目:xxxx 的 Python 解释器中,点击 + 号
    在这里插入图片描述
    输入 numpy ,选择第一个,点击安装软件包
    在这里插入图片描述
    安装成功后关闭该界面
    在这里插入图片描述
    此时发现项目软件包中多了 numpy,点击确定即可。
    在这里插入图片描述
  2. 没有配置 matplotlib 的模块
    解决方案:
    同上,只是搜索 matplotlib 即可
    在这里插入图片描述

2.2 解决方法

2.2.1 ϵ-贪婪算法

  完全贪婪算法就是在每一刻都采取期望奖励估值最大的动作,这就是纯粹的利用,没有探索。而 ε-贪婪算法则是在其基础上添加了噪声,每次以 1-ε 的概率选择以往经验中期望奖励估值最大的那根拉杆【利用】,以 ε 的概率随机选择一根拉杆【探索】,公式如下:

a t = { a r g    max ⁡ a ∈ A Q ^ ,采样概率: 1 − ϵ 从 A 中随机选择,采样概率: ϵ a_t= \left\{ \begin{array}{ll} arg\; \max\limits_{a\in A} \hat{Q},采样概率:1-\epsilon \\ 从A中随机选择,采样概率:\epsilon \end{array} \right. at={argaAmaxQ^,采样概率:1ϵA中随机选择,采样概率:ϵ

  随着探索次数不断的增多,对各个动作的奖励估计越来越准确,所以没必要继续花费大力气进行探索。所以我们可以让 ε 随着时间衰减,但是不会到 0 。因为基于有限步观测的完全贪婪算法仍然是一个局部信息的贪婪算法,永远离最优解有一个固定的差距。

项目结构:

在这里插入图片描述

新建 EpsilonGreedy.py 文件,文件代码如下:

import numpy as np

from Solver import Solver


class EpsilonGreedy(Solver):
    def __init__(self,bandit,epsilon=0.01,init_prob=1.0):
        super(EpsilonGreedy,self).__init__(bandit)
        self.epsilon = epsilon
        self.estimates=np.array([init_prob]*self.bandit.K)

    def run_one_step(self):
        if np.random.random()<self.epsilon:
            k=np.random.randint(0,self.bandit.K)
        else:
            k=np.argmax(self.estimates)
        r=self.bandit.step(k)
        self.estimates[k]+=1./(self.counts[k]+1)*(r-self.estimates[k])
        return k

在新建 Main.py 文件,文件代码如下:

import numpy as np
from matplotlib import pyplot as plt

from BernoulliBandit import bandit
from EpsilonGreedy import EpsilonGreedy


def plot_results(solvers, solver_names):
    """输出解决方法的累积懊悔变化图"""
    for idx, solver in enumerate(solvers):
        time_list = range(len(solver.regrets))
        plt.plot(time_list, solver.regrets, label=solver_names[idx])
    plt.xlabel('Time Step')
    plt.ylabel('Cumulative regrets')
    plt.title('%d-arm bandit' % solvers[0].bandit.K)
    plt.legend()
    plt.show()


np.random.seed(1)
epsilon_greedy_solver = EpsilonGreedy(bandit, epsilon=0.01)
epsilon_greedy_solver.run(5000)
print('epsilon-贪婪算法的累积懊悔为:', epsilon_greedy_solver.regret)
plot_results([epsilon_greedy_solver], ["EpsilonGreedy"])

运行 Main.py 文件,结果如下:

在这里插入图片描述

随机生成了一个 10 臂的伯努利多臂老虎机
获奖概率最大的拉杆为 1 号,其获奖概率为 0.7203
epsilon-贪婪算法的累积懊悔为: 25.526630933945313

  接下来尝试不同 ε 取值的结果:

修改 Main.py 代码如下:

import numpy as np
from matplotlib import pyplot as plt

from BernoulliBandit import bandit
from EpsilonGreedy import EpsilonGreedy


def plot_results(solvers, solver_names):
    """输出解决方法的累积懊悔变化图"""
    for idx, solver in enumerate(solvers):
        time_list = range(len(solver.regrets))
        plt.plot(time_list, solver.regrets, label=solver_names[idx])
    plt.xlabel('Time Step')
    plt.ylabel('Cumulative regrets')
    plt.title('%d-arm bandit' % solvers[0].bandit.K)
    plt.legend()
    plt.show()


# np.random.seed(1)
# epsilon_greedy_solver = EpsilonGreedy(bandit, epsilon=0.01)
# epsilon_greedy_solver.run(5000)
# print('epsilon-贪婪算法的累积懊悔为:', epsilon_greedy_solver.regret)
# plot_results([epsilon_greedy_solver], ["EpsilonGreedy"])

np.random.seed(0)
epsilons = [1e-4, 0.01, 0.1, 0.25, 0.5]
epsilon_greedy_solver_list = [EpsilonGreedy(bandit, epsilon=e) for e in epsilons]
epsilon_greedy_solver_names = ['epsilon={}'.format(e) for e in epsilons]
for epsilon_greedy_solver in epsilon_greedy_solver_list:
    epsilon_greedy_solver.run(5000)

plot_results(epsilon_greedy_solver_list, epsilon_greedy_solver_names)

运行 Main.py 文件,结果如下:

在这里插入图片描述

随机种子为 0 的结果很完美,但是选择随机种子为 1 的话,这是实验结果:

在这里插入图片描述

但是将时间步扩大为 50000,实验结果又变回来了

在这里插入图片描述

  接下来尝试 ε 随着时间反比例衰减,公式为: ϵ t = 1 t \epsilon_t=\frac1t ϵt=t1

修改 EpsilonGreedy.py 文件,文件代码如下:

import numpy as np

from Solver import Solver


class EpsilonGreedy(Solver):
    def __init__(self, bandit, epsilon=0.01, init_prob=1.0):
        super(EpsilonGreedy, self).__init__(bandit)
        self.epsilon = epsilon
        self.estimates = np.array([init_prob] * self.bandit.K)

    def run_one_step(self):
        if np.random.random() < self.epsilon:
            k = np.random.randint(0, self.bandit.K)
        else:
            k = np.argmax(self.estimates)
        r = self.bandit.step(k)
        self.estimates[k] += 1. / (self.counts[k] + 1) * (r - self.estimates[k])
        return k


class DecayingEpsilonGreedy(Solver):
    def __init__(self, bandit, init_prob=1.0):
        super(DecayingEpsilonGreedy, self).__init__(bandit)
        self.estimates = np.array([init_prob] * self.bandit.K)
        self.total_count = 0

    def run_one_step(self):
        self.total_count += 1
        if np.random.random() < 1 / self.total_count:
            k = np.random.randint(0, self.bandit.K)
        else:
            k = np.argmax(self.estimates)
        r = self.bandit.step(k)
        self.estimates[k] = 1. / (self.counts[k] + 1) * (r - self.estimates[k])

        return k

修改 Main.py 文件,文件代码如下:

import numpy as np
from matplotlib import pyplot as plt

from BernoulliBandit import bandit
from EpsilonGreedy import EpsilonGreedy, DecayingEpsilonGreedy


def plot_results(solvers, solver_names):
    """输出解决方法的累积懊悔变化图"""
    for idx, solver in enumerate(solvers):
        time_list = range(len(solver.regrets))
        plt.plot(time_list, solver.regrets, label=solver_names[idx])
    plt.xlabel('Time Step')
    plt.ylabel('Cumulative regrets')
    plt.title('%d-arm bandit' % solvers[0].bandit.K)
    plt.legend()
    plt.show()


# np.random.seed(1)
# epsilon_greedy_solver = EpsilonGreedy(bandit, epsilon=0.01)
# epsilon_greedy_solver.run(5000)
# print('epsilon-贪婪算法的累积懊悔为:', epsilon_greedy_solver.regret)
# plot_results([epsilon_greedy_solver], ["EpsilonGreedy"])


# np.random.seed(1)
# epsilons = [1e-4, 0.01, 0.1, 0.25, 0.5]
# epsilon_greedy_solver_list = [EpsilonGreedy(bandit, epsilon=e) for e in epsilons]
# epsilon_greedy_solver_names = ['epsilon={}'.format(e) for e in epsilons]
# for epsilon_greedy_solver in epsilon_greedy_solver_list:
#     epsilon_greedy_solver.run(50000)
# plot_results(epsilon_greedy_solver_list, epsilon_greedy_solver_names)


np.random.seed(1)
decaying_epsilon_greedy_solver = DecayingEpsilonGreedy(bandit)
decaying_epsilon_greedy_solver.run(5000)
print('epsilon 反比衰减的贪婪算法的累积懊悔为:', decaying_epsilon_greedy_solver.regret)
plot_results([decaying_epsilon_greedy_solver], ["DecayingEpsilonGreedy"])

运行 Main.py 文件,结果如下:

在这里插入图片描述

D:\RL\MAB\.venv\Scripts\python.exe D:\RL\MAB\Main.py 
随机生成了一个 10 臂的伯努利多臂老虎机
获奖概率最大的拉杆为 1 号,其获奖概率为 0.7203
epsilon 反比衰减的贪婪算法的累积懊悔为: 10.114334931260183

进程已结束,退出代码为 0

这是扩大时间步至 50000 的结果:

在这里插入图片描述

  从实验结果可以发现,反比例衰减的 ε-贪婪算法可以使得累积懊悔与时间步的关系变为次线性,这明显优于固定 ε 值的 ε-贪婪算法。

2.2.2 上置信界算法

  对于多臂老虎机来说,一根拉杆的探索次数较少,它的不确定性就很高。不确定越高,它具有的探索价值就越大。为此,引入不确定性度量 U(a) ,它随着一个动作被尝试次数的增加而减少。【说白了就是新鲜感】

  上置信界(UCB)算法是一种经典的基于不确定性的策略算法,其思想是基于霍夫丁不等式。在霍夫丁不等式中,令 X 1 , X 2 , . . . , X n X_1,X_2,...,X_n X1,X2,...,Xn 为 n 个独立同分布的随机变量,取值范围为 [0,1] ,其经验期望为 x ˉ = 1 n ∑ j = 1 n X j \bar{x}=\frac1n\sum ^n_{j=1}X_j xˉ=n1j=1nXj ,则有 P ( E [ X ] ≥ x ˉ + u ) ≤ e − 2 n u 2 P(E[X]\ge\bar{x}+u)\le e^{-2nu^2} P(E[X]xˉ+u)e2nu2

  将霍夫丁不等式运用到多臂老虎机问题中。 Q ^ \hat{Q} Q^ 代入 x ˉ \bar{x} xˉ,不等式中 u = U ^ ( a t ) u=\hat{U}(a_t) u=U^(at) 代表不确定性度量。给定一个概率 p = e − 2 N ( a t ) U ( a t ) 2 p=e^{-2N(a_t)U(a_t)^2} p=e2N(at)U(at)2 ,根据上述不等式, Q ( a t ) < Q ^ ( a t ) + U ^ ( a t ) Q(a_t)<\hat{Q}(a_t)+\hat{U}(a_t) Q(at)<Q^(at)+U^(at) 至少以概率 1 − p 1 - p 1p 成立,当 p 很小时, Q ( a t ) < Q ^ ( a t ) + U ^ ( a t ) Q(a_t)<\hat{Q}(a_t)+\hat{U}(a_t) Q(at)<Q^(at)+U^(at) 就以很大概率成立,所以 Q ^ ( a t ) + U ^ ( a t ) \hat{Q}(a_t)+\hat{U}(a_t) Q^(at)+U^(at) 就是期望奖励上界。

  根据 p = e − 2 N ( a t ) U ( a t ) 2 p=e^{-2N(a_t)U(a_t)^2} p=e2N(at)U(at)2 得知 U ^ ( a t ) = − log ⁡ p 2 N ( a t ) \hat{U}(a_t)=\sqrt{\frac{-\log p}{2N(a_t)}} U^(at)=2N(at)logp ,其中 N ( a t ) N(a_t) N(at) 是该拉杆的已经拉动的次数。确定概率 p 就可以计算 U ^ ( a t ) \hat{U}(a_t) U^(at)

  在实际编程中,令 p = 1 t p=\frac1t p=t1 ;令 U ^ ( a t ) = − log ⁡ p 2 ( N ( a t ) + 1 ) \hat{U}(a_t)=\sqrt{\frac{-\log p}{2(N(a_t)+1)}} U^(at)=2(N(at)+1)logp ,以免出现分母为 0 的情况;令 a t = a r g    m a x a ∈ A [ Q ^ ( a ) + c ⋅ U ^ ( a ) ] a_t=arg\;max_{a\in A}[\hat{Q}(a)+c\cdot\hat{U}(a)] at=argmaxaA[Q^(a)+cU^(a)] ,用系数 c 来控制不确定性比重。

新建 UCB.py 文件,文件代码如下:

import numpy as np

from Solver import Solver


class UCB(Solver):
    def __init__(self, bandit, c, init_prob=1.0):
        super(UCB, self).__init__(bandit)
        self.total_count = 0
        self.estimates = np.array([init_prob] * self.bandit.K)
        self.c = c

    def run_one_step(self):
        self.total_count += 1
        ucb = self.estimates + self.c * np.sqrt(np.log(self.total_count) / (2 * (self.counts + 1)))  # 计算上置信界
        k = np.argmax(ucb)
        r = self.bandit.step(k)
        self.estimates[k] += 1. / (self.counts[k] + 1) * (r - self.estimates[k])
        return k

修改 Main.py 文件,文件代码如下:

import numpy as np
from matplotlib import pyplot as plt

from BernoulliBandit import bandit
from EpsilonGreedy import EpsilonGreedy, DecayingEpsilonGreedy
from UCB import UCB


def plot_results(solvers, solver_names):
    """输出解决方法的累积懊悔变化图"""
    for idx, solver in enumerate(solvers):
        time_list = range(len(solver.regrets))
        plt.plot(time_list, solver.regrets, label=solver_names[idx])
    plt.xlabel('Time Step')
    plt.ylabel('Cumulative regrets')
    plt.title('%d-arm bandit' % solvers[0].bandit.K)
    plt.legend()
    plt.show()


def apply_epsilon_greedy_1():
    np.random.seed(1)
    epsilon_greedy_solver = EpsilonGreedy(bandit, epsilon=0.01)
    epsilon_greedy_solver.run(5000)
    print('epsilon-贪婪算法的累积懊悔为:', epsilon_greedy_solver.regret)
    plot_results([epsilon_greedy_solver], ["EpsilonGreedy"])


def apply_epsilon_greedy_2():
    np.random.seed(1)
    epsilons = [1e-4, 0.01, 0.1, 0.25, 0.5]
    epsilon_greedy_solver_list = [EpsilonGreedy(bandit, epsilon=e) for e in epsilons]
    epsilon_greedy_solver_names = ['epsilon={}'.format(e) for e in epsilons]
    for epsilon_greedy_solver in epsilon_greedy_solver_list:
        epsilon_greedy_solver.run(50000)
    plot_results(epsilon_greedy_solver_list, epsilon_greedy_solver_names)


def apply_decaying_epsilon_greedy():
    np.random.seed(1)
    decaying_epsilon_greedy_solver = DecayingEpsilonGreedy(bandit)
    decaying_epsilon_greedy_solver.run(50000)
    print('epsilon 反比衰减的贪婪算法的累积懊悔为:', decaying_epsilon_greedy_solver.regret)
    plot_results([decaying_epsilon_greedy_solver], ["DecayingEpsilonGreedy"])


def apply_UCB():
    np.random.seed(1)
    c = 1  # 不确定性比重
    UCB_solver = UCB(bandit, c)
    UCB_solver.run(5000)
    print('上置信界算法累积懊悔为:', UCB_solver.regret)
    plot_results([UCB_solver], ["UCB"])

apply_UCB()

运行 Main.py 文件,结果如下:

在这里插入图片描述

D:\RL\MAB\.venv\Scripts\python.exe D:\RL\MAB\Main.py 
随机生成了一个 10 臂的伯努利多臂老虎机
获奖概率最大的拉杆为 1 号,其获奖概率为 0.7203
上置信界算法累积懊悔为: 70.45281214197854

进程已结束,退出代码为 0
2.2.3 汤普森采样算法

  MAB问题还有一种经典算法——汤普森采样,先假设每个拉杆的奖励服从特定的概率分布,然后根据每个拉杆的期望奖励来进行选择。但是计算所有拉杆的期望奖励的代价比较高,所以该算法使用采样的方式,即根据当前每个动作 a 的奖励概率分布进行一轮采样,得到一组拉杆的奖励样本,再选择样本中奖励最大的动作。【汤普森采样是一种计算所有拉杆的最高奖励概率的蒙特卡洛采样方法】

  在实际中,通常用 Beta 分布对当前每个动作的奖励概率分布进行建模。具体来说,若某拉杆被选择了 k 次,其中 m 1 m_1 m1 次奖励为 1, m 2 m_2 m2 次奖励为 0,则该拉杆服从参数为 ( m 1 + 1 , m 2 + 1 ) (m_1+1,m_2+1) (m1+1,m2+1) Beta 分布。

新建 ThompsonSampling.py 文件,文件代码如下:

import numpy as np

from Solver import Solver


class ThompsonSampling(Solver):
    def __init__(self, bandit):
        super(ThompsonSampling, self).__init__(bandit)
        self._a = np.ones(self.bandit.K)
        self._b = np.ones(self.bandit.K)

    def run_one_step(self):
        samples = np.random.beta(self._a, self._b)
        k = np.argmax(samples)
        r = self.bandit.step(k)
        self._a[k] += r
        self._b[k] += (1 - r)
        return k

修改 Main.py 文件,文件代码如下:

import numpy as np
from matplotlib import pyplot as plt

from BernoulliBandit import bandit
from EpsilonGreedy import EpsilonGreedy, DecayingEpsilonGreedy
from ThompsonSampling import ThompsonSampling
from UCB import UCB


def plot_results(solvers, solver_names):
    """输出解决方法的累积懊悔变化图"""
    for idx, solver in enumerate(solvers):
        time_list = range(len(solver.regrets))
        plt.plot(time_list, solver.regrets, label=solver_names[idx])
    plt.xlabel('Time Step')
    plt.ylabel('Cumulative regrets')
    plt.title('%d-arm bandit' % solvers[0].bandit.K)
    plt.legend()
    plt.show()


def apply_epsilon_greedy_1():
    np.random.seed(1)
    epsilon_greedy_solver = EpsilonGreedy(bandit, epsilon=0.01)
    epsilon_greedy_solver.run(5000)
    print('epsilon-贪婪算法的累积懊悔为:', epsilon_greedy_solver.regret)
    plot_results([epsilon_greedy_solver], ["EpsilonGreedy"])


def apply_epsilon_greedy_2():
    np.random.seed(1)
    epsilons = [1e-4, 0.01, 0.1, 0.25, 0.5]
    epsilon_greedy_solver_list = [EpsilonGreedy(bandit, epsilon=e) for e in epsilons]
    epsilon_greedy_solver_names = ['epsilon={}'.format(e) for e in epsilons]
    for epsilon_greedy_solver in epsilon_greedy_solver_list:
        epsilon_greedy_solver.run(50000)
    plot_results(epsilon_greedy_solver_list, epsilon_greedy_solver_names)


def apply_decaying_epsilon_greedy():
    np.random.seed(1)
    decaying_epsilon_greedy_solver = DecayingEpsilonGreedy(bandit)
    decaying_epsilon_greedy_solver.run(50000)
    print('epsilon 反比衰减的贪婪算法的累积懊悔为:', decaying_epsilon_greedy_solver.regret)
    plot_results([decaying_epsilon_greedy_solver], ["DecayingEpsilonGreedy"])


def apply_UCB():
    np.random.seed(1)
    c = 1  # 不确定性比重
    UCB_solver = UCB(bandit, c)
    UCB_solver.run(5000)
    print('上置信界算法累积懊悔为:', UCB_solver.regret)
    plot_results([UCB_solver], ["UCB"])


def apply_thompson_sampling():
    np.random.seed(1)
    thompson_sampling_solver = ThompsonSampling(bandit)
    thompson_sampling_solver.run(5000)
    print('汤普森采样算法累积懊悔为:', thompson_sampling_solver.regret)
    plot_results([thompson_sampling_solver], ["ThompsonSampling"])

apply_thompson_sampling()

运行 Main.py 文件,结果如下:

在这里插入图片描述

D:\RL\MAB\.venv\Scripts\python.exe D:\RL\MAB\Main.py 
随机生成了一个 10 臂的伯努利多臂老虎机
获奖概率最大的拉杆为 1 号,其获奖概率为 0.7203
汤普森采样算法累积懊悔为: 57.19161964443925

进程已结束,退出代码为 0
2.2.4 小结
算法累积懊悔与时间步的关系
ε-贪婪算法线性
ε-衰减贪婪算法次线性(对数)
上置信界算法次线性(对数)
汤普森采样算法次线性(对数)

第3章 马尔可夫决策过程

3.1 马尔可夫过程

过程介绍
随机过程在某时刻 t 的状态 S t S_t St 通常取决于 t 时刻之前的状态。状态 S t + 1 S_{t+1} St+1 的概率表示为: P ( S t + 1 ∣ S 1 , . . . , S t ) P(S_{t+1}|S_1,...,S_t) P(St+1S1,...,St)
马尔可夫过程某时刻 t 的状态只取决于上一个时刻 t-1 的状态。状态 S t + 1 S_{t+1} St+1 的概率表示为: P ( S t + 1 ∣ S t ) = P ( S t + 1 ∣ S 1 , . . . , S t ) P(S_{t+1}|S_t)=P(S_{t+1}|S_1,...,S_t) P(St+1St)=P(St+1S1,...,St)

  马尔可夫过程也被称为马尔可夫链,通常用元组 < S , P > <S,P> <S,P> 来描述,其中 S 是有限数量的状态集合,P 是状态转移矩阵。假设有 n 个状态,则 S = { s 1 , s 2 , . . . , s n } S=\{s_1,s_2,...,s_n\} S={s1,s2,...,sn} ,
P = [ P ( s 1 ∣ s 1 ) ⋯ P ( s n ∣ s 1 ) ⋮ ⋱ ⋮ P ( s 1 ∣ s n ) ⋯ P ( s n ∣ s n ) ] P=\begin{bmatrix} P(s_1|s_1) & \cdots & P(s_n|s_1) \\ \vdots & \ddots & \vdots\\ P(s_1|s_n) & \cdots & P(s_n|s_n) \end{bmatrix} P= P(s1s1)P(s1sn)P(sns1)P(snsn)
  矩阵 P 中第 i 行第 j 列元素 P ( s j ∣ s i ) = P ( S t + 1 = s j ∣ S t = s i ) P(s_j|s_i)=P(S_{t+1}=s_j|S_t=s_i) P(sjsi)=P(St+1=sjSt=si) 表示从状态 s i s_i si 转移到状态 s j s_j sj 的概率,称 P ( s ′ ∣ s ) P(s'|s) P(ss) 为状态转移函数。从某个状态出发,到达其他状态的概率和必须为 1 。即状态转移矩阵 P 的每一行和为 1 。

示例:

在这里插入图片描述

S = { S i , 1 ≤ i ≤ 6 }    状态转移矩阵    P = [ 0.9 0.1 0 0 0 0 0.5 0 0.5 0 0 0 0 0 0 0.6 0 0.4 0 0 0 0 0.3 0.7 0 0.2 0.3 0.5 0 0 0 0 0 0 0 1 ] S=\{S_i,1\le i \le 6\} \\ \; \\ 状态转移矩阵\;P= \begin{bmatrix} 0.9 & 0.1 & 0 & 0 & 0 & 0 \\ 0.5 & 0 & 0.5 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0.6 & 0 & 0.4 \\ 0 & 0 & 0 & 0 & 0.3 & 0.7 \\ 0 & 0.2 & 0.3 & 0.5 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 1 \\ \end{bmatrix} S={Si,1i6}状态转移矩阵P= 0.90.500000.10000.2000.5000.30000.600.500000.300000.40.701

3.2 马尔可夫奖励过程

3.2.1 定义

  马尔可夫奖励过程由 < S , P , r , γ > <S,P,r,\gamma> <S,P,r,γ> 构成,其中:

  • S 是有限状态的集合
  • P 是状态转移矩阵
  • r 是奖励函数, r ( s ) r(s) r(s) 是指转移到该状态时可以获得的奖励期望
  • γ \gamma γ 是折扣因子,取值范围为: [ 0 , 1 ] [0,1] [0,1] 。引入折扣因子是因为远期利益具有一定的不确定性,有时希望能尽快获得有些奖励,所以需要对远期利益打一些折扣。接近 1 则更关注长期的累积奖励,接近 0 则更关注短期奖励。
3.2.2 回报

  回报是指从状态 S t S_t St 开始,一直到终止状态,所有奖励的衰减之和。具体公式如下:
G t = ∑ k = 0 ∞ γ k R t + k G_t=\sum^{\infty}_{k=0}\gamma^kR_{t+k} Gt=k=0γkRt+k
  其中 R t R_t Rt 是指在时刻 t 获得的奖励。

示例:

在这里插入图片描述
【状态旁的数字表示进入该状态获得的奖励】

新建项目 MDP,项目结构如下:

在这里插入图片描述

在 MDP 目录下新建文件 MRP.py ,文件代码如下:

import numpy as np

np.random.seed(0)

P = [
    [0.9, 0.1, 0.0, 0.0, 0.0, 0.0],
    [0.5, 0.0, 0.5, 0.0, 0.0, 0.0],
    [0.0, 0.0, 0.0, 0.6, 0.0, 0.4],
    [0.0, 0.0, 0.0, 0.0, 0.3, 0.7],
    [0.0, 0.2, 0.3, 0.5, 0.0, 0.0],
    [0.0, 0.0, 0.0, 0.0, 0.0, 1.0]
]
P = np.array(P)
rewards = [-1, -2, -2, 10, 1, 0]
gamma = 0.5


def compute_return(start, chain, gamma):
    G = 0
    for i in reversed(range(start, len(chain))):
        G = gamma * G + rewards[chain[i] - 1]
    return G


chain = [1, 2, 3, 6]
start = 0
G = compute_return(start, chain, gamma)
print('计算回报为:%s' % G)

运行 MRP.py 文件,运行结果如下:

D:\RL\MDP\.venv\Scripts\python.exe D:\RL\MDP\MRP.py 
计算回报为:-2.5

进程已结束,退出代码为 0
3.2.3 价值函数

3.3 马尔可夫决策过程

3.4 蒙特卡洛方法

3.5 占用度量

3.6 最优策略

第4章 动态规划算法

第5章 时序差分算法

第6章 Dyna-Q 算法

第二部分 强化学习进阶

第7章 DQN 算法

第8章 DQN 改进算法

第9章 策略梯度算法

第10章 Actor-Critic 算法

第11章 TRPO 算法

第12章 PPO 算法

第13章 DDPG 算法

第14章 SAC 算法

第三部分 强化学习前沿

第15章 模仿学习

第16章 模型预测控制

第17章 基于模型的策略优化

第18章 离线强化学习

第19章 目标导向的强化学习

第20章 多智能体强化学习入门

第21章 多智能体强化学习进阶

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/789121.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java泛型的定义与运用

泛型 泛型的作用从使用层面上来说是统一数据类型&#xff0c;防止将来的数据转换异常。从定义层面上来说&#xff0c;定义带泛型的类&#xff0c;方法等&#xff0c;将来使用的时候给泛型确定什么类型&#xff0c;泛型就会变成什么类型&#xff0c;凡是涉及到泛型的都会变成确…

【Mark笔记】基于Centos7.7更改SSH端口重启服务报错

0x0 场景描述 RT&#xff0c;更改默认端口22为2276后直接重启服务报错&#xff1a; 查看报错内容&#xff0c;如下&#xff1a; 0x1 相关操作 关闭selinux &#xff08;未重启&#xff09;本地防火墙端口放行tcp 2276端口更改回22端口服务可以正常启动sshd -t 检查配置并未…

【086】基于Springboot+vue实现的图书商城购物系统

系统介绍 视频演示 基于Springbootvue实现的图书商城购物系统采用前后端分离的架构方式&#xff0c;系统分为管理员、用户两个角色&#xff0c;实现了用户注册与登录、用户管理、书籍分类管理、书籍管理、轮播图管理、资讯管理、订单及发货管理等功能。 技术选型 开发工具&…

增强现实(AR)与虚拟现实(VR)的区别?

随着科技的飞速发展&#xff0c;增强现实&#xff08;AR&#xff09;与虚拟现实&#xff08;VR&#xff09;技术在各个领域展现出巨大的潜力和应用前景。这两种技术虽然在体验和实现方式上有所不同&#xff0c;但都为用户提供了全新的感知体验。本文将详细解析AR和VR的概念、区…

房地产销售管理能力提升之资产复用、优化管理

提升房地产销售管理能力&#xff0c;从哪些场景入手&#xff1f;惟客数据认为可以从放大流量、提升优化、资产复用、优化管理四方面入手。 本篇继续拆解如何做好“资产复用、优化管理”&#xff1a; 一、资产复用 首先&#xff0c;通过全渠道客户数据的整合与挖掘&#xff0c;…

雷池WAF动态防护功能初体验

一、 介绍 大名鼎鼎的雷池WAF最近新上了个名为 动态防护 的功能 所谓动态防护&#xff0c;是在用户浏览到的网页内容不变的情况下&#xff0c;将网页赋予动态特性&#xff0c;即使是静态页面&#xff0c;也会具有动态的随机性。 说白了就是给你网站的 html 和 js 代码加上加密…

LeetCode—和为K的子数组(前缀和)

题目描述 给你一个整数数组 nums 和一个整数 k &#xff0c;请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列。 示例 1&#xff1a; 输入&#xff1a;nums [1,1,1], k 2 输出&#xff1a;2示例 2&#xff1a; 输入&#xff1a;nums …

NodeJS校园快递智能互助平台-计算机毕业设计源码58554

摘 要 随着校园人口的增加和生活节奏的加快&#xff0c;校园快递成为一个重要的服务需求。然而&#xff0c;传统的校园快递方式存在一些问题&#xff0c;例如无法满足快速和高效的需求&#xff0c;易发生丢失或损坏的情况&#xff0c;同时也给快递人员和用户带来不便。因此&am…

SpringMVC(2)——controller方法参数与html表单对应(请求参数的绑定)

controller方法参数与html表单对应 规则 1. 绑定机制 表单提交的数据都是kv格式的 usernamehaha&password123SpringMVC的参数绑定过程是把表单提交的请求参数&#xff0c;作为控制器中方法的参数进行绑定的&#xff0c;要求&#xff1a;提交表单的name和参数的名称是相同…

使用“nvm use 版本号“命令无效

使用"nvm use 版本号"命令无效 为什么无效?解决 为什么无效? 解决 将这个nodejs文件夹删除,然后在运行nvm use 版本号,则 node生效.

HIVE启动报错HiveException java.lang.RuntimeException:

启动hive以后 我们输入SQL语句 会产生以下错误 FAILED: HiveException java.lang.RuntimeException: Unable to instantiate org.apache.hadoop.hive.ql.metadata.SessionHiveMetaStoreClient搜索解决办法发现是要开启元数据&#xff1a; hive --service metastore

【Python进阶】继承进阶和私有权限

目录 一、继承进阶 1、方法重写 2、调用父类方法 3、多层继承 二、私有权限 1、私有属性 2、私有方法 面向对象基础&#xff1a;小白也能看懂的Python基础教程&#xff08;8&#xff09;-CSDN博客 一、继承进阶 1、方法重写 当父类的同名方法达不到子类的要求&#x…

Drools开源业务规则引擎(六)- Drools Flow中RuleFlow文件即*.rf文件介绍

文章目录 Drools开源业务规则引擎&#xff08;六&#xff09;- RuleFlow文件即*.rf文件介绍1.\<header>1.1.\<imports>a.标签格式b.属性说明c.示例代码 1.2.\<globals>a.标签格式b.属性说明c.示例代码 1.3.\<functionImports>a.标签格式b.属性说明c.示…

怎么简单快捷的分享文件呢?扫描二维码看文件的制作方法

怎么简单快捷的分享文件呢&#xff1f;想要快速的实现文件分享&#xff0c;那么可以将文件转成二维码之后&#xff0c;通过分享二维码让其他人扫码在手机上查看文件&#xff0c;可以将单个文件或者多个文件生成二维码&#xff0c;扫描点击文件就能够在手机上预览或者下载文件。…

云开发技术的壁纸小程序源码,无需服务期无需域名

1、本款小程序为云开发版本&#xff0c;不需要服务器域名 2、文件内有图文搭建教程&#xff0c;小白也不用担心不会搭建。 3、本程序反应速度极快&#xff0c;拥有用户投稿、积分系统帮助各位老板更多盈利。 4、独家动态壁纸在线下载&#xff0c;给用户更多的选择 5、最新版套图…

概论(二)随机变量

1.名词解释 1.1 样本空间 一次具体实验中所有可能出现的结果&#xff0c;构成一个样本空间。 1.2 随机变量 把结果抽象成数值&#xff0c;结果和数值的对应关系就形成了随机变量X。例如把抛一次硬币的结果&#xff0c;正面记为1&#xff0c;反面记为0。有变量相对应的就有自…

智源打造基于Triton的大模型算子库,助力AI芯片软硬件生态建设

2024年大模型进入了新的发展阶段&#xff0c;AI全领域开启了更为迅猛的量变积累。一方面&#xff0c;模型突破了模态的隔离&#xff0c;文本、语音、视觉等各种形式之间产生的丰富的结合&#xff0c;大大增加了模态的多样性&#xff1b;同时&#xff0c;模型参数量从百亿、千亿…

60页论文参考:基于Java+SpringMvc+Vue技术的智慧校园系统设计与实现

详细查看地址&#xff1a; 基于JavaSpringMvcVue技术的智慧校园系统设计与实现-CSDN博客 基于JavaSpringMvcVue技术的智慧校园系统设计与实现 六、论文参考&#xff1a;

Linux初始化新的git仓库

1.在git服务器上找到项目常部署的git地址可以根据其他项目的git地址确认 例如ssh://git192.168.10.100/opt/git/repository.git 用户名&#xff1a;git&#xff08;前面的是用户&#xff09; 服务器地址&#xff1a;192.168.10.100 git仓库路径&#xff1a;/opt/git/ 2.在服务器…

4.2 存储管理

大纲 页式存储必考&#xff0c;段式存储看运气 页式存储 概念