(初探)强化学习路径规划的理论基础与代码实现
一、强化学习路径规划的核心理论
1.1 马尔可夫决策过程(MDP)框架
理论基础:
路径规划问题可以建模为马尔可夫决策过程(Markov Decision Process, MDP),由五元组(S, A, P, R, γ)定义。其中,S(状态空间)表示智能体所在的位置和环境信息(如坐标、传感器数据);A(动作空间)用于表示可执行的移动指令(如前进、转向);P(状态转移概率),我们通常使用P(s'|s,a)表示在状态s执行动作a后转移到状态s'的概率;R(奖励函数),用R(s,a,s')给出状态转移的即时奖励;γ(折扣因子)用于权衡当前奖励与未来奖励的重要性(通常取0.9-0.99)。
代码映射:
class GridWorldEnv(gym.Env):
def __init__(self):
self.state_space = [...] # S
self.action_space = [...] # A
self.transition_matrix = [...] # P
self.reward_function = [...] # R
self.gamma = 0.95 # γ
1.2 贝尔曼方程与价值函数
理论解释:
价值函数V(s)表示从状态s开始遵循策略π的预期回报:Vπ(s) = Eπ[∑γ^t R_t | S_0 = s]
贝尔曼方程给出了价值函数的递归形式:Vπ(s) = ∑π(a|s)∑P(s'|s,a)[R(s,a,s') + γVπ(s')]
代码实现:
# Q-learning更新规则 new_q = (1 - learning_rate) * current_q + \learning_rate * (reward + gamma * max_next_q)
二、Q-Learning算法深度解析
2.1 Q表学习原理
理论说明:
Q-learning是一种无模型(model-free)的时序差分(TD)算法,通过学习动作价值函数Q(s,a)来找到最优策略。更新规则为:Q(s,a) ← Q(s,a) + α[r + γ max_a' Q(s',a') - Q(s,a)]
其中α是学习率,γ是折扣因子。
代码细节:
def update_q_table(self, state, action, reward, new_state):
# 当前状态的Q值
current_q = self.q_table[state[0], state[1], action]
# 下一状态的最大Q值(最优未来价值)
max_next_q = np.max(self.q_table[new_state[0], new_state[1]])
# 应用Q-learning更新公式
new_q = (1 - self.lr) * current_q + \
self.lr * (reward + self.discount * max_next_q)
# 更新Q表
self.q_table[state[0], state[1], action] = new_q
2.2 探索-利用权衡
理论分析:
ε-greedy策略是平衡探索与利用的经典方法:
(1)以概率ε随机选择动作
(2)以概率1-ε选择当前最优动作
代码实现:
def get_action(self, state):
# 探索阶段:随机动作
if np.random.uniform(0, 1) < self.exploration_rate:
return self.env.action_space.sample()
# 利用阶段:选择Q值最高的动作
return np.argmax(self.q_table[state[0], state[1]])
参数设置建议:
-
初始ε:1.0(完全探索)
-
最终ε:0.01(基本不探索)
-
衰减率:0.995(每个episode衰减)
三、深度Q网络(DQN)技术详解
3.1 神经网络架构设计
理论背景:
DQN使用神经网络近似Q函数,解决传统Q-learning在高维状态空间的"维度灾难"问题。网络输入为状态,输出为各动作的Q值。
代码实现:
class DQN(nn.Module):
def __init__(self, input_shape, n_actions):
super().__init__()
# 卷积层提取空间特征
self.conv = nn.Sequential(
nn.Conv2d(input_shape[2], 32, kernel_size=3, stride=1),
nn.ReLU(),
nn.Conv2d(32, 64, kernel_size=3, stride=1),
nn.ReLU()
)
# 计算卷积输出尺寸
conv_out_size = self._get_conv_out(input_shape)
# 全连接层决策
self.fc = nn.Sequential(
nn.Linear(conv_out_size, 256),
nn.ReLU(),
nn.Linear(256, n_actions)
)
3.2 经验回放机制
理论意义:打破数据间的时序相关性;提高数据利用率;稳定训练过程
代码解析:
class ReplayBuffer:
def __init__(self, capacity):
self.buffer = deque(maxlen=capacity) # 固定大小的循环队列
def push(self, transition):
"""存储(s,a,r,s',done)五元组"""
self.buffer.append(transition)
def sample(self, batch_size):
"""随机采样一批经验"""
return random.sample(self.buffer, batch_size)
def __len__(self):
return len(self.buffer)
训练循环节选:
# 收集经验
state = env.reset()
action = agent.select_action(state)
next_state, reward, done, _ = env.step(action)
memory.push((state, action, reward, next_state, done))
# 从记忆中采样训练
if len(memory) > batch_size:
transitions = memory.sample(batch_size)
batch = Transition(*zip(*transitions))
# 计算当前Q值和目标Q值
current_q = model(batch.state).gather(1, batch.action)
next_q = target_model(batch.next_state).max(1)[0].detach()
expected_q = batch.reward + (1 - batch.done) * gamma * next_q
# 计算损失并反向传播
loss = F.mse_loss(current_q, expected_q.unsqueeze(1))
optimizer.zero_grad()
loss.backward()
optimizer.step()
四、奖励函数设计原则
4.1 多目标奖励设计
理论指导:
良好的奖励函数应:引导智能体快速到达目标;避免碰撞障碍物;鼓励高效路径;保持信号尺度合理
代码示例:
def calculate_reward(self, new_pos):
# 基础奖励组件
goal_reward = 10.0 if new_pos == self.goal_pos else 0.0
collision_penalty = -2.0 if self.obstacles[new_pos] else 0.0
# 距离奖励(鼓励靠近目标)
old_dist = np.linalg.norm(self.agent_pos - self.goal_pos)
new_dist = np.linalg.norm(new_pos - self.goal_pos)
distance_reward = (old_dist - new_dist) * 0.5
# 探索奖励(鼓励访问新区域)
visit_reward = 0.1 if new_pos not in self.visited else -0.05
self.visited.add(new_pos)
# 时间惩罚(鼓励快速决策)
time_penalty = -0.01
return goal_reward + distance_reward + collision_penalty + visit_reward + time_penalty
4.2 奖励塑形(Reward Shaping)
理论说明:通过添加中间奖励引导学习过程,潜在函数形式:
R' = R + γΦ(s') - Φ(s)
其中Φ是势能函数,通常设计为到目标的负距离。
代码实现:
def potential_function(self, pos):
"""势能函数:到目标的负距离"""
return -np.linalg.norm(pos - self.goal_pos)
def shaped_reward(self, old_pos, new_pos, base_reward):
potential = self.potential_function(new_pos)
old_potential = self.potential_function(old_pos)
return base_reward + self.gamma * potential - old_potential