強化學習——多臂老虎機問題(MAB)【附python代碼】

文章目錄

  • 一、問題描述
    • 1.1 問題定義
    • 1.2 形式化描述
    • 1.3 累積懊悔
    • 1.4 估計期望獎勵
  • 二、解決方法
    • 2.1 ?-貪婪算法
    • 2.2 上置信界算法
    • 2.3 湯普森采樣算法
    • 2.4 小結

一、問題描述

1.1 問題定義

??有一個用于 K 根拉桿的老虎機,每一根拉桿都對應一個關于獎勵的概率分布 R 。每拉動一個拉桿,就可以從該拉桿的獎勵概率分布中獲得一個獎勵 r 。在各拉桿的獎勵概率分布未知的情況下,從頭開始嘗試,目標是在操作 T 次拉桿后獲得盡可能高的累積獎勵。

??由于獎勵的概率分布是未知的,因此我們需要在“探索拉桿的獲獎概率”和“根據經驗選擇獲獎多的拉桿”中進行權衡。

【通俗易懂:有 K 個機器,你不知道每個機器的獎勵概率分布,你只有 T 次機會選擇機會,探索機器的獎勵概率分布也算在 T 次內,然后盡可能獲得最多的獎勵。】

【示例:有 1 個 10 臂老虎機,你有 20 次選擇機會,你可以花 10 次機會探索前 5 臂,根據獲得的獎勵,選擇獎勵期望最大的一個,剩下 10 次都選擇最大的那 1 臂。(有可能獎勵期望最大在沒有探索的 5 臂中,也有可能在前 5 臂中,但是不是你選擇的那個)】

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 at?A 表示任意一個動作;
  • 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=1T?rt?,rt?R(?at?)。其中 a t a_t at? 表示在第 t 時間步拉動某一拉桿的動作, r t r_t rt? 表示動作 a t a_t at? 獲得的獎勵。

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?=maxaA?Q(a)

  • 懊悔:當前動作 a 與最優拉桿期望獎勵的差距,即 R ( a ) = Q ? ? Q ( a ) R(a)=Q^*-Q(a) R(a)=Q??Q(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=1T?R(at?)

??所以求解 MAB 問題等價于最小化累積懊悔

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?[rt??Q^?(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)

配置 numpy 和 matplotlib 模塊

訪問文章:配置 numpy 和 matplotlib 模塊

二、解決方法

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?={argaAmax?Q^?,采樣概率: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 上置信界算法

??對于多臂老虎機來說,一根拉桿的探索次數較少,它的不確定性就很高。不確定越高,它具有的探索價值就越大。為此,引入不確定性度量 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ˉ=n1?j=1n?Xj? ,則有 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)e?2nu2

??將霍夫丁不等式運用到多臂老虎機問題中。 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=e?2N(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 1?p 成立,當 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=e?2N(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)+c?U^(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.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.4 小結

算法累積懊悔與時間步的關系
ε-貪婪算法線性
ε-衰減貪婪算法次線性(對數)
上置信界算法次線性(對數)
湯普森采樣算法次線性(對數)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/45985.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/45985.shtml
英文地址,請注明出處:http://en.pswp.cn/web/45985.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【C++題解】1154. 數組元素的查找

問題&#xff1a;1154. 數組元素的查找 類型&#xff1a;數組找數 題目描述&#xff1a; 給你 m 個整數&#xff0c;查找其中有無值為 n 的數&#xff0c;有則輸出該數第一次出現的位置,沒有則輸出 ?1 。 輸入&#xff1a; 第一行一個整數 m 代表數的個數 ( 0≤m≤100 ) 。…

Qt基礎 | Qt全局定義 | qglobal頭文件中的數據類型、函數、宏定義

文章目錄 一、數據類型定義二、函數三、宏定義 QtGlobal頭文件包含了 Qt 類庫的一些全局定義 &#xff0c;包括基本數據類型、函數和宏&#xff0c;一般的Qt類的頭文件都會包含該文件。 詳細內容可參考&#xff1a;https://doc.qt.io/qt-5/qtglobal.html 一、數據類型定義 為了…

數據可視化在智慧醫療中的重要應用

在現代智慧醫療的推動下&#xff0c;數據可視化技術正日益成為醫療領域的重要工具。通過將復雜的醫療數據轉換為直觀的圖表和圖形&#xff0c;數據可視化不僅提升了醫療服務的效率&#xff0c;還極大地改善了患者的就醫體驗。 在智慧醫療中&#xff0c;數據可視化首先在電子病歷…

客流統計系統優化景區服務流程,增強游客滿意度

在當今旅游業蓬勃發展的時代&#xff0c;景區面臨著越來越多的挑戰和機遇。如何提供更優質、更高效的服務&#xff0c;滿足游客日益增長的需求&#xff0c;成為了景區管理者們關注的焦點。客流統計系統作為一種創新的技術手段&#xff0c;正逐漸成為優化景區服務流程、增強游客…

MySQL主從同步的原理與思考

摘要 分析主從同步出現的原因&#xff0c;MySQL實現主從同步的原理&#xff0c;思考實現原理的局限性和優點 背景 在實際應用中主從同步常用于實現備份、負載均衡和高可用。數據冗余的目的是提高數據的安全性&#xff0c;避免因磁盤損壞導致數據丟失的問題。讀寫分離的目的是…

ubuntu系統Docker常用命令

1.查看docker是否開機啟動 sudo systemctl list-unit-files | grep enable|grep docker 2.設置開機啟動 sudo systemctl enable docker 3.關閉docker開機啟動 sudo systemctl disable docker 4.開啟docker服務 sudo service docker start 5.關閉docker服務 sudo servi…

基于CNN的MINIST手寫數字識別項目代碼以及原理詳解

文章目錄 項目簡介項目下載地址項目開發軟件環境項目開發硬件環境前言一、數據加載的作用二、Pytorch進行數據加載所需工具2.1 Dataset2.2 Dataloader2.3 Torchvision2.4 Torchtext2.5 加載項目需要使用的庫 三、加載MINIST數據集3.1 數據集簡介3.2 數據預處理3.3 加載數據集 四…

2.10、matlab中字符、數字、矩陣、字符串和元胞合并為字符串并將字符串以不同格式寫入讀出excel

1、前言 在 MATLAB 中&#xff0c;可以使用不同的數據類型&#xff08;字符、數字、矩陣、字符串和元胞&#xff09;合并為字符串&#xff0c;然后將字符串以不同格式寫入 Excel 文件。 以下是一個示例代碼&#xff0c;展示如何將不同數據類型合并為字符串&#xff0c;并以不…

重生奇跡mu魔法師瞬間移動技能

瞬間移動是勇士大陸魔法師所擁有的一項技能。一開始&#xff0c;許多玩家對這種技能的用處感到困惑。實際上&#xff0c;這種技能只能在游戲中不同的位置間進行移動&#xff0c;不能隨機傳送到地圖的其他坐標位置。 一位重生奇跡mu魔法師在PK中不小心使用了一項技能&#xff0c…

【仿真建模-anylogic】數據源組件

Author&#xff1a;趙志乾 Date&#xff1a;2024-07-16 Declaration&#xff1a;All Right Reserved&#xff01;&#xff01;&#xff01; 1. 簡介 仿真模型依賴的數據源通常有Excel文件、MySQL數據庫兩種&#xff1b;針對小數量、大數據量以及是否允許外部依賴等場景設計了一…

labview使用斑馬打印機打印標簽

使用ZebraDesigner 3設計標簽樣式 設計完成后打印至文件&#xff0c;生成prn文件 用記事本打開prn文件 ^MMT 標簽撕下 ^MMP 標簽剝離 按照需求替換FD--------^FS中間內容

路由上傳一個ui_control參數(uint32類型)控制頁面UI顯隱

前言&#xff1a;傳一個uint32類型的值&#xff0c;通過 按位或操作符&#xff08;|&#xff09;來設置ui_control的值&#xff0c;通過按位與操作符&#xff08;&&#xff09;來檢測是否顯示或隱藏 簡單介紹一下兩個概念&#xff1a; 按位與操作符和按位或操作符都是二進…

etcd的備份與恢復

一 為什么使用etcd 與ZooKeeper相比&#xff0c;etcd更簡單&#xff0c;安裝、部署和使用更加容易&#xff0c;并且etcd的某些功能是ZooKeeper所沒有的。因此&#xff0c;在很多場景下&#xff0c;etcd 比ZooKeeper更受用戶的青&#xff0c;具體表現在如下幾個方面: 1 etcd更…

上海市計算機學會競賽平臺2022年10月月賽丙組門禁記錄

題目描述 小愛得到了某大樓一天內按時間順序記錄的&#x1d45b;n條門禁出入記錄&#xff0c;每條記錄由兩個字符串組成&#xff0c;第一個字符串為出入人員姓名&#xff0c;第二個字符串表示該人員進出狀態、為 enter 或 exit 中一項&#xff0c;其中 enter 為進入&#xff0…

鑫創SSS1700USB音頻橋芯片USB轉IIS芯片

鑫創SSS1700支持IIC初始外部編&#xff08;EEPROM選項),兩線串行總線&#xff08;I2C總線&#xff09;用于外部MCU控制整個EEPROM空間可以通過MCU訪問用于主機控制同步的USB HID外部串行EEPROM&#xff08;24C02~24C16&#xff09;接口&#xff0c;用于客戶特定的USB視頻、PID、…

jmeter之變量隨機參數化以及解決多線程不會隨機變化

參考鏈接&#xff1a; https://www.cnblogs.com/Testing1105/p/12743475.html jmeter 使用random函數多線程運行時數據不會隨機變化&#xff1f;_jmeter 線程組循環執行時 變量不變-CSDN博客 1、如下圖所示&#xff0c;需要對請求參數 autor 和phone進行隨機參數化 2、目前有…

MyBatis源碼中的設計模式2

組合模式的應用 組合模式介紹 組合模式(Composite Pattern) 的定義是&#xff1a;將對象組合成樹形結構以表示整體和部分的層次結構。組合模式可以讓用戶統一對待單個對象和對象的組合。 比如&#xff1a;Windows操作系統中的目錄結構&#xff0c;通過tree命令實現樹形結構展…

【系統架構設計師】十二、系統質量屬性與架構評估(開發期質量屬性|運行期質量屬性|面向架構評估的質量屬性|質量屬性效用樹|質量屬性場景)

目錄 一、軟件系統質量屬性 1.1 開發期質量屬性 1.2 運行期質量屬性 1.3 面向架構評估的質量屬性 1.4 質量屬性效用樹 1.5 質量屬性場景 1.5.1 可用性質量屬性場景描述 1.5.2 可修改性質量屬性場景描述 1.5.3 性能質量屬性場景描述 相關推薦 歷年真題練習 歷…

【vue】輸入框和文本域切換

輸入框的樣子 文本域的樣子 當輸入框出現滾動條的時候&#xff0c;就自動切換成文本域&#xff1b;當文本域到1行并且寬度小于輸入框寬度時切換成輸入框 <div class"left_box_inpt"><divclass"right_box_inpt":class"{notclickable: inputd…

OpenResty使用Lua筆記

文章目錄 一、基礎1、常用2、使用局部變量3、模塊化 二、性能提升1、使用fft調用shell2、不要在循環中拼接字符串3、不要頻繁修改table4、不要在table中用nil5、做好異常處理6、ngx.var 的性能提升 三、拓展1、加載字符串為動態方法 一、基礎 1、常用 OpenResty 中文官網&…