DQN 模型加载后性能骤降,主因是未同步保存 epsilon 探索率和经验回放记忆(memory),导致加载后仍以高随机性决策,且丧失历史经验。需统一保存模型权重、超参数状态与 replay buffer。
如何正确保存与加载 dqn 智能体以保持训练后性能:dqn 模型加载后性能骤降,主因是未同步保存 epsilon 探索率和经验回放记忆(memory),导致加载后仍以高随机性决策,且丧失历史经验。需统一保存模型权重、超参数状态与 replay buffer。
在深度强化学习中,仅保存 Keras 模型权重(如 .keras 文件)远不足以完整复现训练后的智能体行为。从您提供的代码可见,DQLAgent 类中存在两个关键未持久化的状态变量:self.epsilon(探索率)和 self.memory(经验回放缓冲区)。当调用 DQLAgent(env, model_path=...) 时,__init__ 方法会重置 epsilon = 1.0,并初始化空的 deque,即使模型权重已正确加载——这直接导致智能体在评估或继续训练时几乎完全依赖随机动作(ε-greedy 中 ε ≈ 1),性能崩塌。
✅ 正确做法是将模型、探索策略状态、经验数据三者协同序列化。以下是推荐的增强实现:
1. 完整保存/加载智能体状态(推荐使用 pickle + tf.keras.models.save_model)
import pickle
import tensorflow as tf
from tensorflow.keras.models import load_model
class DQLAgent:
# ...(原有 __init__, build_model 等方法保持不变)
def save_full_state(self, model_path: str, state_path: str):
"""保存模型权重 + epsilon + memory(支持后续评估或增量训练)"""
self.model.save(model_path) # 保存 Keras 模型(含结构、权重、optimizer 状态)
with open(state_path, 'wb') as f:
pickle.dump({
'epsilon': self.epsilon,
'epsilon_min': self.epsilon_min,
'epsilon_decay': self.epsilon_decay,
'memory': list(self.memory), # deque → list 便于序列化
'gamma': self.gamma,
'learning_rate': self.learning_rate,
}, f)
def load_full_state(self, model_path: str, state_path: str):
"""完整加载:模型 + 所有运行时状态"""
self.model = load_model(model_path) # 自动兼容 optimizer 状态(若训练中保存)
with open(state_path, 'rb') as f:
state = pickle.load(f)
self.epsilon = state['epsilon']
self.epsilon_min = state['epsilon_min']
self.epsilon_decay = state['epsilon_decay']
self.gamma = state['gamma']
self.learning_rate = state['learning_rate']
self.memory = deque(state['memory'], maxlen=2000)2. 评估阶段:禁用探索(关键!)
加载后若仅用于纯推理/评估(非继续训练),应显式关闭 ε-greedy 随机性,确保 100% 由网络决策:
# 加载后设置为纯贪婪策略(评估模式) agent.epsilon = 0.0 # 或 agent.epsilon = agent.epsilon_min # 后续 act() 将始终执行 np.argmax(model.predict(...))
⚠️ 注意:不要在 act() 中硬编码 if self.epsilon <= 0.01: —— 应通过外部控制 epsilon 值来切换模式,保证逻辑清晰可复现。
3. 继续训练:确保 optimizer 状态被保存(重要细节)
Keras 的 model.save() 默认不保存优化器状态(如 Adam 的动量、RMSProp 的缓存),这会导致加载后学习率“重置”,影响收敛稳定性。解决方案:
- 使用 save_format='tf'(SavedModel 格式)并确保训练中调用 model.save(..., include_optimizer=True)(默认为 True);
- 或手动保存 optimizer:
# 保存时 import tensorflow as tf tf.keras.models.save_model(self.model, model_path, include_optimizer=True)
总结与最佳实践
| 组件 | 是否必须保存 | 说明 |
|---|---|---|
| 模型权重 & 结构 | ✅ 是 | model.save() 或 model.save_weights() |
| epsilon 及衰减参数 | ✅ 是 | 决定探索行为,直接影响策略输出 |
| replay memory | ✅ 是(若需增量训练) | 否则训练从零开始,丢失先验经验 |
| optimizer 状态 | ✅ 强烈建议 | 避免学习率突变,保障训练连续性 |
| 环境配置(env) | ❌ 否 | 由外部重建,不应序列化 |
最终验证:加载后打印 agent.epsilon 和 len(agent.memory),确认其值与训练结束时一致;并在评估循环中固定 agent.epsilon = 0,即可复现原始性能。忽略任一状态,都可能导致“模型已加载但不会玩”的假象。


















