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

文章目录

  • 第一部分 强化学习基础
    • 第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 pltclass 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=Kdef step(self, k):if np.random.rand() < self.probs[k]:return 1else:return 0np.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 npclass Solver:"""多臂老虎机解决方案抽象类"""def __init__(self, bandit):self.bandit = banditself.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 NotImplementedErrordef run(self, num_steps):# 运行一定次数,num_steps为总运行次数for _ in range(num_steps):k = self.run_one_step()self.counts[k] += 1self.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 npfrom Solver import Solverclass EpsilonGreedy(Solver):def __init__(self,bandit,epsilon=0.01,init_prob=1.0):super(EpsilonGreedy,self).__init__(bandit)self.epsilon = epsilonself.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 pltfrom BernoulliBandit import bandit
from EpsilonGreedy import EpsilonGreedydef 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 pltfrom BernoulliBandit import bandit
from EpsilonGreedy import EpsilonGreedydef 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 npfrom Solver import Solverclass EpsilonGreedy(Solver):def __init__(self, bandit, epsilon=0.01, init_prob=1.0):super(EpsilonGreedy, self).__init__(bandit)self.epsilon = epsilonself.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 kclass 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 = 0def run_one_step(self):self.total_count += 1if 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 pltfrom BernoulliBandit import bandit
from EpsilonGreedy import EpsilonGreedy, DecayingEpsilonGreedydef 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 npfrom Solver import Solverclass UCB(Solver):def __init__(self, bandit, c, init_prob=1.0):super(UCB, self).__init__(bandit)self.total_count = 0self.estimates = np.array([init_prob] * self.bandit.K)self.c = cdef run_one_step(self):self.total_count += 1ucb = 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 pltfrom BernoulliBandit import bandit
from EpsilonGreedy import EpsilonGreedy, DecayingEpsilonGreedy
from UCB import UCBdef 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 npfrom Solver import Solverclass 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] += rself._b[k] += (1 - r)return k

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

import numpy as np
from matplotlib import pyplot as pltfrom BernoulliBandit import bandit
from EpsilonGreedy import EpsilonGreedy, DecayingEpsilonGreedy
from ThompsonSampling import ThompsonSampling
from UCB import UCBdef 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 npnp.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.5def compute_return(start, chain, gamma):G = 0for i in reversed(range(start, len(chain))):G = gamma * G + rewards[chain[i] - 1]return Gchain = [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章 多智能体强化学习进阶

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【机器学习】必会数学知识:一文掌握数据科学核心数学知识点(上),值得收藏~

核心数学知识点 1、引言2、数据科学必会数学知识2.1 线性代数2.2 微积分2.3 概率论2.4 数理统计2.5 随机过程2.6 数据分布2.7 贝叶斯统计2.8 线性回归2.9 逻辑回归2.10 矩阵分解2.11 主成分分析&#xff08;PCA&#xff09;2.12 奇异值分解&#xff08;SVD&#xff09; 3、总结…

【人工智能大语言模型技术发展研究报告 2024】

文末‍有福利&#xff01; 人工智能作为引领新一轮科技产业革命的战略性技术和新质生产力重要驱动力&#xff0c;正在引发经济、社会、文化等领域的变革和重塑&#xff0c;2023 年以来&#xff0c;以 ChatGPT、GPT-4 为代表的大模型技术的出台&#xff0c;因其强大的内容生成及…

提升教师健康,聚焦智慧校园人事系统的职工体检功能

智慧校园人事管理系统内置的职工体检管理&#xff0c;是专为教职员工设计的一项健康管理创新实践&#xff0c;巧妙融合先进信息技术&#xff0c;致力于为教职工提供更加便捷、易懂且持续性的健康检查与管理支持。该服务从多个维度出发&#xff0c;全面呵护教职工的身心健康。 该…

给你的博客加上评论区

一个网站如果有评论功能&#xff0c;可以更好的和读者互动。VuePress 也有很多评论插件&#xff0c;这里简单介绍下&#xff0c;最后介绍本站所使用的 Twikoo。 大部分评论插件都是使用的 Github 或 Gitee 的 issue 功能&#xff0c;也就是用 issue 去存储评论&#xff1b;而 …

脚本实现保留文本中特定字符之后的字符串

#目的背景 原始txt文本如下图 目的是为了去除序号&#xff0c;每行只单独呈现域名 手工删除漫长又麻烦&#xff0c;使用脚本快捷些 代码实现逻辑&#xff1a; 1.使用open函数打开文本&#xff0c;之后用变量lines存储文本的所有行&#xff0c;使用for循环&#xff0c;让变量te…

暑假学习计划怎么做 用待办计划软件安排更科学

暑期来临&#xff0c;无论是学生还是老师&#xff0c;做好暑期计划都至关重要。记得去年暑假&#xff0c;我给自己定下了阅读十本书的目标&#xff0c;却因为缺乏明确的计划&#xff0c;最后只草草读完了两本。而今年&#xff0c;我决定尝试一种新的方式——使用待办计划软件来…

谷粒商城实战笔记-24-分布式组件-SpringCloud Alibaba-Nacos配置中心-命名空间与配置分组

文章目录 一&#xff0c;命名空间1&#xff0c;简介1.1&#xff0c;命名空间的主要功能和特点1.2&#xff0c;使用场景1.3&#xff0c;如何指定命名空间 2&#xff0c;命名空间实战2.1&#xff0c;环境隔离2.2&#xff0c;服务隔离 二&#xff0c;配置集三&#xff0c;配置集ID…

js原型和类---prototype,__proto__,new,class

原型和原型链 在js中&#xff0c;所有的变量都有原型&#xff0c;原型也可以有原型&#xff0c;原型最终都指向Object 什么是原型 在js中&#xff0c;一个变量被创建出来&#xff0c;它就会被绑定一个原型&#xff1b;比如说&#xff0c;任何一个变量都可以使用console.log打…

PostgreSQL 中如何实现数据的增量更新和全量更新的平衡?

文章目录 一、增量更新与全量更新的概念增量更新全量更新 二、考虑的因素1. 数据量2. 数据更改的频率和规模3. 数据一致性要求4. 系统性能和资源利用5. 业务逻辑和流程 三、解决方案&#xff08;一&#xff09;混合使用增量更新和全量更新&#xff08;二&#xff09;使用临时表…

暑期旅游季必备,用这款客服神器应对爆棚的客流咨询

解决暑期旅游客流高峰问题 暑期是旅游高峰季节&#xff0c;客流量剧增&#xff0c;客户咨询纷至沓来。在这个时候&#xff0c;如何高效处理客户的咨询成为每家旅游机构和景点不可忽视的挑战。 聊天宝快捷回复助手是一款强大的工具&#xff0c;可帮助企业在客流高峰期快速回复客…

MemFire Cloud: 一种全新定义后端即服务的解决方案

在这个快节奏的互联网时代&#xff0c;开发者们最希望的就是能够省时省力地完成项目&#xff0c;快速上线。然而&#xff0c;搭建服务、开发接口API、处理各种后端问题&#xff0c;往往让人头疼不已。别担心&#xff0c;现在有了MemFire Cloud&#xff0c;一款为懒人开发者量身…

制作电子名片的小程序系统源码 快速生成电子名片

在当今数字化时代&#xff0c;传统的纸质名片已逐渐被智能电子名片所取代。电子名片小程序作为一种基于微信生态的创新名片交换方式&#xff0c;凭借其便捷性、高效性和环保性&#xff0c;成为了众多商务人士的首选。小编分享一个制作电子名片的小程序系统源码&#xff0c;无忧…

malloc实现原理【Liunx】

malloc实现原理 malloc是什么&#xff1f;malloc,calloc, realloc的区别malloc的实现原理malloc的两种实现方式为什么使用brk&#xff1f;为什么使用mmap&#xff1f; malloc怎么定界的malloc分配的是虚拟内存上的空间吗&#xff1f; malloc是什么&#xff1f; 通过malloc&…

LinK3D: Linear Keypoints Representation for 3D LiDAR Point Cloud【翻译与解读】

LinK3D: Linear Keypoints Representation for 3D LiDAR Point Cloud 摘要 特征提取和匹配是许多机器人视觉任务的基本组成部分&#xff0c;如 2D 或 3D 目标检测、识别和配准。2D 特征提取和匹配已取得巨大成功。然而&#xff0c;在 3D 领域&#xff0c;当前方法由于描述性差…

2024前端面试题之Vue3

2024前端面试题之Vue3 在面试具有五年经验的前端工程师时&#xff0c;对于 Vue 3 的掌握程度是一个重要的考核点。本文将提供一系列针对这一级别工程师的 Vue 3 面试题&#xff0c;并附上详细的解析&#xff0c;帮助面试官全面评估候选人的技术实力和项目经验。 一、Vue 3 基础…

vscode-server安装和部分配置

文章目录 前言code-server安装rpm包安装tar.gz安装 vscode部分配置vscode配置函数跳转安装插件 vscode的structurevscode的hierarchy更改颜色主题 前言 vscode确实彳亍&#xff0c;虽然我觉得Clion(c/c语言版的IDEA)更方便&#xff0c;但是毕竟我没钱买license 这里记录一下网…

11410-00SF 同轴连接器

型号简介 11410-00SF是Southwest Microwave的连接器。该连接器的外壳采用优质不锈钢&#xff0c;材质为 CRES ALLOY UNS-S303500&#xff0c;符合 ASTM-A582 标准。首先&#xff0c;不锈钢材料经过锻造加工&#xff0c;形成转接器的基本形状。然后&#xff0c;外壳进行精密的 C…

CentOS7忘记root密码无法登陆解决方法

重启服务器&#xff0c;等到如图下所示界面的时候&#xff0c;快速按下键盘的↑或者↓按键&#xff0c;等固定住画面&#xff0c;然后按下e按键 然后按键盘上的↓按键&#xff0c;找到图下所示的linux16开头的那段&#xff0c;然后把光标挪到ro这里 按照图下所示&#xff0c;把…

提供跨平台的视觉安防解决方案,满足不同场景的需求的智慧交通开源了。

智慧交通视觉监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒&#xff0c;省去繁琐重复的适配流程&#xff0c;实现芯片、算法、应用的全流程组合&#xff0c;从而大大减少企业级应用约95%的开发成本。用户只需在界面上…

大气热力学(6)——位温和假相当位温

本篇文章源自我在 2021 年暑假自学大气物理相关知识时手写的笔记&#xff0c;现转化为电子版本以作存档。相较于手写笔记&#xff0c;电子版的部分内容有补充和修改。笔记内容大部分为公式的推导过程。 文章目录 6.1 位温6.2 斜 T-lnP 图&#xff08;Skew T-lnP&#xff09;6.2…