Python(強化学習の試し03_過去の試行3つ分で学習2)

■学習するコードの改善。
何となく学習されているようだけど結果が芳しくなかったので、学習するコードを改善する。
条件は下のもの。
・ボタン(0と1)がある状態で、どちらかを押す想定。
・0を押した後に1を押すと報酬として1が追加される。
・試行は10回。これを1エピソードとする。

過去3つ分の結果を強化学習の環境として取得する場合、8つの状況がある。3つ前、2つ前、1つ前で押した値を2進数と見なして、0~7のラベルを付ける。

前回の学習コードでは、ε-greedy法を省略していたしQ値の更新部分も正しくなかった。改善したコードが下の通り。

class GenAction():
    def __init__(self):
        self._Qtable = np.zeros((8, 2))

    def getAction(self, history, epsilon):
        val = 0
        action = 0
        if (len(history) >= 3):
            if epsilon > np.random.uniform(0, 1):
                action = np.random.choice([0, 1])
            else:
                for i in range(len(history)):
                    if len(history) - i <= 3:
                        val = val + (history[i] * 2 ** ((len(history) - i - 1)))
                        a = np.where(self._Qtable[val] == self._Qtable[val].max())[0]
                        action = np.random.choice(a)
        else:
            action = np.random.choice([0, 1])

        return action

    def updateSelectAction(self, curhistory, action, reward, history):
        gamma = 0.9
        alpha = 0.7
        val = 0
        next_val = 0
        if (len(curhistory) >= 3):
            for i in range(len(curhistory)):
                if len(curhistory) - i <= 3:
                    val = val + (curhistory[i] * 2 ** ((len(curhistory) - i - 1)))
            for i in range(len(history)):
                if len(history) - i <= 3:
                    next_val = next_val + (history[i] * 2 ** ((len(history) - i - 1)))

            next_maxQ = max(self._Qtable[next_val])
            self._Qtable[val, action] = (1 - alpha) * self._Qtable[val, action] + alpha * (
                    reward + gamma * next_maxQ)
        return self._Qtable

ここでは、ε-greedy法として1.0から0までの直線を使う。一番初めは1.0で、0~1.0からランダムな値を取得し、この閾値以下ならランダムなActionをとる。閾値以上なら、Q値に基づいたActionをとる。後の試行の方がQ値に基づいたActionとなる確率が高くなる。Q値は、縦(状況8通り)x 横(Action2通り)の行列であり、Q値に基づいたActionをとる際に、ある状況に対してQ値が高い方のActionが選択されるよう。この値は都度更新されていく。

200エピソード行い、Q値を更新した結果が下のもの。縦8×横2の行列で、左側が0を押すAction、右側が1を押すAction、上から上の表のVal 0~7 に対応する。ここで、Val が0、2、4、6の時に5.2631と1を押すActionを取る。1、3、5、7では、4.7368と0を押すActionを取る。

200分のエピソードとそれぞれのRewardの結果をグラフにすると下のようになった。0, 1の組み合わせでRewardが1追加されるので、最大は[0, 1, 0, 1, 0, 1, 0, 1, 0, 1] の5となる。Q値に基づくActionの選択は試行回数が3以上でなければできなくしているので、必ず5になるわけではないが、学習が進むにつれてRewardの成績が良くなっている。

ちなみに完全にランダムでActionを選択すると、下のグラフになった。ランダムでRewardが5になる確率は、2^8 = 256 分の1 なので、200エピソードであれば1度も出ないことは不思議ではない。

試行回数やRewardが出る条件を変えてもう少し試してみる。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です