[強化学習] 実践的な強化学習: 多腕バンディット問題

強化学習マインドマップ

強化学習

序章

強化学習は、エージェントと環境の間の相互作用中の学習に焦点を当てており、試行錯誤学習 ( trial-and-error learning) パラダイムです。強化学習を正式に学習する前に、強化学習問題の簡易版とみなすことができるマルチアーム バンディット問題を理解する必要があります。強化学習とは異なり、マルチアーム スロット マシンには状態情報はなく、アクションと報酬のみが含まれます。これは、「環境との相互作用による学習」の最も単純な形式です多腕の盗賊における探索と搾取 ( explorationvs ) の問題exploitationは常に特に古典的な問題であり、それを理解することは強化学習を学ぶのに役立ちます。

  • エクスプロイトは、既知の最適な収益につながる決定を実行します。
  • 探索ではより多くの可能な決定を試みますが、必ずしも最適なリターンが得られるわけではありません

逐次決定問題を次のように形式化します。
探検
探索: より良い戦略を発見する可能性
探索して活用する

問題の導入

問題定義

マルチアーム バンディット (MAB) 問題 (図 2-1 を参照) では、K 個のレバーを備えたスロット マシンがあり、引かれる各レバーは、報酬に関する確率分布 R に対応しますレバーの 1 つを引くたびに、レバー に対応する報酬確率分布から報酬 r を得ることができます各レバーの報酬確率分布が不明な場合はゼロから試し、T レバーを操作した後にできるだけ高い累積報酬を獲得することを目標とします報酬の確率分布は不明であるため、「レバーの勝率を調べる」か「経験に基づいて最も多く獲得できるレバーを選択する」かのトレードオフを行う必要があります。どのような作戦戦略をとれば最も高い累積報酬を獲得できるか」が多腕盗賊問題です。
マルチアームスロットマシン

正式な説明

マルチアーム バンディット問題は確率論の古典的な問題であり、強化学習のカテゴリにも属しますギャンブラーが目の前に N 台のスロット マシンがあると想像してください。各スロット マシンの実際の利益は事前にわかりません。次にどのスロット マシンをプレイするか、各スロットの結果に基づいてギャンブルをやめるかをどのように選択すればよいでしょうか?禁欲の最終的な収益を最大化するためにマシンを使用します。

マルチアームバンディット問題は、タプル <A,R> として表すことができます。

  • A は一連のアクションであり、そのうちの 1 つはレバーを引くことを表します。マルチアーム スロット マシンに合計 K とレバーがある場合、アクション スペースは集合{ a 1 , ..., a K } \{a_1,...,a_K\} になります。{ _1... あるK},用at ∈ A a_t\in AあるA は任意のアクションを表します。
  • R は報酬確率分布、各レバーを引く動作はaaa は報酬確率分布R ( r ∣ a ) R(r|a)R ( r a )、異なるレバーの報酬分布は通常異なります。

各タイム ステップで 1 つのレバーのみを引くことができると仮定すると、マルチアーム バンディット マシンの目標は、タイム ステップ T での累積報酬を最大化することです。 max ∑ t = 1 T rt , rt ∈ R ( ⋅ ∣ at ) max \sum_{t =1}^T{r_t,r_t\in R(\cdot|a_t)}×t = 1TrrR ( a),其中 a t a_t あるttで表現タイムステップt 、 rt r_tでレバーを引く動作ra_t でのアクションを示しますある報酬。

ビジネスにおいて、多腕盗賊問題は、広告表示、医療実験、金融など、幅広い分野に応用されています。たとえば、レコメンド システムでは、N 個のアイテムがあり、N 個のアイテムに対するユーザー U の反応は事前にわかりません。ユーザーの価値を最大化するために、毎回特定のアイテムをユーザーに推奨する必要があります (または、試してみます)。ユーザー U を変換させるため)、ユーザーの購入など。

積み重なる自責の念

アクションごとにaaa ,我们定义其期望奖励为 Q ( a i ) = E r ∼ R ( r ∣ a i ) [ r ∣ a i ] Q(a^i)=\mathbb{E}_{r \sim \mathcal{R}(r\mid a^i)}[r|a^i] Q ( _=Er R ( r a[ r a]したがって、期待される報酬が他のレバーを引くことよりも小さくないレバーが少なくとも 1 つ存在し、最適な期待される報酬は次のように表されます。Q ∗ = max ⁡ ai ∈ AQ ( ai ) Q^{*}=\max _ {a ^i \in \mathcal{A}} Q(a^i)Q=あるiAマックスQ ( _レバーを引くことで期待される報酬と、レバーを引くことによる最適な報酬との間のギャップをより直観的かつ便利に観察するために、後悔(regret)。後悔は、現在のレバーを引くアクションとして定義されますaと最適レバーの期待報酬の差、つまりR ( ai ) = Q ∗ − Q ( ai ) R(a^i)=Q^{*}-Q(a^i)R ( _=QQ ( _溜まった後悔(cumulative regret)は作戦TT完全なTTで、 T がプルされた後に蓄積された後悔の合計量T步决策{ a 1 , a 2 , … , a T } \left\{a_{1}, a_{2}, \ldots, a_{T}\right\}{ _1ある2あるT},累積积懊悔はσ R = E a 〜 π [ ∑ t = 1 TR ( ati ) ] \sigma_{R}=\mathbb{E}_{a\sim \pi}[\sum_{t=1}^ {T} R\left(a_{t}^i\right)]pR=Ea〜π _ _[t = 1TR( _t私は) ]MAB 問題の目標は、累積報酬を最大化することです。これは、累積後悔を最小化することと同じです。つまり、min σ R = max E a 〜 π [ ∑ t = 1 TQ ( ati ) ] \text{min } \ sigma_R=\text{max } \mathbb{E}_{a\sim \pi}[\sum_{t=1}^TQ(a_t^i)]最小 時間R=最大 Ea〜π _ _[t = 1TQ ( _t私は)]時間が経つにつれて、後悔の総量はどんどん小さくなるはずですが、探索は常に必要なのでしょうか?

新しい戦略を探索し続けると: KaTeX 解析エラー: 未定義の制御シーケンス: 位置 9 の \proptoT: \sigma_R\̲p̲r̲o̲p̲t̲o̲T̲\cdot R、総後悔は直線的に増加し、収束できません;
新しい戦略を探索していない場合: σ R ∝ T ⋅ R \sigma_R\propto T\cdot RpRTR、合計の後悔は直線的に増加します。

線形未満の収束保証で後悔する方法はありますか?
下限

期待される報酬の見積もり

より高い報酬を得るためにどのレバーを引くべきかを知るためには、そのレバーを引くことで期待される報酬を見積もる必要があります。レバーを1回引いた場合に得られる報酬はランダムであるため、複数回レバーを引いて得られる複数の報酬の期待値を計算する必要があります。

  • 对于 ∀ a ∈ A \forall a \in \mathcal{A} ∀a _A、カウンターを初期化しますN ( a ) = 0 N(a)=0=0および期待される報酬評価Q ^ ( a ) = 0 \hat{Q}(a)=0Q^( a )=0
  • for t = 1 → T t=1 \rightarrow Tt=1する_
    • タイロッドを選択します。このアクションはa_{t}として記録されます。ある
    • 報酬を受け取りますrt r_{t}r
    • 更新数器: N ( at ) = N ( at ) + 1 N\left(a_{t}\right)=N\left(a_{t}\right)+1N( _)=N( _)+1
    • 更新期待奖励估值: Q ^ ( at ) = Q ^ ( at ) + 1 N ( at ) [ rt − Q ^ ( at ) ] \hat{Q}\left(a_{t}\right)=\hat {Q}\left(a_{t}\right)+\frac{1}{N\left(a_{t}\right)}\left[r_{t}-\hat{Q}\left(a_{ t}\右)\右]Q^( _)=Q^( _)+N ( _)1[ rQ^( _) ]
  • 終わります

上記の for ループの 4 番目のステップは、増分期待値更新を実行できるため、この方法で評価を更新します。式は次のとおりです:
Q k = 1 k ∑ i = 1 kri = 1 k ( rk + ∑ i = 1 k − 1 ri ) = 1 k ( rk + ( k − 1 ) Q k − 1 ) = 1 k ( rk + k Q k − 1 − Q k − 1 ) = Q k − 1 + 1 k [ rk − Q k − 1 ] Q_k=\frac{1}{k}\sum_{i=1}^kr_i=\frac{1}{k}(r_k+\sum_{i=1}^{k−1}r_i)=\frac {1}{k}(r_k+(k−1)Q_{k−1})=\frac{1}{k}(r_k+kQ_{k−1}−Q_{k−1})=Q_{k −1}+\frac{1}{k}[r_k−Q_{k−1}]Q=k1i = 1r私は=k1( r+i = 1k 1r私は)=k1( r+( k1 ) Qk 1)=k1( r+kQ _k 1Qk 1)=Qk 1+k1[ rQk 1]

すべての数値を合計して回数で割ると、各更新の時間計算量と空間計算量がO ( n ) O(n)になるという欠点があります。O ( n )増分更新では、時間計算量と空間計算量は両方ともO ( 1 ) O(1)( 1 )

以下に、10 個のレバーを備えたマルチアーム スロット マシンを実装するコードを記述します。各レバーを引くことに対する報酬はベルヌーイ分布 ( Bernoulli distribution) に従います。つまり、レバーを引くたびにppが与えられます。確率pで得られる報酬は1 11. 1 − p 1-pがあります1確率pで得られる報酬は0 00報酬は1 11 は勝利を意味し、報酬は0 00 は賞なしを意味します。

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):
        # 当玩家选择了k号拉杆后,根据拉动该老虎机的k号拉杆获得奖励的概率返回1(获奖)或0(未获奖)
        if np.random.rand() < self.probs[k]:
            return 1
        else:
            return 0

の結果
次に、ソルバー基本クラスを使用して、上記のマルチアーム スロット マシン ソリューションを実装します。前述のアルゴリズム フローによれば、次の機能を実装する必要があります:戦略に従ってアクションを選択し、アクションに従って報酬を取得し、期待される報酬の評価を更新し、累積された後悔とカウントを更新しますrun_one_step()以下の MAB アルゴリズムの基本フレームワークでは、戦略に従ってアクションを選択し、アクションに従って報酬を取得し、継承された各クラスの戦略によってSolver実装される関数内の期待報酬評価を更新します。更新中、累積後悔とカウントはrun()メイン ループに直接配置されます。

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)

貪欲な戦略とϵ \epsilonϵ -貪欲な戦略

完全に貪欲なアルゴリズムは、各瞬間に最大の期待報酬値を伴うアクションを実行することであり、探索を行わずに純粋に利用することになります。したがって、通常は完全に貪欲なアルゴリズムにいくつかの変更を加える必要があります。より古典的な方法はϵ \epsilonです。ϵ -貪欲な行動。ϵ \epsilonϵ -greedy アルゴリズムは、毎回 1-ϵ \epsilonϵ確率ϵ \epsilonで、忘れられた経験の中で最大の期待報酬値を持つレバー (利用率) を選択します。ϵ はレバー (探索) をランダムに選択します。貪欲な戦略とϵ \epsilonϵ貪欲戦略は次
貪欲な戦略の比較
比較されます。ϵ -greedy 戦略の具体的な実装では、ϵ \epsilonϵ は時間とともに減衰します。つまり、探索の確率は減少し続けます。しかし、ϵ \epsilon限られたステップ数内でϵ が0 に減衰することはありません。これは、限られたステップ数での観測に基づく完全に貪欲なアルゴリズムであっても、局所的な情報を伴う貪欲なアルゴリズムであり、最適解からの距離が常に固定されているためです。
朽ち果てた貪欲な戦略
この欠点は、適切な減衰計画を見つけるのが難しいことです。

異なるϵ \epsilonϵ -greedy 戦略の比較: Total Regret
まったくの後悔
上の図は、基本的にϵ \epsilonϵの値が何であっても、累積された後悔は直線的に増加します。ϵ \epsilonの場合ϵが増加すると、累積後悔の増加率も増加します。

次にϵ \epsilonを試してみましょうϵの値は時間とともに減衰しますϵ \epsilonϵgreedyアルゴリズム。採用される特定の減衰形式は反比例減衰です。式はϵ t = 1 t \epsilon_t=\frac{1}{t}ϵ=t1

class DecayingEpsilonGreedy(Solver):
    """epsilon值随时间衰减的epsilon贪心算法,继承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:  # 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

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

朽ちていく
図からわかるように、時間の経過とともに減衰するϵ \epsilonϵ貪欲アルゴリズムは、累積リグレスとタイム ステップの間の関係を線形以下にすることができ、これは固定ϵ \epsilonϵϵ \epsilonϵ貪欲なアルゴリズム。

信頼限界アルゴリズムの上限

レバーの不確実性が大きければ大きいほど、探索の価値は高くなります。これは、探索後のレバーの発見によって期待される報酬が大きいためです。不確実性尺度の導入U ( a ) U(a)U ( a )。アクションの試行回数が増えるにつれて減少します。不確実性ベースの戦略は、既存の期待報酬評価と不確実性を総合的に考慮するために使用できますが、中心的な問題は不確実性をどのように推定するかです。

上限信頼限界 (UCB) アルゴリズムは、古典的な不確実性ベースの戦略アルゴリズムであり、その考え方には、非常に有名な数学原理である Hoeffding の不等式 (Hoeffding の不等式) が使用されています。Hoeffding の不等式では、X 1 , ..., X n X_1,...,X_nとします。バツ1... バツは n 個の独立した同一分布の確率変数であり、値の範囲は [0,1]、その経験的期待値はx ˉ n = 1 n ∑ j = 1 ∗ X j \bar{x}_n=\frac{1}{ n}\sum_{j=1}^*X_jバツˉ=n1j = 1バツj,有: P ( E [ X ] ≥ x ˉ n + u ) ≤ e − 2 nu 2 P(E[X]\ge \bar{x}_n+u)\le e^{-2nu^2}P ( E [ X ]バツˉ+e−2 n u _2

確率論では、ヘフディングの不等式は確率変数の合計が期待値から外れる確率の上限を与えます。この不等式は 1963 年にワシリー ヘフディングによって提案され、証明されました。Hoeffding 不等式は、Azuma-Hoeffding 不等式の特殊なケースであり、1923 年に Sergei Bernstein によって証明された Bernstein 不等式よりも一般的です。これらの不等式は、マクダーミッドの不等式の特殊なケースです。

Q ^ ( at ) \hat{Q}(a_t)Q^( _) x ˉ t \bar{x}_tバツˉ、不等式のパラメータu = U ^ ( at ) u=\hat{U}(a_t)あなた=U^ (_)は不確実性の尺度を表します。確率が与えられると、p = e − 2 N ( at ) U ( at ) 2 p=e^{-2N(a_t)U(a_t)^2}p=e2N ( a _) U ( _)2、上記の不等式によれば、Q ( at ) < Q ^ ( at ) + U ^ ( at ) Q(a_t)<\hat{Q}(a_t)+\hat{U}(a_t)Q ( _)<Q^( _)+U^ (_)は少なくとも確率 1-p で成り立ちます。p が小さい場合、Q ( at ) < Q ^ ( at ) + U ^ ( at ) Q(a_t)<\hat{Q}(a_t)+\hat{U}(a_t)Q ( _)<Q^( _)+U^ (_)が高い確率で成立する、Q ^ ( at ) + U ^ ( at ) \hat{Q}(a_t)+\hat{U}(a_t)Q^( _)+U^ (_)は、前のセッションに報酬を与える期待値です。このとき、信頼限界アルゴリズムの上限は、前のセッションで期待される報酬が最も大きいアクションを選択します。つまり、a = arg max ⁡ a ∈ A [ Q ^ ( a ) + U ^ ( a ) ] a=arg \ max_{a\in A}[ \hat{Q}(a)+\hat{U}(a)]ある=a r g最大a A[Q^( a )+U^(a)]。那其中 U ^ ( a ) \hat{U}(a) U^ (a)とは何ですか方程式によれば、p = e − 2 N ( at ) U ( at ) 2 p=e^{-2N(a_t)U(a_t)^2}p=e2N ( a _) U ( _)2 の場合、解はU ^ ( at ) = − logp 2 N ( at ) \hat{U}(a_t)=\sqrt{\frac{-log p}{2N(a_t)}} です。U^ (_)=2N ( a _)ログページ_ _ したがって、確率 p を設定した後、対応する不確実性尺度U ( at ) ^ \hat{U(a_t)} を計算できます。_)^上。

UCB アルゴリズムは、各プル ロッドを選択する前に、まず各プル ロッドの期待される報酬の上限を推定します。これにより、各プル ロッドを引くことで期待される報酬がこの上限を超える確率はわずかになり、その後、プル ロッドを選択します。最大の期待報酬上限を設定して、最大の期待報酬を獲得する可能性が最も高いレバーを選択します。

UCB アルゴリズムを実装するコードを作成します。実装のプロセスでは、p = 1 tp=\frac{1}{t}と設定します。p=t1、各タイロッドを引く回数の分母に定数 1 を加えて、分母が 0 になる状況、つまりU ^ ( at ) = log ⁡ t 2 ( N ( at ) になることを回避します。 + 1 ) \hat{U }(a_t)=\sqrt{\frac{\log t}{2(N(a_t)+1)}}U^ (_)=2 ( N ( a) + 1 )ログ_ _ 同時に係数ccを設定しますcで不確実性の割合を制御します。このとき、at = arg max ⁡ a ∈ A [ Q ^ ( a ) ] a_t=arg\max_{a\in A}[\hat{Q}(a)]ある=a r g最大a A[Q^( a )]

class UCB(Solver):
    """ UCB算法,继承Solver类 """

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

    def run_one_step(self):
        self.total_count += 1
        ucb = self.estimates + self.coef * 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


np.random.seed(1)
coef = 1  # 控制不确定性比重的系数
UCB_solver = UCB(bandit_10_arm, coef)
UCB_solver.run(5000)
print('上置信界算法的累积懊悔为:', UCB_solver.regret)
plot_results([UCB_solver], ["UCB"])

UCB

トンプソンサンプリングアルゴリズム

MAB には古典的なアルゴリズム、トンプソン サンプリング (トンプソン サンプリング) もあります。これは、最初に各レバーを引くことによる報酬が特定の確率分布に従うと仮定し、次に各レバーを引くことで期待される報酬に応じて選択しますただし、すべてのレバーの期待される報酬を計算するコストが高いため、トンプソン サンプリング アルゴリズムはサンプリングを使用します。つまり、現在の各アクションに従ってaの報酬確率分布に対して一連のサンプリングを実行して、各レバーの一連の報酬サンプルを取得し、サンプル内で最大の報酬を持つアクションが選択されます。

トンプソン サンプリングは、すべてのレバーに対して最高の報酬確率を計算するモンテカルロ サンプリング手法です

実際には、通常、ベータ分布は各アクションの現在の報酬確率分布をモデル化するために使用されます。具体的には、レバーが k 回選択された場合、ここでm 1 m_1メートル1二次報酬は 1, m 2 m_2ですメートル2二次報酬が 0 の場合、レバーの報酬従順パラメーターは( m 1 + 1 , m 2 + 1 ) (m_1+1, m_2+1) となります。( m1+1 メートル2+1 )ベータ版の配布。

ベータ分布は連続確率密度分布であり、x 〜 B eta ( a , b ) x\sim Beta(a, b)で表されます。バツベータ( a , _ _ _b )は、形状パラメータと呼ばれる 2 つのパラメータ a、b によって決定されます。その定義域は (0,1) であるため、一般にベルヌーイ試行イベントの成功確率の確率分布をモデル化するために使用されます。簡単に言えば、ベータ分布は確率の確率密度分布とみなすことができ、何かの具体的な確率がわからない場合、すべての確率が現れる可能性を与えることができます。

class ThompsonSampling(Solver):
    """汤普森采样算法,继承Solver类"""
    def __init__(self, bandit):
        super(ThompsonSampling, self).__init__(bandit)
        self._a = np.ones(self.bandit.K)  # 列表,表示每根拉杆奖励为1的次数
        self._b = np.ones(self.bandit.K)  # 列表,表示每根拉杆奖励为0的次数

    def run_one_step(self):
        samples = np.random.beta(self._a, self._b)  # 按照Beta分布采样一组奖励样本
        k = np.argmax(samples)  # 选出采样奖励最大的拉杆
        r = self.bandit.step(k)

        self._a[k]  += r  # 更新Beta分布的第一个参数
        self._b[k] += (1-r)  # 更新Beta分布的第二个参数
        return k

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

トンプソンサンプリング
実験を通じて次の結論が導き出されます:
ϵ \epsilonϵ -greedy アルゴリズムの累積的反省は時間とともに直線的に増加しますが、他の 3 つのアルゴリズム (ϵ \epsilonϵ - 減衰貪欲アルゴリズム、上限信頼限界アルゴリズム、トンプソン サンプリング アルゴリズム) 累積後悔は時間とともに線形未満 (具体的には対数的に) 増加します。

参考文献

  1. 「実践的な集中学習」Zhang Weinan、Shen Jian、Yu Yong 著
  2. 張偉南氏による「ElitesAI 強化学習」講演
  3. 機械学習の数学的原理 (8) - ホッファーディング不等式
  4. ベータ分布の深い理解: 定義から式の導出まで

おすすめ

転載: blog.csdn.net/ARPOSPF/article/details/129756783