強化学習・Q学習

Image from Gyazo

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}")

Image from Gyazo

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()

Image from Gyazo

Google Colaboratoryで作成した AI-15.ipynb を保存し, ノートブック(.ipynb) をダウンロードして提出しなさい. 提出の前に必ず下記の設定を行うこと.

参考書籍

愛知県名古屋市にある椙山女学園大学 文化情報学部 向研究室の公式サイトです. 専門は情報科学であり,人工知能やデータベースなどの技術要素を指導しています. この公式サイトでは,授業で使用している教材を公開すると共に, ベールに包まれた女子大教員のミステリアスな日常を4コマ漫画でお伝えしていきます. サイトに関するご意見やご質問はFacebookまたはTwitterでお問い合わせください.