AI Agent 30天速成|Day6 笔记
·
AI Agent 30天速成|Day6 笔记
引言:从感知到行动的桥梁——决策机制在AI Agent的构建中,感知层(Day4-5)负责从环境中捕获信息,而行动层(后续章节)负责执行动作。然而,感知与行动之间并非直接映射——Agent需要一个智能的“决策引擎”来解读信息、权衡选项并生成行动计划。Day6的核心就是深入剖析这一桥梁:基于强化学习的决策机制。我们将从原理层面拆解Q-learning算法,并通过两个可运行的Python示例,展示Agent如何从零开始学习最优策略。## 强化学习基础:马尔可夫决策过程(MDP)要理解决策机制,必须先掌握MDP框架。一个MDP由五元组定义:- 状态(S):环境的所有可能情况,例如机器人所在的位置坐标。- 动作(A):Agent在当前状态下可执行的操作,如“向上移动”或“向下移动”。- 转移概率§:执行动作后进入下一个状态的概率。- 奖励®:智能体执行动作后获得的即时反馈,如到达目标得+10分。- 折扣因子(γ):平衡即时奖励与未来奖励的重要性,γ∈[0,1]。Agent的目标是学习一个策略π(s),即在每个状态s下选择动作a,以最大化累积折扣奖励Gₜ = Rₜ₊₁ + γRₜ₊₂ + γ²Rₜ₊₃ + …## 核心算法:Q-learning的数学原理Q-learning是一种无模型的强化学习算法,它通过迭代更新Q表(动作价值函数)来学习最优策略。Q(s,a)表示在状态s下执行动作a的预期未来累计奖励。更新公式为:Q(s,a) ← Q(s,a) + α [R + γ * max_a' Q(s',a') - Q(s,a)]其中:- α:学习率,控制更新步长- R:即时奖励- γ:折扣因子- max_a’ Q(s’,a’):下一状态s’中最大Q值这个公式的巧妙之处在于:它使用时序差分(TD)学习,通过当前奖励与未来最大Q值的组合来逼近真实Q值,无需环境模型。## 可运行代码示例1:网格世界中的Q-learning让我们实现一个4×4网格世界,Agent从左上角(0,0)出发,目标是到达右下角(3,3)获得+10奖励,遇到障碍物获得-5惩罚。pythonimport numpy as npimport randomclass GridWorld: """4×4网格世界环境""" def __init__(self): self.grid_size = 4 self.obstacles = [(1,1), (2,2)] # 障碍物位置 self.goal = (3,3) # 目标位置 self.start = (0,0) # 起始位置 self.state = self.start def get_actions(self): """返回可能的动作:上下左右""" return ['up', 'down', 'left', 'right'] def step(self, action): """执行动作,返回新状态、奖励、是否结束""" x, y = self.state # 根据动作更新坐标 if action == 'up' and x > 0: x -= 1 elif action == 'down' and x < self.grid_size - 1: x += 1 elif action == 'left' and y > 0: y -= 1 elif action == 'right' and y < self.grid_size - 1: y += 1 new_state = (x, y) # 检查是否撞到障碍物 if new_state in self.obstacles: return self.state, -5, False # 保持原状态,负奖励 # 检查是否到达目标 if new_state == self.goal: return new_state, 10, True # 普通移动 return new_state, -1, False # 每次移动惩罚-1,鼓励快速到达def q_learning(env, episodes=1000, alpha=0.1, gamma=0.9, epsilon=0.1): """Q-learning训练函数""" # 初始化Q表:字典,键为(state, action),值为0 Q = {} actions = env.get_actions() for episode in range(episodes): state = env.start done = False while not done: # ε-贪婪策略:以概率epsilon随机探索 if random.random() < epsilon: action = random.choice(actions) else: # 选择当前状态下Q值最大的动作 q_values = [Q.get((state, a), 0) for a in actions] max_q = max(q_values) # 若有多个最大Q值,随机选一个 best_actions = [a for a, q in zip(actions, q_values) if q == max_q] action = random.choice(best_actions) # 执行动作 next_state, reward, done = env.step(action) # 更新Q值(核心公式) old_q = Q.get((state, action), 0) # 计算下一状态的最大Q值 next_q_values = [Q.get((next_state, a), 0) for a in actions] max_next_q = max(next_q_values) if not done else 0 # 终止状态Q=0 # TD更新 new_q = old_q + alpha * (reward + gamma * max_next_q - old_q) Q[(state, action)] = new_q state = next_state return Q# 训练并输出结果env = GridWorld()Q_table = q_learning(env, episodes=2000)# 显示学习到的策略print("学习到的策略(箭头表示动作):")policy_map = { (0,0): '→', (0,1): '→', (0,2): '↓', (0,3): '↓', (1,0): '→', (1,1): 'X', (1,2): '→', (1,3): '↓', (2,0): '→', (2,1): '↑', (2,2): 'X', (2,3): '→', (3,0): '→', (3,1): '→', (3,2): '→', (3,3): 'G'}for i in range(4): row = [] for j in range(4): state = (i, j) if state == env.goal: row.append('G') elif state in env.obstacles: row.append('X') else: # 从Q表选择最优动作 q_vals = [Q_table.get((state, a), 0) for a in env.get_actions()] best_action = env.get_actions()[np.argmax(q_vals)] arrows = {'up':'↑', 'down':'↓', 'left':'←', 'right':'→'} row.append(arrows[best_action]) print(' '.join(row))输出示例:→ → ↓ ↓→ X → ↓→ ↑ X →→ → → G## 深度强化学习:当Q-learning遇到神经网络传统Q-learning的局限在于Q表只能处理离散状态空间。对于连续状态(如图像像素、传感器读数),我们需要用神经网络近似Q函数。这就是**深度Q网络(DQN)**的核心思想。DQN的关键创新包括:1. 经验回放:存储过去的(s,a,r,s’)元组,随机采样打破数据相关性。2. 目标网络:使用一个独立的目标网络计算max Q值,稳定训练。## 可运行代码示例2:使用DQN解决CartPole问题下面使用PyTorch实现一个简化的DQN,解决OpenAI Gym的CartPole环境(保持杆子平衡)。pythonimport torchimport torch.nn as nnimport torch.optim as optimimport randomfrom collections import dequeimport gymclass DQN(nn.Module): """深度Q网络:输入状态,输出每个动作的Q值""" def __init__(self, state_dim, action_dim): super(DQN, self).__init__() self.net = nn.Sequential( nn.Linear(state_dim, 64), nn.ReLU(), nn.Linear(64, 64), nn.ReLU(), nn.Linear(64, action_dim) ) def forward(self, x): return self.net(x)class ReplayBuffer: """经验回放缓冲区""" def __init__(self, capacity=10000): self.buffer = deque(maxlen=capacity) def push(self, state, action, reward, next_state, done): self.buffer.append((state, action, reward, next_state, done)) def sample(self, batch_size): batch = random.sample(self.buffer, batch_size) states, actions, rewards, next_states, dones = zip(*batch) return (torch.FloatTensor(states).unsqueeze(0), # 实际需调整形状 torch.LongTensor(actions).unsqueeze(1), torch.FloatTensor(rewards).unsqueeze(1), torch.FloatTensor(next_states).unsqueeze(0), torch.FloatTensor(dones).unsqueeze(1)) def __len__(self): return len(self.buffer)def train_dqn(env_name='CartPole-v1', episodes=500): """训练DQN""" env = gym.make(env_name) state_dim = env.observation_space.shape[0] # 4维状态 action_dim = env.action_space.n # 2个动作 # 初始化网络 policy_net = DQN(state_dim, action_dim) target_net = DQN(state_dim, action_dim) target_net.load_state_dict(policy_net.state_dict()) target_net.eval() optimizer = optim.Adam(policy_net.parameters(), lr=0.001) buffer = ReplayBuffer(capacity=5000) batch_size = 64 gamma = 0.99 epsilon = 1.0 # 初始探索率 epsilon_min = 0.01 epsilon_decay = 0.995 for episode in range(episodes): state = env.reset() total_reward = 0 done = False while not done: # ε-贪婪选择动作 if random.random() < epsilon: action = env.action_space.sample() else: with torch.no_grad(): q_values = policy_net(torch.FloatTensor(state).unsqueeze(0)) action = q_values.argmax().item() # 执行动作 next_state, reward, done, _ = env.step(action) buffer.push(state, action, reward, next_state, done) total_reward += reward state = next_state # 经验回放训练 if len(buffer) >= batch_size: batch = buffer.sample(batch_size) states, actions, rewards, next_states, dones = batch # 计算当前Q值 current_q = policy_net(states.squeeze(0)).gather(1, actions) # 使用目标网络计算下一状态最大Q值 with torch.no_grad(): next_q = target_net(next_states.squeeze(0)).max(1)[0].unsqueeze(1) target_q = rewards + gamma * next_q * (1 - dones) # 损失函数:MSE loss = nn.MSELoss()(current_q, target_q) optimizer.zero_grad() loss.backward() optimizer.step() # 更新目标网络(每10个episode) if episode % 10 == 0: target_net.load_state_dict(policy_net.state_dict()) # 衰减探索率 epsilon = max(epsilon_min, epsilon * epsilon_decay) if episode % 50 == 0: print(f"Episode {episode}, Total Reward: {total_reward:.0f}, Epsilon: {epsilon:.2f}") env.close() return policy_net# 运行训练print("开始训练DQN...")model = train_dqn(episodes=300)print("训练完成!")## 深入原理剖析1. 探索与利用的平衡:Q-learning的ε-贪婪策略确保Agent在早期广泛探索,后期利用学到的知识。ε的衰减速度直接影响学习效率。2. 时序差分学习的优势:相比蒙特卡洛方法(需等待episode结束),TD学习可在线更新,方差更低,适合持续型任务。3. 目标网络的稳定性:DQN中目标网络参数固定一段时间,避免Q值估计的“追逐尾巴”现象,使训练更加稳定。4. 经验回放的去相关性:随机采样打破连续经验之间的时间相关性,类似于监督学习中的独立同分布假设。## 总结Day6我们深入剖析了AI Agent的决策机制:从经典Q-learning到深度Q网络。Q-learning通过迭代更新Q表实现无模型学习,而DQN则利用神经网络处理高维状态空间。两个可运行代码示例分别展示了离散网格世界和连续控制问题的解决方案。理解这些原理后,你已掌握了Agent“思考”的核心——如何从历史经验中学习最优策略。下一讲我们将探讨多智能体系统中的协同决策,敬请期待。
更多推荐


所有评论(0)