我们知道强化学习中最重要的就是状态转移公式,也成为Bellman Equation҅,公式如下:
其中Q是一个二维的矩阵,用于记录在不同状态下采取不同动作所获得的预期累计奖励值(本文理解为探索最优路径时累计的分数)。每一行()表示状态,每一列(
)表示动作,
是奖励表,
表示当前状态在各个动作上的奖励分数,
为一个(0,1)之间的常数,用于确定后续的奖励对现阶段动作的影响权重。
表示下一步的状态与位置,而
表示下一步状态与各项动作对应奖励值,通过max()函数获取最大值并相加。
本文通过一个简单路径游戏来介绍该方法。该游戏就是从loc 0块 出发,通过中间的块,最终抵达loc 7 块通关,如下图所示:
如果通过肉眼,我们一眼能看出,从loc 0 块出发,经过loc 2 块、loc 4 块、loc 6 块最终抵达loc 7块时最安全且最合适的。但是,如果块的连接更加复杂,数量更多,是不是就不好判断了呢。
接下来,通过Bellman Equation҅的基本原理,实现最有路径的探索。
首先,导入需要用到的模块。
import numpy as np
import random
然后,根据图设置奖励矩阵,每一行分别表示从开始的loc0到最后的loc7上、下、左、右、不东五个方向上的奖励值,例如loc1,其不能向左和向上,我们将其设置为0,向下到达危险块,设置-10,向右到达正常块,由于花费了时间,所以设置为-1,当到达通关块,设置得分为30,通关。最终得到如下奖励矩阵。
reward = np.array([[0, -1, 0, 0, -1],
[0, -10, 0, -1, -1],
[-1, -1, -1, 0, -1],
[-1, 0, 0, -1, -10],
[0, 0, -10, -1, -1],
[0, -1, -1, 0, -10],
[0, 30, 0, 0, -1],
[0, 0, 0, 0, 30]
])
接着,构建转移矩阵,其记录一个块能转移到的块的编号(也是按上、下、左、右、不动五个反向确定的),方向上无法转移到的填-1。
transition_matrix = np.array([[-1, 2, -1, -1, 0],
[-1, 3, -1, 2, 1],
[0, 4, 1, 0, 2],
[1, -1, -1, 4, 3],
[-1, -1, 3, 6, 4],
[-1, 6, 2, -1, 5],
[-1, 7, -1, -1, 6],
[-1, -1, -1, 6, 7]])
创建Q矩阵用于存放奖励分数以推测最优路线,设置bellman equation中的 gamma。以及一个块能有效移动的移动矩阵valid_move_matrix,其根据能移动的方向填入值,例如loc1块,只能向右与向下移动,则可以建立按上、下、左、右不动填入值1,3,4。
gamma = 0.8
Q_matrix = np.zeros((8, 5))
valid_move_matrix = [[1, 4], [1, 3, 4], [0, 1, 2, 4], [0, 3, 4], [2, 3, 4], [1, 2, 4], [1, 4], [4]]
开始训练,以获取最佳路径。
for e in range(10):
current_state = 0 #初始化当前位置为0,即loc0,开始位置。
while current_state != 7: #在到达loc7之前需要不断循环。
action = random.choice(valid_move_matrix[current_state]) #获取一个当前位置能去的块的索引
net_state = transition_matrix[current_state][action] # 获取去往块的索引
future_rewards = [] #用于存放一个块各个方向奖励值的中间变量
for action_nxt in valid_move_matrix[net_state]:
future_rewards.append(Q_matrix[net_state][action_nxt])
q_state = reward[current_state][action] + gamma * max(future_rewards) #bellman equation 计算奖励矩阵Q中的元素值
Q_matrix[current_state][action] = q_state #赋值
current_state = net_state #更新当前位置,进行下一次循环
print("Episode:{},q matrix:{}".format(e + 1, Q_matrix))
最后一次输出如下:
Episode:10,q matrix:[[ 0. 12.92 0. 0. 9.336]
[ 0. 3.92 0. 12.92 9.336]
[ 9.336 17.4 9.336 0. 12.92 ]
[ 9.336 0. 0. 17.4 3.92 ]
[ 0. 0. 3.92 23. 17.4 ]
[ 0. 0. 0. 0. 0. ]
[ 0. 30. 0. 0. 23. ]
[ 0. 0. 0. 0. 0. ]]
从输出结果可以看出,在每一行最大值对应的移动方向(动作),即为最合适在该块处的移动方向(动作)。然后标出所有最适合移动的反向,能从loc 0 块到loc 7 块的 仅有依次经过loc 2 块、loc 4 块、loc 6 块能实现。
大家也可以自己绘制一个块图,然后通过上述原理实现最优路径分析。