強化学習・Q学習
Q学習とは
Q学習 は状態$s_x$と行動$a_x$の組み合わせに対する 価値$Q(s_x,a_x)$ を学習するためのアルゴリズムです. 下記は,状態$s_x$で行動$a_x$を選択し,報酬$r$を獲得したときの更新式です. また,$Q(s_y, a_y)$は,状態$s_x$から遷移した先の状態$s_y$において,行動$a_y$を選択したときの価値を表しています. ここで,$\alpha$は学習率,$\gamma$は割引率と呼ばれるパラメータであり, $0 \leq \alpha \leq 1$,$0 \leq \gamma \leq 1$の範囲で設定します. 学習率は学習の収束に影響し,小さいとゆっくりと学習し,大きいと速く学習します(収束の安定性とトレードオフ). また,割引率は将来得られるであろう報酬を割り引いて評価するために用います.
$$ Q'(s_x,a_x) = (1 - \alpha)Q(s_x,a_x) + \alpha(r + \gamma \max_{a_y \in A(s_y)} Q(s_y, a_y)) $$
パラメータ | 意味 |
---|---|
$s$ | 状態 |
$a$ | 行動 |
$Q(s,a)$ | 状態$s$で行動$a$を選択する価値 |
$r$ | 報酬 |
$A(s)$ | 状態$s$で選択可能な行動の集合 |
$\alpha$ | 学習率 |
$\gamma$ | 割引率 |
ノートブックの作成
Google Colaboratory を起動し,新規にノートブックを作成してください. ノートブックのタイトルは AI-15 とします. ノートブックの作成方法は第1回の資料を参照してください.
下記のライブラリも導入しておきます.
import gym
import numpy as np
import random
import time
from google.colab import output
from PIL import Image
from gym.envs.toy_text.frozen_lake import generate_random_map
フローズンレイク(FrozenLake)
フローズンレイク(FrozenLake)をQ学習を利用して解いてみましょう.
環境の初期化
前回と同様に対象とする環境を作成します.
env = gym.make('FrozenLake-v1', map_name="4x4", is_slippery=False)
また,実行結果の理解を簡単にするために,辞書ACTION
,関数toString()
も定義します.
ACTION = {
0: "LEFT",
1: "DOWN",
2: "RIGHT",
3: "UP"
}
def toString(histories):
moves = []
for observation, action in histories:
moves.append((observation, ACTION[action]))
return moves
Q学習
Qテーブル
価値$Q(s,a)$を記録するための辞書を作成します.
$s$は$0,1,\cdots,15$の16パターン,
$a$は$0,1,2,3$の4パターンが存在するため,
$16\times4=64$パターンの$Q$を記録する必要があります.
全ての$Q$は0.01
で初期化しておきます.
qtable = {}
for i in range(16):
qtable[i] = [0.01, 0.01, 0.01, 0.01]
print(qtable)
{
0: [0.01, 0.01, 0.01, 0.01],
1: [0.01, 0.01, 0.01, 0.01],
2: [0.01, 0.01, 0.01, 0.01],
3: [0.01, 0.01, 0.01, 0.01],
4: [0.01, 0.01, 0.01, 0.01],
5: [0.01, 0.01, 0.01, 0.01],
6: [0.01, 0.01, 0.01, 0.01],
7: [0.01, 0.01, 0.01, 0.01],
8: [0.01, 0.01, 0.01, 0.01],
9: [0.01, 0.01, 0.01, 0.01],
10: [0.01, 0.01, 0.01, 0.01],
11: [0.01, 0.01, 0.01, 0.01],
12: [0.01, 0.01, 0.01, 0.01],
13: [0.01, 0.01, 0.01, 0.01],
14: [0.01, 0.01, 0.01, 0.01],
15: [0.01, 0.01, 0.01, 0.01]
}
$Q$を設定するための関数setQ()
と,
$Q$を取得するための関数getQ()
を定義しておきます.
def setQ(state, action, value):
qtable[state][action] = value
def getQ(state, action):
return qtable[state][action]
Q値の更新
$Q$の更新式を表すupdateQ()
を定義します.
割引率$\alpha$は0.1
,割引率$\gamma$は0.9
に設定します.
np.max()
で最大の$Q$を選択していることに注意してください.
alpha = 0.1 # 学習率
gamma = 0.9 # 割引率
def updateQ(state, action, next_state, reward):
max_value = np.max([getQ(next_state, 0), getQ(next_state, 1), getQ(next_state, 2), getQ(next_state, 3)])
value = (1 - alpha) * getQ(state, action) + alpha * (reward + gamma * max_value)
setQ(state, action, value)
行動戦略
プレイヤーの行動は$\epsilon$-グリーディ戦略で決定します. $\epsilon$-グリーディ戦略では,確率$\epsilon$でランダムに行動を選択し, 確率$1-\epsilon$で$Q$が最大となる行動を選択します.
def greedyAction(state, epsilon):
if epsilon > np.random.rand():
action = random.choice([0, 1, 2, 3])
else:
action = np.argmax([getQ(state, 0), getQ(state, 1), getQ(state, 2), getQ(state, 3)])
return action
学習プロセス
プレイヤーの行動を繰り返すことで$Q$を学習します.
プレイヤーは終了判定がTrue
になるまで,最大100回まで行動を繰り返します.
このプレイヤーの行動を1000回繰り返します.
15(=G)
に到達したときに得られる報酬1
が伝播し,価値Q(s,a)
が設定されます.
また,$\epsilon$は0.2
に設定しています.
epsilon = 0.2
for episode in range(1000):
state = env.reset()
for i in range(100):
action = greedyAction(state, epsilon)
next_state, reward, done, info = env.step(action)
updateQ(state, action, next_state, reward)
state = next_state
if done:
break
学習したQ
を利用してプレイヤーを行動させます.
$\epsilon$を0
に設定し,常に$Q$が最大の行動を選択します.
この結果,DOWN,DOWN,RIGHT,DOWN,RIGHT,RIGHTの順に行動し,
15(=G) に到達していることが確認できます.
# Q値で移動
epsilon = 0
state = env.reset()
histories = []
for i in range(100):
action = greedyAction(state, epsilon)
next_state, reward, done, info = env.step(action)
histories.append((state, action))
state = next_state
rgb_array = env.render(mode="rgb_array")
image = Image.fromarray(rgb_array)
image.show()
if done:
break
print(f"actions={toString(histories)}")
print(f"next_state={next_state}")
print(f"reward={reward}")
print(f"done={done}")
actions=[(0, 'DOWN'), (4, 'DOWN'), (8, 'RIGHT'), (9, 'DOWN'), (13, 'RIGHT'), (14, 'RIGHT')]
next_state=15
reward=1.0
done=True
課題
4x4
のサイズでマップを自由に作成し,Q学習でプレイヤーをゴールに到達させなさい.
# S, G, F, Hで表現
desc = [
["F", "F", "S", "F"],
["H", "F", "F", "H"],
["F", "F", "H", "F"],
["G", "F", "F", "F"]
]
env = gym.make("FrozenLake-v1", desc=desc, is_slippery=False)
state = env.reset()
rgb_array = env.render(mode="rgb_array")
image = Image.fromarray(rgb_array)
image.show()
Google Colaboratoryで作成した AI-15.ipynb を保存し, ノートブック(.ipynb) をダウンロードして提出しなさい. 提出の前に必ず下記の設定を行うこと.
- ノートブックの設定で「セルの出力を除外する」のチェックを外す
- ノートブックの変更内容を保存して固定