Self Reference Ngin

アウトプットの練習・テクノロジーについて

Q-Learning学習器を作って強化学習を理解したい

注意

勉強中のためあまり正確ではありませんのでご容赦ください。

この記事の目的

  • 『これからの強化学習』1.1 ~ 1.3までを勉強
  • Q-Learningを実装したい

用語

行動する主体・・・エージェント(agent)
はたらきかけられる対象・・・環境(enviroment)
エージェントが環境に行う働きかけ・・・行動(action)
エージェントが行動することで変化する環境の要素・・・状態(state)
エージェントの行動の結果与えられる指標・・・報酬(reward)
エージェントが行動を決定するためのルール・・・方策(policy)
エージェントの一連の行動の後、最終的に得られる報酬全てを含めた結果・・・収益(return)

強化学習って?

対象について不完全な知識しかなく、対象への働きかけによって観測できることが変わってくる場合において、試行錯誤を繰り返しながら最適な行動を学習することで問題を解く理論のこと。 したがって、最適な行動=最も良い方策(最適方策)を探し当てることが強化学習の目的となる。

最適方策ってどうやって決めるの?

最適方策を決めるためには、方策を比較できるようにしなければならない。そこで、 { \displaystyle
} \begin{align*} Q^\pi(s, a) = \mathbb{E}^\pi [G_{t+1} \mid S_t = s, A_t = a ] \end{align*}

の値を状態 s及び行動 a行動価値とよび、 Q^\pi(s, a)行動価値関数とよぶ。 \piは方策、Gは収益を表す。最適方策のもとでの行動価値関数を、 { \displaystyle
} \begin{align*} Q^*(s, a) = \max_\pi Q^\pi (s, a) \end{align*}

とし、これを最適行動価値関数とよぶ。方策の良さを評価するためには、その方策のもとでの価値関数を求めることが必要となる。

価値関数を求めるための手法

具体的に価値関数を求めるためには、現在の状態と行動についての価値と、一時刻後の状態についての価値のあいだの関係を利用して現在の状態・行動についての価値を逐次更新していく必要がある。

  • Sarsa
    事前に定められたある方策 \piのもとでの行動価値関数を学習する手法。

  • Q-Learning 最適行動価値関数、すなわちエージェントがすべての場所で理想的な行動をした場合の方策を推定する手法。

具体的なアルゴリズムはこちらが詳しい yamaimo.hatenablog.jp

Q-Learningを試す

コードはこちらのブログを大いに参照しました

www.jonki.net

例題:無人島(『これからの機械学習』pp32のケースを引用)

この環境の状態集合の要素は,  s_1:寝起きしている洞窟,  s_2:遠回り,  s_3:近道(岩場),  s_4:水場となる. 行動集合の要素は, a_1:近道の経路を進む行動, a_2:遠回りの経路を進む行動, となる. 近道経路( s_3経由)で水場に到着すれば最も良い(報酬5を得る)が, ここは岩場であり, 間違った行動( a_2)をとると怪我をする(報酬-100を得る). 遠回り経路( s_2)経由では歩きやすく( s_2に着いた時点で報酬1を得る), 間違った行動(この場合はa_1)をとっても大きな問題にはならない(報酬-1を得る)が、水場に到着したときの良さは少し(報酬1を得る)である.

コード

import numpy as np
import random

# 報酬行列
R = np.array([
    [0, 1],
    [-1, 1],
    [5, -100],
    [0, 0]
    ])

# Q値
Q = np.zeros((4, 2))

# 割引率
Gamma = 0.8

# 初期状態
state = 0

# エピソード
episode = 1

# 状態遷移関数
def shiftState(state, action):
    if state is 0:
        if action == 0:
            return 2
        return 1
    elif state is 1:
        if action == 0:
            return 0
        return 3
    elif state is 2:
        if action == 0:
            return 3
        return 0
    else:
        return

# t+1のアクションのうち最大のQ値を取得
def fetchMaxQvalueOfNextState(next_state, action_menu):
    return max([Q[next_state][i] for i in action_menu])

# Q学習
def learnQ(R, Q, Gamma, state, episode):
    
    while episode <= 10:
        print("episode is %d" %episode)
        print("state is %d" % state)
        action_menu = [0, 1]
        action = random.choice(action_menu)
        print("action is %d" %action)
        next_state = shiftState(state, action)
        print("next state is %d" %next_state)
        max_Q_next_sa = fetchMaxQvalueOfNextState(next_state, action_menu)
        Q[state, action] = R[state, action] + Gamma * max_Q_next_sa

        print(Q)

        state = next_state

        if next_state is 3:
            episode = episode + 1
            if episode is 11:
                print("Finish!!")
                print(Q)
            else:
                print("next episode is %d" %episode)
            state = 0
            
if __name__ == "__main__":
    learnQ(R, Q, Gamma, state, episode)
    Q

実行してみた結果

[[  4.     2.76]
 [  2.2    1.  ]
 [  5.   -96.8 ]
 [  0.     0.  ]]

こんな行列になって収束した。  s_1a_1 s_3 a_1の値が高いので、これを頼りにエージェントを走らせれば一応最適解になるっぽい。

感想

報酬行列の値を変えていろいろ試すと最適解が変化していって面白い(小学生)
実際にエージェントを走らせてみないとどうにも結果がわからんですね。
次回はもうちょっと複雑なケースを実装して走らせてみようかと思います。
サンキュー