今年 Kaggle コンペティションで DeepSeek-Math-7B-RL モデルを使用し、学習時に Claude 3.5 Sonnet を教師として使いました。この 2 つのモデルが強力である理由は、どちらも RL に依存しているからです。この分野の技術が非常に強力で美しいと感じ、少し触れてみることにしましたが、基礎が不十分で理解できず、OpenAI Spinning Up を理解できなかったため、HuggingFace DeepRLのような入門コースを軽く試すことにしました。
導入#
強化学習の理念は、エージェント(AI)が環境と相互作用し(試行錯誤を通じて)、報酬(正のものまたは負のもの)を得ることで行動のフィードバックを受け取り、環境から学ぶというものです。
- エージェントは環境から最初のフレームを取得し、状態を受け取り、に基づいてエージェントは行動(例えば右に進む)を取ります。環境は新しいフレーム(新しい状態)に移行し、環境はエージェントに一定の報酬(例えば死亡しなかった場合の + 1 の正の報酬)を与えます。
エージェントの目標は累積報酬を最大化することであり、これを期待報酬と呼びます。
報酬仮説:強化学習の核心思想#
強化学習は報酬仮説に基づいており、すべての目標は期待報酬の最大化(期待累積報酬)として記述できます。強化学習では、最適な行動を得るために、私たちの目標は期待累積報酬を最大化する行動を取ることを学ぶことです。
タスクは 2 つのカテゴリに分かれます#
-
エピソディック:開始点と終了点があります。(ゲームレベル)
-
連続:開始点はありますが、終了点はありません。(自動運転)
状態と観測の違いは何ですか?#
- 状態は世界の状態の完全な記述です(隠れた情報は存在しません)、例えばチェスボードのように。
- 観測は状態の部分的な記述です、例えばマリオゲームの視点のように。
ポリシーベースの手法#
この方法では、ポリシーは直接学習されます。
各状態をその状態での最適な対応行動、またはその状態での可能な行動セットの確率分布にマッピングします。
バリューベースの手法#
ポリシーを訓練するのではなく、各状態をその状態の期待価値にマッピングする価値関数を訓練します。
探索 / 利用のトレードオフ#
強化学習では、環境の探索の程度と既知の環境情報の利用の程度をバランスさせる必要があります。
何が深いのか?#
深層ニューラルネットワークを強化学習の問題解決に導入しました。
実践例 - HUGGY#
Colab を直接使用することをお勧めします。WSL2 で実行する場合は、仮想ディスプレイの設定を行う必要があります:
import os
os.environ['PYVIRTUALDISPLAY_DISPLAYFD'] = '0'
from pyvirtualdisplay import Display
display = Display(visible=0, size=(1400, 900))
display.start()
状態空間#
Huggy に私たちが投げた棒を拾わせるために訓練します。これは、Huggy が正しく棒に向かって移動する必要があることを意味します。
提供される環境情報:
- 目標(棒)の位置
- 目標との相対位置
- 彼の両足の向き。
これらの情報に基づいて、Huggy はポリシーを利用して、目標を達成するために次に何をするかを決定します。
行動空間#
Huggy が実行できる行動
関節モーターが Huggy の脚を駆動します。
したがって、目標を達成するために、Huggy は各脚の関節モーターを正しく回転させて移動する方法を学ぶ必要があります。
報酬関数#
したがって、私たちの報酬関数は:
- 方向報酬:目標に近づくことに対する報酬。
- 目標達成報酬:Huggy が目標を達成したときに報酬を与えます。
- 時間ペナルティ:各行動時に与えられる固定の時間ペナルティ、できるだけ早く棒に到達することを強制します。
- 回転ペナルティ:過度の回転と速すぎる回転に対するペナルティ。
Q-Learning の紹介#
バリューベース
- 状態 s から始めて、私たちはポリシーに従って行動します。
- 未来の報酬を累積しますが、遠くの報酬は割引因子によってその影響が減少します。
- 価値関数は、現在の状態から始めたときの全未来の「報酬」の期待値を計算します。
RL エージェントの目標は最適なポリシーを持つことです。
価値とポリシーの関係#
最適な価値関数を見つけることで最適なポリシーを導出できます。
- :最適ポリシーを示し、状態で取るべき最良の行動。
- :状態 - 行動価値関数を示し、状態で行動を選択したときの未来のすべての可能な割引報酬の期待値。
- :を最大化する行動を選択することを示します。つまり、期待報酬を最大化する行動を見つけること。
この公式の核心的な考え方は、最適な関数があれば、を最大化する行動を選択することで最適ポリシーを決定できるということです。つまり、最適ポリシーは各状態で未来の期待報酬を最大化する行動を選択することです。
2 つのバリューベース手法#
ネズミが迷路でチーズを探すシーンを想像してください:
- 状態価値関数は、ネズミがある位置(状態)にいるときの気分の期待を表します。「ここから私のポリシーに従って行動した場合、チーズを見つける確率はどれくらいですか?」
- 行動価値関数はさらに進みます。「ここから出発し、右に移動することを選択した場合、成功する確率はどれくらいですか?」行動価値関数は、ネズミが各状態で異なる行動の効果を評価するのに役立ち、よりターゲットを絞った行動の選択を可能にします。
1. 状態価値関数(State Value Function)#
状態価値関数は、特定のポリシーの下で、与えられた状態から出発したときに期待される累積報酬を評価します。言い換えれば、これは「もし私が今状態にいて、ポリシーに従った場合、私の長期的な利益はどれくらいになるか」を測定します。
- :状態の価値、すなわちから出発し、ポリシーに従って期待される累積報酬。
- :時間ステップからの累積報酬で、通常はと表され、は割引因子です。
- :ポリシーの下での期待を示します。
迷路があると仮定し、ネズミがある位置(状態)から始まり、チーズを探すために何らかのポリシーに従うとします。状態価値関数は、ネズミが現在の位置から始めた場合、チーズを見つけるのにどれくらいの時間がかかるかを教えてくれます。
上の図の例では、各マスの数値は特定の状態の価値を示しています。例えば、状態の値がである場合、ネズミがここから始めたときの期待される累積報酬は悪いことを意味します(チーズから遠い可能性があるため)。チーズに近い状態(値がなど)は、より良い期待報酬を持っています。
2. 行動価値関数(Action Value Function)#
行動価値関数は、特定のポリシーの下で、与えられた状態で行動を取ったときに期待される累積報酬を評価します。これは、状態の価値だけでなく、その状態から特定の行動を選択したときの期待される利益も評価します。
- :状態 - 行動対の価値、すなわち状態で行動を選択し、ポリシーに従ったときに期待される累積報酬。
- 状態価値関数とは異なり、行動価値関数は状態から特定の行動を実行したときの長期的な報酬を評価します。
上記の迷路の例を再度考えます。ネズミが現在状態にいて、チーズを探すために 4 つの方向(上、下、左、右)を選択できます。行動価値関数は、ネズミが各方向を選択したときの期待される報酬を教えてくれます。例えば、状態から右に移動する価値は、左に移動する価値よりも高いかもしれません。なぜなら、右に移動することでチーズにより早く近づくからです。
違いの要約#
-
** 状態価値関数** は、特定の状態でポリシーに従って将来の行動の累積期待報酬を考慮します。具体的にどの行動を取ったかには関心がありません。
-
** 行動価値関数** は、より詳細で、特定の行動を選択した後の期待される報酬を考慮します。
ベルマン方程式#
前の例に戻ります。ネズミが状態から始め、各ステップで得られる報酬が - 1 の場合:
これは、ネズミが状態から始めてゴールに到達するまでの累積報酬が - 6 であることを示しています。
このように各状態の累積報酬を直接計算するのは明らかにコストが高いプロセスです。なぜなら、すべての可能な経路とその報酬を考慮する必要があり、重複計算が多く発生するからです。ベルマン方程式は、この問題を解決するためのより簡潔な再帰的方法を提供します。
ベルマン方程式の核心的な考え方は、ある状態の価値をその状態の即時報酬と未来の状態価値の割引和として表現できるということです。公式は次のようになります:
これにより、各状態の累積報酬を最初から計算する必要がなく、即時報酬と次の状態の価値を再帰的に加算できます。
以前の例に戻りましょう。もし状態の価値が - 5 であることがわかっていれば、状態の価値はベルマン方程式を使って再帰的に計算できます:
割引を行わない場合(つまり)で、、即時報酬であれば:
これは、以前に直接計算した結果と一致します。
割引因子の役割#
ベルマン方程式の割引因子は、未来の報酬に対する重視の程度を決定します。
- が非常に低い(例えば 0.1 または 0)場合、私たちは未来の報酬をほとんど無視し、現在の即時報酬に焦点を当てます。
- の場合、私たちは未来のすべての報酬を考慮し、未来の各ステップが現在と同じくらい重要です。
- が大きすぎる(例えば百万)場合、物理的な意味を失い、未来の価値が無限に膨れ上がるため、実際のアプリケーションでは不合理です。
モンテカルロ法と時系列差分学習#
モンテカルロ法と時系列差分学習は、価値関数またはポリシー関数を訓練するための 2 つの異なる戦略であり、どちらも経験を利用して強化学習の問題を解決します。
モンテカルロ:エピソード終了時に学習#
モンテカルロ法(Monte Carlo Approach)は、状態または状態 - 行動対の価値を推定するために反復サンプリングを使用する方法です。この方法では、各エピソードが終了した後、そのエピソードの完全な経験に基づいて価値関数を更新します。以下に具体的な例を通じてモンテカルロ法の動作原理を詳しく説明します。
-
状態、行動、報酬、次の状態を記録:
- エージェントが行動を取るたびに、その時の状態、取った行動、得られた報酬、移行した次の状態を記録します。
-
総報酬を計算:
- エージェントは、そのエピソード内のすべての報酬を累積し、総報酬を計算して現在のポリシーのパフォーマンスを評価します。
-
価値関数を更新:
- 状態の価値推定を更新します。公式は次のようになります:
- 状態の価値推定を更新します。公式は次のようになります:
ここで:
- は学習率で、更新のステップサイズを示します。
- は実際に得られた総報酬です。
- は状態の現在の価値推定です。
更新後、エージェントは新しい状態価値関数で次のエピソードを開始し、複数のゲームを通じて学習し、ポリシーを改善します。
同じシーンを使って例を挙げます:
- ゲームの開始時に、ネズミは各状態の価値を 0(つまり)と仮定します。
- 学習率で、割引を行わない(つまり)とします。
- ネズミは探索中に一連の報酬を得て、累積報酬を得たと仮定します。
アルゴリズムの流れ:
- 報酬。
- 状態価値を更新:
既知の値を代入:
このエピソードの更新を通じて、ネズミの状態に対する価値推定は 0.3 に変わりました。
時系列差分学習:各ステップで学習#
モンテカルロ法とは異なり、** 時系列差分学習(Temporal Difference Learning、TD 学習)** は、エピソードが終了するのを待たずに、1 ステップの経験に基づいて逐次調整を行います。更新の根拠は、現在の状態から出発し、観察された即時報酬と次の状態の推定価値です。
公式は次のようになります:
ここで:
- は学習率です。
- は即時報酬です。
- は割引因子で、未来の報酬の重みを制御します。
この更新方法は ** ブートストラップ法(Bootstrapping)** と呼ばれ、既存の価値推定()に部分的に基づいて更新を行うため、完全なサンプルに依存しません。
ネズミがチーズを探す例を続けます:
-
価値関数の初期化:最初に、各状態の価値を 0 と仮定します。
-
エージェントの探索:ネズミは状態から始まり、ランダムに行動を選択します。仮にネズミが左に移動し、チーズを食べたとします。このとき、即時報酬を得ます。
-
TD 目標の計算:
TD 目標は即時報酬と次の状態の割引値の合計です:この例では、次の状態の価値で、と仮定すると:
-
価値関数の更新:
TD 目標を使用して状態の価値を更新します:値を代入すると:
このように、ネズミは各ステップ後に現在の状態の価値を更新します。ネズミが環境と相互作用を続けるにつれて、価値関数は各状態の真の価値を反映するようになります。
比較の要約:偏差と分散の観点から#
- モンテカルロ法:エピソード全体が終了した後、累積報酬を計算して価値関数を更新します。使用するのは実際の報酬値です。エピソード全体の経験に基づいて価値関数を更新するため、特に明確なモデルや遷移確率がない場合に適しています。
- **無偏性**:モンテカルロ法は実際の経験から完全な報酬を得るため、無偏です。すなわち、推定された期待値と真の期待値が一致します。
- **高分散**:エピソード全体の報酬を計算するため、複数のステップの状態遷移と報酬が関与し、推定の分散が高くなります。
- MC法は偏差の影響を受けません。分散は高いが無偏で、全体的な経験の評価に適しています。
- 時系列差分学習:各ステップ後に即時更新を行い、完全な報酬がなくても学習できます。使用するのは推定された報酬、すなわちで、の代わりに使用します。
- **有偏性**:TD法はブートストラップを使用し、初期値は通常任意であり、必ずしも正確ではないため、初期に偏差が存在しますが、より多くの実際の経験が蓄積されるにつれて偏差は徐々に減少します。偏差の存在は特にoff-policy + 関数近似器(例えばニューラルネットワーク)を使用する場合に深刻な問題を引き起こすことがあります。サットンとバルトが提唱した**「致命的三重奏」**はまさにこの状況を指します。
- **低分散**:単一ステップの状態遷移と報酬のみを考慮するため、分散は比較的低くなります。
- 分散は低いが有偏で、初期の推定は不正確ですが、リアルタイム更新に適しています。
Q-Learning 関連用語#
Q-Learning はoff-policyのvalue-based手法であり、TD 法を使用してその行動価値関数:Q 関数を訓練します。Q という文字は「Quality」を表し、特定の状態におけるその行動の価値を示します。
状態と行動が与えられた場合、Q 関数は状態 - 行動価値(Q 値とも呼ばれます)を出力します。
ここで、価値と報酬の違いを再確認します:
用語 | 説明 |
---|---|
状態の価値 | 期待累積報酬、すなわちエージェントがある状態から始まり、ポリシーに従って行動したときに期待される総報酬。 |
報酬 | 特定の状態で行動を実行した後、環境から得られる即時のフィードバック。 |
内部的に、私たちの Q 関数はQ テーブルによってエンコードされており、このテーブルの各セルは状態 - 行動対の値に対応しています。この Q テーブルはQ 関数の記憶(チートシート)と見なすことができます。
初期状態と上に移動する状態 - 行動価値は 0 であることがわかります。
したがって、トレーニングが完了すると、最適な Q 関数が得られます。これは、最適な Q テーブルを持つことを意味し、各状態で取るべき最適な行動を知ることができます。
アルゴリズムの流れ#
恐ろしい擬似コード:
ステップ 1:Q テーブルの初期化#
各状態 - 行動ペアに対して Q テーブルを初期化します。ほとんどの場合、0 で初期化します。
def initialize_q_table(state_space, action_space):
Qtable = np.zeros((state_space, action_space))
return Qtable
ステップ 2:ε- グリーディポリシーを使用して行動を選択#
ε- グリーディポリシーは、探索と利用の間のトレードオフを行う戦略です。探索の確率を徐々に減少させることで、エージェントは学習の初期段階では新しい行動を探索し、後期では学習した知識に基づいて最適な行動を選択します。
- 確率で:現在の Q テーブルの中で Q 値が最も高い行動を選択します(利用)。
- 確率で:ランダムに行動を選択します(探索)。
- 初期段階:のとき、エージェントは完全に探索を行い、ランダムに行動を選択します。
- トレーニングプロセス:トレーニングが進むにつれて、は徐々に減少し(例えば指数的に減少)、エージェントはますます現在の推定最適な行動を選択するようになります。
def greedy_policy(Qtable, state):
# 利用:最高の状態-行動値を持つ行動を選択
# 典型的なQ-learning操作:Qテーブルを照会し、現在の状態で報酬が最も高い行動を取得します。
# シンプルで直接的で、純粋に「利用」です。
action = np.argmax(Qtable[state][:]) # np.argmaxは最大値のインデックスを見つけます。
return action
def epsilon_greedy_policy(Qtable, state, epsilon):
random_num = random.uniform(0,1) # ランダム数
# ランダム数 > epsilon --> 利用
# これは重要です:1 - epsilonの確率で、私たちは利用を選択します。
# Qテーブルの中で最も良い行動を貪欲に選択します。
if random_num > epsilon:
# 与えられた状態で最高値の行動を選択
action = greedy_policy(Qtable, state)
# そうでなければ --> 探索
# ランダム数がepsilon未満の場合、エージェントは探索を行い、
# ランダムに行動を選択し、新しい可能性を試みます。
else:
action = env.action_space.sample() # 探索:ランダムな行動を選択します。
return action
ステップ 3:行動を実行し、報酬を得て次の状態に移行#
Q-learning では、このステップがアルゴリズムの核心です。エージェントが行動を実行すると、環境からフィードバック(報酬)を受け取り、新しい状態に移行します。このとき、エージェントは現在得られた即時報酬だけでなく、未来の潜在的な報酬も評価する必要があります。
これにより、Q-learningの更新公式が導入されます。
ステップ 4:を更新#
Q-learning は、前述の時系列差分学習で見た非常に重要な更新ルール、すなわちブートストラップを使用します:
- は、状態 - 行動対の現在の推定値です。
- は、エージェントが行動を実行した後に得られる即時報酬です。
- は、次の状態において、現在のポリシーに基づいて最適な行動の Q 値です。
- は学習率で、Q 値の更新速度を決定します。
- は割引因子で、即時報酬と未来の報酬の重みを調整します。
この方法により、Q-learning の各ステップの更新は、次の状態の最適 Q 値に基づいて調整されます。
def train(n_training_episodes, min_epsilon, max_epsilon, decay_rate, env, max_steps, Qtable):
# 外部トレーニングループ:n_training_episodes回の学習を実行
for episode in tqdm(range(n_training_episodes)):
# epsilonの減少:トレーニングが進むにつれて、epsilonは徐々に減少し、探索の確率が減少し、利用が増加します
epsilon = min_epsilon + (max_epsilon - min_epsilon)*np.exp(-decay_rate*episode)
# 各エピソードの開始時に環境をリセットし、初期状態を取得
state, info = env.reset()
step = 0
terminated = False
truncated = False
# 各エピソードで、エージェントは環境と相互作用し、最大max_stepsステップを実行します
for step in range(max_steps):
# ε-グリーディポリシーを使用して行動を選択
action = epsilon_greedy_policy(Qtable, state, epsilon)
# 行動を実行し、新しい状態と新しい報酬を観察
new_state, reward, terminated, truncated, info = env.step(action)
# Q値を更新:
# Q(s,a) = Q(s,a) + 学習率 * (報酬 + 割引因子 * max(Q(s',a')) - Q(s,a))
Qtable[state][action] = Qtable[state][action] + learning_rate * (reward + gamma * np.max(Qtable[new_state]) - Qtable[state][action])
# エージェントが現在の状態で終了した場合(成功または失敗)、このエピソードのトレーニングを停止
if terminated or truncated:
break
# エージェントの次の状態を新しい状態に設定
state = new_state
return Qtable
Off-policy と On-policy#
次に、ポリシーの 2 つのタイプ、Off-policyとOn-policyについて説明します。
ポリシー学習の観点から、両者の重要な違いは次のとおりです:
- On-policy:現在実行中のポリシーを学習し、エージェントの実際の行動と学習するポリシーが一致します。
- Off-policy:現在実行中のポリシーとは異なるポリシーを学習します。エージェントが探索ポリシーを実行していても、更新時には最適ポリシーに基づきます。
Off-policy(異なるポリシー)#
Off-policyは、行動を実行するポリシー(acting policy)と Q 値を更新するポリシー(updating policy)に異なるポリシーを使用します。前述の Q-learning では、エージェントは行動選択に ε- グリーディポリシーを使用しますが、Q 値を更新する際には貪欲ポリシー(greedy policy)を使用して最適な行動を見つけます。
例えば、Q 値を更新する際、エージェントは次の状態で最適な行動を選択します。つまり:
これは、現在のポリシーが ε- グリーディであっても、常に貪欲ポリシーを使用して Q 値を更新し、収束速度を加速させることを意味します。これが Q-learning がOff-policyアルゴリズムと呼ばれる理由です。
On-policy(同じポリシー)#
一方、On-policyは、行動と Q 値の更新に同じポリシーを使用することを要求します。例えば、SARSAアルゴリズムでは、更新時に選択する行動も現在のポリシーに基づいており、貪欲ポリシーではありません。これにより、エージェントは常に ε- グリーディポリシーを使用して行動を選択し、更新するため、学習プロセスが実際の実行ポリシーにより近くなります。
理解を深めるために例を挙げます:
-
SARSA(On-policy):エージェントが現在状態にいて、行動を選択し、新しい状態に移行し、新しい行動を選択したとします。SARSA は(現在の ε- グリーディポリシーに基づいて選択された行動)を使用して Q 値を更新します。
-
Q-learning(Off-policy):同じ状況で、Q-learning も状態から行動を選択し、状態に移行します。しかし、Q 値を更新する際、で実際に選択された行動には関係なく、のすべての行動の最大 Q 値(最適ポリシー)を使用して Q 値を更新します。
さらに深く掘り下げましょう!#
「Frozen Lake」のような簡単なゲームの場合、Q テーブルを構築することで、比較的短時間で優れた Q 関数を得ることができます。
しかし、環境が《Doom》のように膨大な状態空間(数百万の異なる状態)を持つゲームや現実のシミュレーターに変わると、Q テーブルを作成して更新する効率は非常に低下します。
これが、深層 Q 学習を導入し、神経ネットワークを使用して特定の状態における各行動の異なる Q 値を近似する理由です。