Q学習
Q 学習は、行動価値 Q(s,a) を直接学びながら最適行動を目指す方法です。状態価値を経由せず、各行動をその場で比べられるので、モデルなし制御の代表例になります。
参考動画(外部)
授業本編ではなく、別の説明で見直したいときの参考材料です。
max を入れた瞬間に「最善ならどうなるか」を学び始める
Q 学習の特徴は、次状態で実際に取った行動ではなく、そこで取りうる最善行動の価値を目標値に入れることです。だからこそ off-policy になり、探索しながらでも最適方策へ寄せる更新ができます。
ここで見たいのは、Q(s,a) の更新式そのものより、なぜ max が policy の外側にいるのかです。実際の行動列と、学習が目指す行動列が一致しなくてよいのが Q 学習の強さであり、同時に過大評価の入口にもなります。
読み進める視点
参照用の return、1 回の Q 更新、greedy action の抽出、探索と活用の切り替え、最後に得られた方策の読み方を順に見ます。
この notebook の主題は、表形式 Q 学習の骨格です。あとで deep RL を読むときも、target の中身は結局ここで見た から始まっています。
読み方の軸
Q 学習では「実際に何をしたか」より「そこから最善ならどうするか」を更新します。この差が、SARSA との対比でいちばん重要です。
検証 1: Q学習の更新準備
Q学習の更新式確認のため、割引率と報酬列を先に定義します。
rewards = [0.0, 1.0, 0.2, 1.4]
gamma = 0.91
g = 0.0
for r in reversed(rewards):
g = r + gamma * g
print('task = q-learning', 'reference_return=', round(g, 6))
次セルでmax演算を含む更新規則に接続します。
検証 2: ベルマン更新を1回行う
次に、価値更新を1ステップだけ計算します。1回更新でも、再帰構造の意味は十分に見えてきます。
v_next = {'s0': 0.4, 's1': 0.8}
reward = {'left': 0.2, 'right': 1.0}
trans = {'left': 's0', 'right': 's1'}
v_s = max(reward[a] + gamma * v_next[trans[a]] for a in ['left', 'right'])
print('updated V(s)=', round(v_s, 6))
ベルマン更新は『今の価値』を『次状態の価値』で再定義する操作です。この再帰が強化学習の中心です。
定義の確認
検証 3: Q値更新を比較する
ここで Q学習の更新式をコードに写し、数値の動きを確認します。式を読むだけでは掴みにくい感覚を得る段階です。
Q = {('s0','left'): 0.3, ('s0','right'): 0.1, ('s1','left'): 0.5, ('s1','right'): 0.7}
alpha = 0.2
r, s, a, s_next = 1.0, 's0', 'right', 's1'
td_target = r + gamma * max(Q[(s_next,'left')], Q[(s_next,'right')])
Q[(s,a)] += alpha * (td_target - Q[(s,a)])
print('Q(s0,right)=', round(Q[(s,a)], 6))
更新後の値が過去の値とどれだけ違うかは、学習率と TD 誤差で決まります。ここが調整ポイントです。
検証 4: 探索と活用の切り替え
次に、探索率を変えたときの行動選択を見ます。探索不足は局所最適に閉じる典型的な原因です。
import random
random.seed(7)
def choose_action(q_left, q_right, epsilon):
if random.random() < epsilon:
return random.choice(['left', 'right'])
return 'left' if q_left >= q_right else 'right'
samples_high_eps = [choose_action(0.4, 0.7, 0.5) for _ in range(8)]
samples_low_eps = [choose_action(0.4, 0.7, 0.1) for _ in range(8)]
print('epsilon=0.5 ->', samples_high_eps)
print('epsilon=0.1 ->', samples_low_eps)
探索率は固定せず、学習段階に応じて減衰させるのが一般的です。初期は広く探索し、後半で活用へ寄せます。
検証 5: 方策評価の簡易チェック
最後に、方策の平均報酬を簡易的に比較します。アルゴリズムの評価は、更新式だけでなく結果の検証が不可欠です。
episode_rewards = [1.2, 0.8, 1.5, 1.1, 1.4]
avg_reward = sum(episode_rewards) / len(episode_rewards)
variance = sum((r - avg_reward) ** 2 for r in episode_rewards) / len(episode_rewards)
print('avg =', round(avg_reward, 4))
print('var =', round(variance, 4))
平均だけでなく分散を見ると、方策の安定性も評価できます。実運用ではこの二軸が重要です。
この節の要点
- Q 学習は
Q(s,a)を直接学ぶ。 - 目標値に
max_{a'} Q(s',a')を入れるので off-policy になる。 maxの強気さが、後で SARSA との振る舞いの差を生む。