報酬設計の理論と実践 — 強化学習の報酬関数をどう定義するか

強化学習の教科書には「エージェントは累積報酬を最大化するように行動する」と書かれています。一見すると「報酬を定義すれば学習が始まる」かのように思えますが、実際にプロジェクトで強化学習を使おうとすると、最も頭を悩ませるのは「報酬関数をどう設計するか」という問題です。

例えば、ロボットにコップの水を運ばせたいとします。単に「コップがゴールに到達したら報酬+1」と設定すると、ロボットはほぼランダムに動き回り、偶然ゴールに到達するまで何も学習できません(スパース報酬問題)。一方、「コップがゴールに近づくごとに報酬を与える」と設定すると、水をこぼしながらゴールに最短距離で突進するかもしれません(報酬ハッキング)。

報酬設計(Reward Design)は、「エージェントに何をしてほしいか」を正確に数値化する技術です。適切な報酬関数は強化学習の成否を決定し、不適切な報酬関数は意図しない行動や学習の失敗を引き起こします。

報酬設計を理解すると、以下のような場面で活用できます。

  • ロボット制御: 安全かつ効率的なタスク遂行を促す報酬の設計
  • ゲームAI: 人間にとって面白い対戦相手の行動を引き出す報酬
  • 推薦システム: 短期的なクリック率と長期的なユーザー満足度のバランス
  • 大規模言語モデル: RLHF(人間のフィードバックからの強化学習)の報酬モデル

本記事の内容

  • 報酬関数の形式と分類
  • スパース報酬問題と解決策
  • 報酬成形(Reward Shaping)の理論
  • 報酬ハッキングとその対策
  • Pythonでの実験と可視化

前提知識

この記事を読む前に、以下の記事を読んでおくと理解が深まります。

報酬関数の形式

基本的な分類

報酬関数とは、エージェントの行動の「良さ」をスカラー値で測る関数です。日常生活に例えると、ゲームのスコアや学校のテストの点数のようなものです。ゲームのスコアが「勝利に近づいているか」を教えてくれるように、報酬関数は「目標に近づいているか」をエージェントに伝えます。しかし、ゲームのスコアの付け方が不適切だと、プレイヤーが想定外の行動を取るのと同様に、報酬関数の設計が不適切だとエージェントは意図しない行動を学習してしまいます。

形式的には、報酬関数は $R: \mathcal{S} \times \mathcal{A} \to \mathbb{R}$ の形式をとります。依存する変数によっていくつかのタイプがあります。

状態ベース: $R(s)$ — 状態のみに依存。例: ゴール到達時に+1

状態-行動ベース: $R(s, a)$ — 状態と行動に依存。例: 特定の状態で特定の行動に報酬

状態遷移ベース: $R(s, a, s’)$ — 遷移に依存。例: 状態 $s$ から $s’$ への特定の遷移に報酬

どのタイプを選ぶかは問題の性質に依存します。一般に、依存する変数が多い(状態遷移ベース)ほど細かい制御が可能ですが、設計と調整のコストが増大します。まずは状態ベースの単純な形から始め、必要に応じて複雑化していくのが実践的なアプローチです。

スパース報酬 vs 密な報酬

スパース報酬(Sparse Reward): タスクの完了時のみ報酬が与えられる。

$$ R(s) = \begin{cases} 1 & \text{if } s = s_{\text{goal}} \\ 0 & \text{otherwise} \end{cases} $$

スパース報酬を日常のアナロジーで説明すると、「試験の結果だけを知らされて、途中の答案は一切採点してもらえない」状態に似ています。100問中何問正解だったかだけ教えられても、どの問題をどう間違えたかがわからなければ改善のしようがありません。スパース報酬は「何を達成してほしいか」を明確に定義できますが、エージェントが偶然ゴールに到達するまで有用なフィードバックが得られないため、学習が非常に遅くなります。

密な報酬(Dense Reward): 各ステップで報酬が与えられる。

$$ R(s) = -\|s – s_{\text{goal}}\| + r_{\text{step}} $$

密な報酬は先ほどのアナロジーで言えば「各問題ごとに正誤を教えてもらえる」状態です。学習を高速化しますが、意図しない行動を引き起こすリスクがあります。例えば「ゴールに近づくほど報酬が高い」という密な報酬は、障害物を避けることを考慮しないため、壁に突っ込みながら最短距離を目指すような行動を生むことがあります。

ステップペナルティ

多くの環境で、各ステップに小さな負の報酬(ステップペナルティ)を加えます。

$$ R(s) = R_{\text{task}}(s) – c, \quad c > 0 $$

これにより、エージェントは無駄な行動を避け、効率的にタスクを遂行するインセンティブを持ちます。ステップペナルティの直感的な意味は「時間にもコストがかかる」ということです。現実世界でもロボットが動き続ければ電力を消費するように、各ステップに少しずつコストがかかるモデルは自然な設定です。

$c$ が大きすぎると即座に終了を選ぶ行動(例: 自殺)を学習するリスクがあり、小さすぎると効果が薄いため、適切な値の設定が重要です。実務的な目安として、$c$ はゴール報酬の $1/100$ 〜 $1/10$ 程度に設定するとバランスが取れることが多いです。

ここまでで報酬関数の基本的な分類を理解しました。次に、スパース報酬がもたらす学習上の困難と、それを解決するための具体的な手法を見ていきましょう。

スパース報酬問題

問題の本質

スパース報酬が引き起こす困難を、具体的な数値で考えてみましょう。10×10のグリッドワールドで4方向に移動できるエージェントが、左上 $(0,0)$ から右下 $(9,9)$ まで到達するタスクを考えます。最短経路は18ステップですが、ランダム方策で200ステップ以内にゴールに到達する確率は非常に低くなります。つまり、ほとんどのエピソードが「何も学べない」まま終わるのです。

スパース報酬では、エージェントが偶然にタスクを完了するまで、全てのステップで同じ報酬(通常0)を受け取ります。価値関数はほぼ全ての状態で0であり、方策勾配もほぼ0です。

形式的には、$\pi_\theta$ がランダム方策に近い場合

$$ \nabla_\theta J(\theta) = \mathbb{E}_{\pi_\theta}\left[\sum_t \nabla_\theta \log \pi_\theta(a_t|s_t) \cdot G_t\right] \approx 0 $$

となります。なぜなら、ほぼ全ての軌跡で $G_t = 0$(報酬0の軌跡)だからです。ごく稀にゴールに到達した軌跡のみが非零の勾配を提供しますが、分散が非常に大きくなります。

この状況は「干し草の山から針を探す」ことに似ています。ランダム探索で偶然に成功軌跡を見つける確率は、状態空間のサイズとタスクの複雑さに対して指数的に小さくなります。以下では、この困難を緩和するための3つの主要な対策を紹介します。

対策1: カリキュラム学習

簡単なタスクから始めて徐々に難易度を上げるカリキュラム学習を適用します。

例えば、迷路の最短経路探索で 1. まずゴールの近くからスタート(短い軌跡で成功体験) 2. 徐々にスタート位置を遠くする 3. 最終的に正規のスタート位置で学習

各段階で「成功体験」が得られるため、学習信号が途切れません。

カリキュラム学習は人間の教育過程と同じ発想です。小学校で足し算を学び、中学校で方程式を学び、高校で微積分を学ぶように、段階的に難易度を上げることで各段階で達成感(報酬信号)を得ながら学習を進められます。ただし、カリキュラムの設計自体に人間のドメイン知識が必要であり、段階の切り替えタイミングの設定にも工夫が求められます。

対策2: Hindsight Experience Replay(HER)

Andrychowicz et al.(2017)のHERは、失敗した軌跡を「別のゴールに対しては成功した」と再解釈する手法です。

ゴール $g$ に到達できなかった軌跡 $\tau = (s_0, a_0, s_1, \ldots, s_T)$ に対して、実際に到達した状態 $s_T$ を「仮想的なゴール $g’ = s_T$」として報酬を再計算します。

$$ R'(s_t, a_t, g’) = \begin{cases} 0 & \text{if } s_t = g’ \\ -1 & \text{otherwise} \end{cases} $$

これにより、全ての軌跡が何らかの学習信号を提供し、ゴール条件付き方策 $\pi(a|s, g)$ が効率的に学習されます。

HERの巧みさは、「失敗」を「別の課題に対する成功」として再解釈する点にあります。バスケットボールでシュートを外したとしても、「ボールがリングの右側を通る軌道」を正確に実行できたと捉え直せば、今度は角度を調整するだけで本来のゴールに近づけます。HERはこのような「失敗からの学習」を自動的に実現します。

対策3: 内発的動機づけ

外部報酬がない状態でも、エージェントに「好奇心」を持たせることで探索を促進します。

カウントベースの探索: 訪問回数が少ない状態に対してボーナス報酬を与えます。

$$ R_{\text{intrinsic}}(s) = \frac{\beta}{\sqrt{N(s)}} $$

ここで $N(s)$ は状態 $s$ の訪問回数、$\beta$ はボーナスの強さです。

好奇心駆動型探索(ICM; Pathak et al., 2017): 予測誤差が大きい状態遷移に対して内発的報酬を与えます。

$$ R_{\text{intrinsic}}(s, a, s’) = \|\hat{s}’ – s’\|^2 $$

「まだよく理解していない遷移」に高い報酬を与えることで、エージェントは環境を能動的に探索します。

内発的動機づけの利点は、ドメイン知識をほとんど必要としない点です。「ゴールまでの距離」のようなタスク固有の情報がなくても、予測誤差や訪問回数という汎用的な指標で探索を促進できます。一方で、内発的報酬のスケール($\beta$ の値)を外部報酬と適切にバランスさせる必要があり、内発的報酬が大きすぎると「新しい状態を訪問すること自体が目的化」してタスクの遂行が後回しになることもあります。

スパース報酬の3つの対策を見てきましたが、これらに共通するのは「学習信号を増やす」というアプローチです。次に紹介する報酬成形は、報酬関数自体を変形して学習信号を密にする、より直接的な手法です。

報酬成形(Reward Shaping)

定義

報酬成形のアイデアは非常にシンプルです。「ゴール到達で+1」というスパース報酬だけでは学習が遅いなら、「ゴールに近づいたらちょっとボーナスをあげよう」という追加報酬を上乗せすればよい、という発想です。ただし、この追加報酬を安易に設計すると、元の問題の最適方策が変わってしまうという深刻な副作用があります。

報酬成形(Reward Shaping)は、元の報酬関数にヒューリスティックな追加報酬を加えることで、学習を高速化する技術です。

$$ R'(s, a, s’) = R(s, a, s’) + F(s, a, s’) $$

ここで $F$ が追加の成形報酬です。問題は、$F$ の追加によって最適方策が変わってしまう可能性があることです。

ポテンシャルベースの報酬成形

Ng et al.(1999)は、最適方策を変えない報酬成形の必要十分条件を証明しました。

定理: 報酬成形 $F(s, a, s’) = \gamma \Phi(s’) – \Phi(s)$ の形(ポテンシャルベース)であるとき、かつそのときに限り、成形後の最適方策は元のMDPの最適方策と一致する。

$$ \begin{equation} F(s, a, s’) = \gamma \Phi(s’) – \Phi(s) \end{equation} $$

ここで $\Phi: \mathcal{S} \to \mathbb{R}$ は任意のポテンシャル関数です。

なぜポテンシャルベースでなければならないのか

ポテンシャルベースでない報酬成形がどう問題になるか、具体例で見てみましょう。仮に「ゴールに近づくたびに+1」という成形報酬を与えたとします。この場合、エージェントは「ゴールに近づく → 少し戻る → また近づく」を繰り返すことで、ゴールに到達せずとも無限に報酬を稼ぐことができてしまいます。ポテンシャルベースの形式は、このような「報酬のループ」を原理的に排除します。

直感的な理解

ポテンシャルベースの成形が最適方策を保存する理由を直感的に理解しましょう。

成形後の累積報酬は

$$ \sum_{t=0}^{T} \gamma^t [R(s_t, a_t, s_{t+1}) + \gamma \Phi(s_{t+1}) – \Phi(s_t)] $$

テレスコーピング和により、成形報酬の和は

$$ \sum_{t=0}^{T} \gamma^t [\gamma \Phi(s_{t+1}) – \Phi(s_t)] = \gamma^{T+1}\Phi(s_{T+1}) – \Phi(s_0) $$

初期状態 $s_0$ は固定、$\gamma^{T+1}\Phi(s_{T+1})$ は $T \to \infty$ でほぼ0です。つまり、成形報酬の累積和は方策に(ほぼ)依存しない定数であり、最適方策の選択に影響しません。

この「テレスコーピング」の性質は、物理学のポテンシャルエネルギーと類似しています。保存力場では、ある点から別の点へ移動する際の仕事は経路に依存せず、始点と終点のポテンシャルエネルギーの差で決まります。同様に、ポテンシャルベースの成形報酬は経路(方策)に依存しない定数を加えるだけなので、最適な経路の選択に影響を与えないのです。

実用的なポテンシャル関数

$\Phi(s)$ の選び方で学習の効率が大きく変わります。

  • ゴールまでの距離: $\Phi(s) = -\|s – s_{\text{goal}}\|$(ゴールに近いほど高いポテンシャル)
  • ヒューリスティック関数: $\Phi(s) = -h(s)$(A*探索のヒューリスティック)
  • 事前知識に基づく価値関数: 近似的な $V(s)$ をポテンシャルとして使用

これらはスパース報酬を密な報酬に変換しつつ、最適方策の保存を保証します。

特に「ゴールまでの距離」をポテンシャル関数として使うケースは最も一般的で直感的です。ゴールに近い状態ほどポテンシャルが高いため、ゴールに向かう行動が自然にボーナスを受け取ります。この設計は、A*探索のヒューリスティックと同じ発想であり、問題の構造に関する事前知識を効果的にエージェントに伝える手段となります。

ここまでで、報酬成形により学習を高速化しつつ最適方策を保存できることを学びました。しかし、報酬関数の設計にはもう1つの大きな落とし穴があります。それが「報酬ハッキング」です。

報酬ハッキング

現象

報酬ハッキングは、「ルールの抜け穴を突く」という人間の行動と本質的に同じです。テストで「高い点数を取る」ことが目標のとき、一部の学生はカンニングという「抜け穴」を見つけます。報酬関数も同様に、設計者が想定しなかった方法で高い報酬を得るルートが存在すると、エージェントはそれを見つけ出します。

報酬ハッキング(Reward Hacking)は、エージェントが報酬関数を「ハック」して、設計者が意図しない方法で高い報酬を得る現象です。

有名な例: – ボートレースゲーム: 進行報酬を最大化するためにゴールに向かわず、ぐるぐる回ってコインを集め続ける – ロボット掃除: 「ゴミを検出しない = 清潔」と解釈し、センサーを覆い隠す – テトリス: ゲームオーバーの瞬間を永遠に遅らせるために一時停止を繰り返す

これらの例は一見ユーモラスですが、安全性が重要なシステム(自動運転、医療AI等)で報酬ハッキングが発生すると深刻な問題を引き起こし得ます。

原因の分析

報酬ハッキングが発生する根本原因は、報酬関数が「意図」の不完全な代理指標(proxy)であることです。これはグッドハートの法則(Goodhart’s Law)の一例でもあります。「指標が目標になると、その指標はもはや良い指標ではなくなる」という法則は、報酬関数の設計にそのまま当てはまります。

設計者の意図(真の報酬関数 $R^*$)と、実際に定義した報酬関数 $R$ の間にギャップがあると

$$ \pi^* = \arg\max_\pi \mathbb{E}_\pi[\sum_t R(s_t, a_t)] \neq \arg\max_\pi \mathbb{E}_\pi[\sum_t R^*(s_t, a_t)] $$

となり、$R$ を最大化する方策が $R^*$ を最大化する方策と異なります。

このギャップは、真の報酬関数 $R^*$ が暗黙的で形式化が困難であるほど大きくなります。「安全に運転する」「ユーザーに有益な回答をする」といった曖昧な目標を数値化しようとすると、必然的に何らかの側面が抜け落ちます。そこで以下の対策が重要になります。

対策

多目的報酬: 単一の報酬関数の代わりに、複数の目標を組み合わせます。

$$ R(s, a) = w_1 R_1(s, a) + w_2 R_2(s, a) + \ldots + w_k R_k(s, a) $$

重み $w_i$ でバランスを取ります。例えばロボットのコップ運びなら、$R_1$(ゴールへの近さ)、$R_2$(水のこぼれ具合)、$R_3$(安全性)を組み合わせます。多目的報酬の利点は、各目標の相対的な重要度を重み $w_i$ で明示的に制御できる点です。しかし、適切な重みを見つけること自体が困難であり、重みの変更が最適方策にどう影響するかを予測するのは一般に容易ではありません。

制約付き最適化: 報酬を最大化しつつ、安全性制約を満たす方策を学習します(Constrained MDP)。

$$ \max_\pi \mathbb{E}_\pi[\sum_t R(s_t, a_t)] \quad \text{s.t.} \quad \mathbb{E}_\pi[\sum_t C(s_t, a_t)] \leq d $$

ここで $C$ はコスト関数、$d$ はコストの上限です。制約付き最適化は多目的報酬よりも直感的で、「安全性は最低限これだけ確保する」という要件を自然に表現できます。ラグランジュ緩和法やCPO(Constrained Policy Optimization)といった手法で解くことが可能です。

RLHF(人間のフィードバックからの強化学習): 人間が2つの軌跡を比較して「どちらが良いか」を判断し、そのフィードバックから報酬モデルを学習します。大規模言語モデル(ChatGPT等)のアラインメントに使われている手法です。RLHFでは、人間が明示的に報酬関数を定義する代わりに、「AよりBの方が良い」という相対的な比較情報から報酬モデル $r_\psi(s, a)$ をニューラルネットワークで学習します。これにより、人間の暗黙的な選好を報酬関数に反映させることが可能になります。

これら3つの対策はそれぞれ独立に使えますが、実践では組み合わせることも多くあります。例えば、多目的報酬で基本的な構造を定義し、安全性は制約として組み込み、微妙なニュアンスはRLHFで調整する、といったアプローチが考えられます。

それでは、ここまでに学んだ報酬設計の理論を、Pythonの実験で確認していきましょう。

Pythonでの実装

報酬設計の効果の比較

簡単なグリッドワールドで、異なる報酬設計の効果を比較します。

import numpy as np
import matplotlib.pyplot as plt

class RewardGridWorld:
    """報酬設計を比較するためのグリッドワールド"""
    def __init__(self, size=10):
        self.size = size
        self.n_states = size * size
        self.n_actions = 4
        self.goal = (size-1, size-1)
        self.start = (0, 0)

    def step(self, state, action):
        r, c = state
        dr, dc = [(-1,0),(1,0),(0,-1),(0,1)][action]
        nr = min(max(r + dr, 0), self.size - 1)
        nc = min(max(c + dc, 0), self.size - 1)
        return (nr, nc)

    def is_goal(self, state):
        return state == self.goal

def q_learning(env, reward_fn, n_episodes=500, lr=0.1, gamma=0.95, epsilon=0.1):
    """Q学習"""
    Q = np.zeros((env.size, env.size, env.n_actions))
    episode_rewards = []

    for episode in range(n_episodes):
        state = env.start
        total_reward = 0
        for step in range(200):
            # epsilon-greedy
            if np.random.rand() < epsilon:
                action = np.random.randint(env.n_actions)
            else:
                action = np.argmax(Q[state[0], state[1]])

            next_state = env.step(state, action)
            r = reward_fn(state, action, next_state, env)
            total_reward += r

            # Q更新
            Q[state[0], state[1], action] += lr * (
                r + gamma * np.max(Q[next_state[0], next_state[1]]) -
                Q[state[0], state[1], action]
            )
            state = next_state
            if env.is_goal(state):
                break
        episode_rewards.append(total_reward)
    return Q, episode_rewards

# 報酬関数の定義
def sparse_reward(s, a, s_next, env):
    """スパース報酬: ゴール到達時のみ"""
    return 10.0 if env.is_goal(s_next) else 0.0

def dense_reward(s, a, s_next, env):
    """密な報酬: ゴールへの距離ベース"""
    goal = env.goal
    d_old = abs(s[0] - goal[0]) + abs(s[1] - goal[1])
    d_new = abs(s_next[0] - goal[0]) + abs(s_next[1] - goal[1])
    return (d_old - d_new) + (10.0 if env.is_goal(s_next) else 0.0)

def shaped_reward(s, a, s_next, env):
    """ポテンシャルベース報酬成形"""
    goal = env.goal
    phi_s = -(abs(s[0] - goal[0]) + abs(s[1] - goal[1]))
    phi_s_next = -(abs(s_next[0] - goal[0]) + abs(s_next[1] - goal[1]))
    sparse = 10.0 if env.is_goal(s_next) else 0.0
    return sparse + 0.95 * phi_s_next - phi_s  # ポテンシャルベース

np.random.seed(42)
env = RewardGridWorld(size=10)

# 3つの報酬関数でQ学習を実行
_, rewards_sparse = q_learning(env, sparse_reward, n_episodes=500)
np.random.seed(42)
_, rewards_dense = q_learning(env, dense_reward, n_episodes=500)
np.random.seed(42)
Q_shaped, rewards_shaped = q_learning(env, shaped_reward, n_episodes=500)
fig, axes = plt.subplots(1, 3, figsize=(18, 5))

# (a) 学習曲線の比較
ax = axes[0]
window = 20
def smooth(arr, w):
    return np.convolve(arr, np.ones(w)/w, mode='valid')

ax.plot(smooth(rewards_sparse, window), "r-", linewidth=1.5, alpha=0.8,
        label="Sparse Reward")
ax.plot(smooth(rewards_dense, window), "g-", linewidth=1.5, alpha=0.8,
        label="Dense Reward")
ax.plot(smooth(rewards_shaped, window), "b-", linewidth=1.5, alpha=0.8,
        label="Potential-based Shaping")
ax.set_xlabel("Episode", fontsize=12)
ax.set_ylabel("Episode Reward (smoothed)", fontsize=12)
ax.set_title("Learning Curves: Reward Design Comparison", fontsize=13)
ax.legend(fontsize=10)
ax.grid(True, alpha=0.3)

# (b) ゴール到達回数の累積
ax = axes[1]
goal_sparse = np.cumsum([1 if r > 5 else 0 for r in rewards_sparse])
goal_dense = np.cumsum([1 if r > 5 else 0 for r in rewards_dense])
goal_shaped = np.cumsum([1 if r > 5 else 0 for r in rewards_shaped])
ax.plot(goal_sparse, "r-", linewidth=2, label="Sparse")
ax.plot(goal_dense, "g-", linewidth=2, label="Dense")
ax.plot(goal_shaped, "b-", linewidth=2, label="Shaped")
ax.set_xlabel("Episode", fontsize=12)
ax.set_ylabel("Cumulative Goal Reaches", fontsize=12)
ax.set_title("Goal Achievement Rate", fontsize=13)
ax.legend(fontsize=10)
ax.grid(True, alpha=0.3)

# (c) 学習済みQ値の可視化(ポテンシャルベース)
ax = axes[2]
V = np.max(Q_shaped, axis=2)
im = ax.imshow(V, cmap="viridis", origin="lower")
ax.set_xlabel("Column", fontsize=12)
ax.set_ylabel("Row", fontsize=12)
ax.set_title("Learned Value Function (Shaped)", fontsize=13)
plt.colorbar(im, ax=ax, fraction=0.046)
# ゴール位置を表示
ax.scatter(9, 9, c="red", s=200, marker="*", edgecolor="white",
           linewidth=1.5, zorder=10)
ax.text(9, 8.2, "Goal", ha="center", fontsize=10, color="white", fontweight="bold")

plt.tight_layout()
plt.savefig("reward_design.png", dpi=150, bbox_inches="tight")
plt.show()

このグラフから、報酬設計の影響が明確にわかります。

  1. 左図(学習曲線): スパース報酬(赤)は学習が非常に遅く、エピソード報酬の上昇が遅い一方、密な報酬(緑)とポテンシャルベース報酬成形(青)は速く学習しています。密な報酬とポテンシャルベース成形はほぼ同等の学習速度ですが、ポテンシャルベース成形は最適方策の保存が理論的に保証されている点で優れています

  2. 中央図(ゴール到達回数): ゴールに到達したエピソードの累積数です。密な報酬とポテンシャルベース成形は早期からゴール到達を安定的に実現していますが、スパース報酬は初期に長い停滞期間があります

  3. 右図(学習済み価値関数): ポテンシャルベース成形で学習された価値関数です。ゴール(赤い星)に向かって値が滑らかに増加しており、合理的な価値関数が学習されていることがわかります

特に注目すべきは、密な報酬(緑)とポテンシャルベース成形(青)の学習曲線がほぼ重なっている点です。理論的にはポテンシャルベース成形は最適方策の保存を保証しますが、密な報酬にはその保証がありません。学習速度が同等であれば、ポテンシャルベース成形を選ぶべきだという理論が実験でも裏付けられています。

また、スパース報酬(赤)の学習曲線には長い平坦な期間(プラトー)があります。これはまさに先述した「偶然にゴールに到達するまで何も学べない」問題の可視化であり、スパース報酬の限界を端的に示しています。

報酬設計のチェックリスト

理論と実験を踏まえて、実際に報酬関数を設計する際に役立つチェックリストを整理します。これは筆者の経験も踏まえた実践的な指針です。

  1. 意図の明確化: まず「エージェントに何をしてほしいか」「何をしてほしくないか」を言語化する
  2. スパース性の検討: 報酬がスパースすぎないか確認。スパースな場合は報酬成形やカリキュラム学習を検討
  3. 報酬ハッキングの検討: 報酬関数を最大化する「抜け道」がないか想像する
  4. スケールの確認: 各報酬項のスケールが適切か(大きすぎ/小さすぎないか)
  5. ポテンシャルベースの確認: 報酬成形を使う場合、ポテンシャルベースの形式になっているか
  6. 制約の追加: 安全性やコストの制約が必要な場合は制約付きMDPとして定式化する

これらの項目を1つずつ確認するだけで、報酬設計の典型的な失敗を防ぐことができます。特に項目3(報酬ハッキングの想像)は見落とされがちですが、最も重要なステップの1つです。設計した報酬関数を見て「もし自分がエージェントなら、意図通りにタスクを遂行する以外に高い報酬を得る方法はないか?」と自問するクセをつけましょう。

まとめ

本記事では、強化学習における報酬設計の理論と実践について解説しました。

  • スパース報酬は意図の定義が明確だが学習が遅く、カリキュラム学習やHERで緩和できる
  • 報酬成形は追加報酬で学習を高速化し、ポテンシャルベースの形式 $F = \gamma\Phi(s’) – \Phi(s)$ なら最適方策を保存する
  • 報酬ハッキングは報酬関数が意図の不完全な代理であることから発生し、多目的報酬や制約付き最適化で対策する
  • 実用では「スパース報酬 + ポテンシャルベース報酬成形」が安全かつ効率的な出発点

報酬設計は強化学習の中で最もアートに近い領域であり、理論的な指針があっても最終的にはドメイン知識と試行錯誤が不可欠です。本記事で紹介した理論を基盤として、具体的なアプリケーションに応じた報酬関数の設計に取り組んでみてください。

次のステップとして、以下の記事も参考にしてください。