基于 Q - learning 算法的迷宫导航
这段 Python 代码实现了一个基于 Q - learning 算法的迷宫导航系统。代码通过定义迷宫环境、实现 Q - learning 算法来训练智能体,使其能够在迷宫中找到从起点到终点的最优路径,同时利用训练好的 Q 表来测试智能体的导航能力。
在这个代码实现的迷宫环境和 Q-learning 算法中, Q 表存储的是每个状态(即迷宫中的每个格子位置)下对于每个可能动作(上、下、左、右四个方向)的 Q 值。
迷宫的大小由 size 参数决定,状态空间是由 size 确定的所有格子位置的集合,即 [(i, j) for i in range(size) for j in range(size)] ,动作空间固定为 ['up', 'down', 'left', 'right'] 这四个动作。
因此,总的 Q 值的数量就是状态空间中状态的数量(也就是格子的个数,等于 size * size )乘以动作的数量(这里是 4) ,即 size * size * 4 个 Q 值。每个状态都对应着四个动作的 Q 值,算法的目的就是通过不断的学习和更新这些 Q 值,找到从起始状态到目标状态的最优策略。
在 Q-learning 算法中, 经过不断的更新学习后,每个状态下的各个动作都有了对应的 Q 值。
当要确定最佳运行策略时,对于每个状态,我们会选择具有最大 Q 值的那个动作。因为最大的 Q 值意味着从这个状态执行该动作,在后续过程中能获得相对更多的累计奖励,也就是更优的选择。
从起始状态开始,不断按照每个状态下最大 Q 值对应的动作移动,最终形成的路径就是智能体在当前学习成果下找到的近似最佳运行策略。
模块导入
python
import numpy as np
导入numpy
库,它是 Python 中用于科学计算的基础库,在代码中主要用于生成随机数以及数值计算。
迷宫环境类 MazeEnvironment
类初始化 __init__
方法
python
class MazeEnvironment:
def __init__(self, size=4):
self.size = size
self.state_space = [(i, j) for i in range(size) for j in range(size)]
self.action_space = ['up', 'down', 'left', 'right']
# 定义障碍物和目标位置
self.obstacles = [(1, 2), (2, 1)] # 障碍物的位置
self.goal = (size - 1, size - 1) # 终点
# 初始状态设置为左上角
self.start = (0, 0)
self.reset()
- 功能:初始化迷宫环境的各种属性。
- 参数:
size
:迷宫的大小,默认为 4x4 的迷宫。
- 属性说明:
size
:迷宫的边长。state_space
:一个列表,包含迷宫中所有可能的状态(位置),通过嵌套循环生成。action_space
:一个列表,包含智能体可以采取的所有动作,即向上、向下、向左、向右移动。obstacles
:一个列表,存储迷宫中障碍物的位置。goal
:迷宫的终点位置,位于迷宫的右下角。start
:迷宫的起点位置,位于迷宫的左上角。- 调用
reset
方法将环境重置到初始状态。
重置环境 reset
方法
python
def reset(self):
"""重置环境到初始状态"""
self.current_state = self.start
return self.current_state
- 功能:将环境的当前状态重置为起点位置,并返回该状态。
- 返回值:当前状态(起点位置)。
执行动作 step
方法
python
def step(self, action):
"""执行一步操作,并返回下一状态、奖励以及是否完成标志"""
row, col = self.current_state
if action == 'up': row -= 1
elif action == 'down': row += 1
elif action == 'left': col -= 1
elif action == 'right':col += 1
next_state = (row, col)
# 检查边界条件
if not (0 <= row < self.size and 0 <= col < self.size):
next_state = self.current_state # 超出边界的移动无效
reward = -1 # 默认每步都有负奖励鼓励快速达到目标
done = False
if next_state in self.obstacles:
reward = -10 # 碰撞障碍物给予较大惩罚
elif next_state == self.goal:
reward = 10 # 达到目标给予正向奖励
done = True
self.current_state = next_state
return next_state, reward, done
- 功能:根据智能体选择的动作,更新环境的状态,并返回下一状态、奖励和是否完成的标志。
- 参数:
action
:智能体选择的动作,取值为'up'
、'down'
、'left'
、'right'
之一。
- 步骤说明:
- 根据动作更新当前位置的行和列。
- 检查更新后的位置是否超出迷宫边界,如果超出则将下一状态设置为当前状态。
- 初始化奖励为 -1,鼓励智能体尽快到达终点。
- 如果下一状态是障碍物,给予 -10 的惩罚;如果是终点,给予 10 的奖励并将完成标志设置为
True
。 - 更新当前状态为下一状态,并返回下一状态、奖励和完成标志。
Q - learning 算法函数 q_learning
python
def q_learning(env, episodes=500, alpha=0.8, gamma=0.95, epsilon=0.1):
# 初始化 Q 表
q_table = {}
for state in env.state_space:
q_table[state] = {action: 0 for action in env.action_space}
rewards_per_episode = []
for episode in range(episodes):
total_reward = 0
current_state = env.reset()
while True:
# ε-greedy 策略选择动作
if np.random.uniform(0, 1) < epsilon:
action = np.random.choice(env.action_space) # 探索
else:
action = max(q_table[current_state], key=q_table[current_state].get) # 利用
next_state, reward, done = env.step(action)
# 更新 Q 值
best_next_action = max(q_table[next_state], key=q_table[next_state].get)
td_target = reward + gamma * q_table[next_state][best_next_action]
td_error = td_target - q_table[current_state][action]
q_table[current_state][action] += alpha * td_error
total_reward += reward
current_state = next_state
if done:
break
rewards_per_episode.append(total_reward)
return q_table, rewards_per_episode
- 功能:实现 Q - learning 算法,训练智能体在迷宫环境中找到最优策略。
- 参数:
env
:迷宫环境实例。episodes
:训练的回合数,默认为 500。alpha
:学习率,控制 Q 值更新的步长,默认为 0.8。gamma
:折扣因子,衡量未来奖励的重要性,默认为 0.95。epsilon
:探索率,用于 ε - greedy 策略,默认为 0.1。
- 步骤说明:
- 初始化 Q 表:创建一个字典
q_table
,键为状态,值为另一个字典,存储该状态下每个动作的 Q 值,初始值都为 0。 - 训练循环:进行
episodes
个回合的训练。
- 在每个回合开始时,重置环境并初始化总奖励为 0。
- 使用 ε - greedy 策略选择动作:以
epsilon
的概率随机选择动作(探索),以1 - epsilon
的概率选择 Q 值最大的动作(利用)。 - 执行动作,获取下一状态、奖励和完成标志。
- 更新 Q 值:计算时间差分目标(TD target)和时间差分误差(TD error),并根据学习率更新当前状态 - 动作对的 Q 值。
- 累加总奖励,更新当前状态。
- 如果达到终点,结束当前回合。
- 返回结果:返回训练好的 Q 表和每个回合的总奖励列表。
- 初始化 Q 表:创建一个字典
测试智能体函数 test_agent
python
def test_agent(env, q_table):
current_state = env.reset()
path = [current_state]
while True:
action = max(q_table[current_state], key=q_table[current_state].get)
next_state, _, done = env.step(action)
path.append(next_state)
if done:
break
current_state = next_state
return path
- 功能:使用训练好的 Q 表测试智能体在迷宫中的导航能力,记录智能体走过的路径。
- 参数:
env
:迷宫环境实例。q_table
:训练好的 Q 表。
- 步骤说明:
- 重置环境并初始化路径列表,将起点添加到路径中。
- 在循环中,根据 Q 表选择 Q 值最大的动作。
- 执行动作,获取下一状态和完成标志,并将下一状态添加到路径中。
- 如果达到终点,结束循环。
- 返回智能体走过的路径。
主程序
python
# 创建环境实例并运行 Q-Learning
env = MazeEnvironment(size=4)
q_table, _ = q_learning(env)
print("最终的 Q 表:")
for state, actions in q_table.items():
print(f"{state}: {actions}")
path = test_agent(env, q_table)
print("智能体走过的路径:", path)
- 功能:创建迷宫环境实例,调用
q_learning
函数训练智能体,打印最终的 Q 表,然后调用test_agent
函数测试智能体,并打印智能体走过的路径。
通过以上步骤,代码实现了智能体在迷宫环境中通过 Q - learning 算法学习最优策略,并利用该策略找到从起点到终点的路径。
完整代码
import numpy as np
class MazeEnvironment:
def __init__(self, size=4):
self.size = size
self.state_space = [(i, j) for i in range(size) for j in range(size)]
self.action_space = ['up', 'down', 'left', 'right']
# 定义障碍物和目标位置
self.obstacles = [(1, 2), (2, 1)] # 障碍物的位置
self.goal = (size - 1, size - 1) # 终点
# 初始状态设置为左上角
self.start = (0, 0)
self.reset()
def reset(self):
"""重置环境到初始状态"""
self.current_state = self.start
return self.current_state
def step(self, action):
"""执行一步操作,并返回下一状态、奖励以及是否完成标志"""
row, col = self.current_state
if action == 'up': row -= 1
elif action == 'down': row += 1
elif action == 'left': col -= 1
elif action == 'right':col += 1
next_state = (row, col)
# 检查边界条件
if not (0 <= row < self.size and 0 <= col < self.size):
next_state = self.current_state # 超出边界的移动无效
reward = -1 # 默认每步都有负奖励鼓励快速达到目标
done = False
if next_state in self.obstacles:
reward = -10 # 碰撞障碍物给予较大惩罚
elif next_state == self.goal:
reward = 10 # 达到目标给予正向奖励
done = True
self.current_state = next_state
return next_state, reward, done
def q_learning(env, episodes=500, alpha=0.8, gamma=0.95, epsilon=0.1):
# 初始化 Q 表
q_table = {}
for state in env.state_space:
q_table[state] = {action: 0 for action in env.action_space}
rewards_per_episode = []
for episode in range(episodes):
total_reward = 0
current_state = env.reset()
while True:
# ε-greedy 策略选择动作
if np.random.uniform(0, 1) < epsilon:
action = np.random.choice(env.action_space) # 探索
else:
action = max(q_table[current_state], key=q_table[current_state].get) # 利用
next_state, reward, done = env.step(action)
# 更新 Q 值
best_next_action = max(q_table[next_state], key=q_table[next_state].get)
td_target = reward + gamma * q_table[next_state][best_next_action]
td_error = td_target - q_table[current_state][action]
q_table[current_state][action] += alpha * td_error
total_reward += reward
current_state = next_state
if done:
break
rewards_per_episode.append(total_reward)
return q_table, rewards_per_episode
# 创建环境实例并运行 Q-Learning
env = MazeEnvironment(size=4)
q_table, _ = q_learning(env)
print("最终的 Q 表:")
for state, actions in q_table.items():
print(f"{state}: {actions}")
def test_agent(env, q_table):
current_state = env.reset()
path = [current_state]
while True:
action = max(q_table[current_state], key=q_table[current_state].get)
next_state, _, done = env.step(action)
path.append(next_state)
if done:
break
current_state = next_state
return path
path = test_agent(env, q_table)
print("智能体走过的路径:", path)