强化学习中值迭代算法的python实现

1:问题描述

有一个迷宫,小人从迷宫的左上角出发,前往右下角的终点则游戏结束。迷宫中还会有一些障碍物不可以行走,求小人从起点走到终点的最优策略。

2:设置参数

grid为迷宫地图,”S“是起点,”G“是终点,”X“是障碍物。

V是每个状态的状态值函数,初始为 [ [0] *3 for _ in range(3) ]

P是状态转移概率矩阵,P中的每个元素指的是从状态S选择动作a后状态转移成S’的概率,在这个问题中状态的表示是二维的,即用坐标表示状态。

R是奖励矩阵,R中的每个元素指的是从状态S选择动作a获得的奖励。

action_dict是动作的集合。在这个问题中,动作只有上下左右四种。

import numpy as np

# 网格世界的状态矩阵
grid = np.array([
    ["S", "0", "0"],
    ["X", "0", "X"],
    ["0", "0", "G"]
])
# 防止圈走动
# 状态值函数的初始化
V = np.zeros_like(grid, dtype=np.float32)


# 定义状态转移概率矩阵和奖励矩阵
P = np.zeros((3, 3, 4, 3, 3), dtype=np.float32)  # (s, a, s')
R = np.zeros((3, 3, 4), dtype=np.float32)  # (s, a)

action_dict = {
    0: "UP",
    1: "DOWN",
    2: "LEFT",
    3: "RIGHT"
}

 3:求参数的值

首先遍历每个状态(也就是遍历每个坐标(i,j)),对于每个状态再遍历所有可能的动作。在不超出地图边界且不走到障碍物的前提下,更新next_i,next_ j,然后为P[i, j, a, next_i, next_j]赋值为1/4。#当然也可以自己设置概率

对于回报矩阵来说,如果智能体走到了终点,则reward=10,若智能体走到了障碍物,则reward=-1 且next_i 和next_ j赋值回i和j,目的就是不允许走到障碍物。若智能体走到了普通状态,奖励也为 -1,目的是防止智能体循环走动。

# 定义状态转移概率矩阵和奖励矩阵的值
for i in range(3):
    for j in range(3):
        if grid[i, j] == "X":
            # 障碍物状态
            continue
        for a in range(4):
            # 针对每个状态和动作,计算可能的下一个状态和对应的概率和奖励
            if a == 0:  # UP
                next_i = max(i - 1, 0)
                next_j = j
            elif a == 1:  # DOWN
                next_i = min(i + 1, 2)
                next_j = j
            elif a == 2:  # LEFT
                next_i = i
                next_j = max(j - 1, 0)
            elif a == 3:  # RIGHT  把规则写出来
                next_i = i
                next_j = min(j + 1, 2)
            if grid[next_i, next_j] == "X":
                # 下一个状态是障碍物状态
                next_i = i
                next_j = j
                r = -1.0
            elif grid[next_i, next_j] == "G":
                # 下一个状态是终点状态
                r = 10.0
            else:
                # 下一个状态是普通状态
                r = -1.0
            P[i, j, a, next_i, next_j] += 1.0/4
            R[i, j, a] = r

4:值迭代

首先设定折扣因子gamma和收敛阈值theta。

折扣因子是我们考虑未来收益的比例,theta是判断迭代是否收敛的阈值。

算法逻辑是,只要不收敛,就不断的迭代值函数。

每次迭代,先初始化状态差值delta,遍历每个状态,若这个状态不在终点也不在障碍物,则遍历它的四个动作,利用动作状态值函数求这个状态下采取这个动作的值函数,并将这个值函数和上一个动作的值函数进行对比,保留这个状态下最大的值函数。在每次状态变化时,更新状态值矩阵V,直到遍历完所有状态。最后,再判断值函数的变化delta是否小于阈值theta,若小于则停止迭代,最后得到的值函数矩阵V就是最优值函数

# 定义值迭代算法的超参数
gamma = 0.9  # 折扣因子
theta = 1e-5  # 收敛阈值

# 迭代更新状态值函数
while True:
    delta = 0.0   # 是什么的差值
    for i in range(3):
        for j in range(3):
            if grid[i, j] == "X" or grid[i, j] == "G":
                # 障碍物状态或终点状态,状态值为0
                continue
            v = V[i, j]
            new_v = -np.inf
            for a in range(4):
                # 计算从状态s出发,执行动作a的预期回报
                q = np.sum(P[i, j, a] * (R[i, j, a] + gamma * V))

                if q > new_v:
                    new_v = q
            V[i, j] = new_v
            delta = max(delta, abs(v - new_v))
    if delta < theta:
        break

至此,值迭代函数成功实现在走迷宫小游戏中。对于其他更复杂的场景,状态集可能是非常大的,需要用到剪枝方法,留待下次实现。

你可能感兴趣的:(python,算法,机器学习)