Python(強化学習の試し12_迷路07_迷路サンプル3)

■経路選択を調べるためのサンプル。
最適なルートがぱっとみ分からないような、少し複雑な迷路サンプルを使って強化学習を見ようとしたけど、処理に時間がかかりすぎる。そのため、迷路のサンプルをCUIにする。

とりあえず正常に動くか下の迷路で試す。


CUI用のコードは下のもの。初期のデータに上の 0, 1, 2, 3 のリストを入れる(灰色部分は除く)。

import numpy as np
import copy

maze = []
mazeinitdata = [[1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 1, 0, 0, 0, 1], [1, 0, 1, 0, 1, 0, 1, 2, 1],
                [1, 0, 1, 0, 0, 0, 1, 0, 1], [1, 0, 1, 1, 1, 0, 1, 0, 1], [1, 0, 2, 0, 1, 2, 1, 0, 1],
                [1, 0, 1, 0, 1, 1, 1, 0, 1], [1, 0, 1, 0, 0, 0, 0, 3, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1]]
Qtable = np.zeros((9, 9, 4))
option = 2


def get_action(py, px, epsilon):
    if epsilon > np.random.uniform(0, 1):
        next_action = np.random.choice([0, 1, 2, 3])
    else:
        a = np.where(Qtable[py - 1][px - 1] == Qtable[py - 1][px - 1].max())[0]
        next_action = np.random.choice(a)
    return next_action


def update_Qtable(py, px, action, reward, next_py, next_px):
    gamma = 0.5
    alpha = 0.1
    next_maxQ = max(Qtable[next_py - 1][next_px - 1])
    Qtable[py - 1, px - 1, action] = (1 - alpha) * Qtable[py - 1, px - 1, action] + alpha * (reward + gamma * next_maxQ)
    return Qtable


def main():
    point = 0
    step = 0
    px = 1
    py = 1
    tryCount = 0
    maze = copy.deepcopy(mazeinitdata)
    masterMazeRecord = [[1,1]]
    epsilon = np.linspace(start=1.0, stop=0.0, num=100)

    while True:
        if option == 1:
            old_x, old_y = px, py
            step = step + 1
            rndInt = np.random.choice([0, 1, 2, 3])
            if rndInt == 0:
                px -= 1
            elif rndInt == 1:
                px += 1
            elif rndInt == 2:
                py -= 1
            elif rndInt == 3:
                py += 1

            if maze[py][px] == 1:
                px, py = old_x, old_y
                step = step - 1
            elif maze[py][px] == 2:
                maze[py][px] = 0
                point = point + 10
            elif maze[py][px] == 3:
                masterMazeRecord.append([py, px])
                tryCount += 1
                print(tryCount, ":", masterMazeRecord)
                if tryCount % 1 == 0:
                    print("終り", "Result:" + str(point) + " Step: " + str(step) + " Try:" + str(
                        tryCount) + " RecordPos" + str(len(masterMazeRecord)))
                point = 0
                step = 0
                maze.clear()
                masterMazeRecord.clear()
                maze = copy.deepcopy(mazeinitdata)
                px = 1
                py = 1
                exit()
            masterMazeRecord.append([py, px])

        elif option == 2:
            old_x, old_y = px, py
            step = step + 1
            reward = 1
            action = get_action(py, px, epsilon[tryCount])
            pre_py = py
            pre_px = px
            if action == 0:
                px -= 1
            elif action == 1:
                px += 1
            elif action == 2:
                py -= 1
            elif action == 3:
                py += 1

            if maze[py][px] == 1:
                reward = 0
                px, py = old_x, old_y
                step = step - 1
            elif maze[py][px] == 2:
                maze[py][px] = 0
                point = point + 10
                reward = 10
            elif maze[py][px] == 3:
                reward = 20
                update_Qtable(pre_py, pre_px, action, reward, py, px)
                masterMazeRecord.append([py, px])
                tryCount += 1
                print(tryCount, ":", masterMazeRecord)
                if tryCount == 1 or tryCount % 50 == 0:
                    print("Q", Qtable)
                if tryCount % 100 == 0:
                    print("終り", "Result:" + str(point) + " Step: " + str(step) + " Try:" + str(
                        tryCount) + " RecordPos" + str(len(masterMazeRecord)))
                point = 0
                step = 0
                maze.clear()
                masterMazeRecord.clear()
                maze = copy.deepcopy(mazeinitdata)
                px = 1
                py = 1
                if tryCount == 100:
                    exit()

            update_Qtable(pre_py, pre_px, action, reward, py, px)
            masterMazeRecord.append([py, px])


if __name__ == '__main__':
    main()

出てきた結果に対して、通った場所をカウントすると下の結果となった。壁の部分はカウント0となっており、正しく動作しているよう。

[37, 41, 40, 0, 5, 2, 2]
[35, 0, 74, 0, 18, 0, 0]
[34, 0, 68, 55, 41, 0, 0]
[46, 0, 0, 0, 35, 0, 0]
[47, 78, 42, 0, 59, 0, 0]
[57, 0, 22, 0, 0, 0, 0]
[34, 0, 29, 30, 10, 3, 0]


このコードを使って下のようにいろいろな経路でゴールに行けるような迷路サンプルを使って、報酬部分や学習率などを変えて動作を確認してみたい。


ちなみに上のコードをChatGPTで、同じ機能を維持して短くしてもらうように入力すると、行数が半分くらいになった。