使用Gym与keras_rl构建DQN时动作输出异常问题求助
问题根源与解决方案
看起来你在动作空间定义、DQN配置和动作含义理解上出现了几个关键偏差,导致策略返回的0/1动作和你预期的[100,200]数值不匹配。下面一步步拆解问题并给出修正方案:
核心问题分析
- 动作空间定义错误:你需要的是智能体做出「提示/不提示」的二元决策,但你把
action_space设成了连续的Box(100,200),这和模型输出的2个离散动作(softmax层)完全不兼容。 - DQN参数配置矛盾:
nb_actions = env.action_space.shape[0]得到的是1(因为Box空间的维度是1),但你的模型最后一层是2个神经元,这直接导致DQN的动作逻辑混乱。 - 动作含义误解:策略返回的0/1是离散动作的索引,不是你要的区间数值——你混淆了「动作(智能体的决策)」和「观测(输入给智能体的数值)」的概念。
分步修正方案
1. 修正环境的动作空间
你需要的是离散动作空间,对应「不提示」和「提示」两个决策:
# 替换原有的action_space定义 self.action_space = spaces.Discrete(2) # 0=不提示,1=提示 # 观测空间保持不变,因为智能体需要观测当前的数值 self.observation_space = spaces.Box(low=np.array([100]), high=np.array([200]), dtype=np.int32)
2. 修正DQN智能体的配置
- 调整
nb_actions为离散动作的数量:
nb_actions = env.action_space.n # 现在返回2,和模型输出匹配
- 修正DQNAgent的初始化参数(注意你之前写错了
model=env.model,应该用自己定义的Sequential模型):
dqn = DQNAgent( model=model, # 这里是你定义的Sequential模型,不是env.model memory=memory, policy=policy, nb_actions=nb_actions, nb_steps_warmup=10, target_model_update=1e-2 )
3. 正确处理step()函数中的动作
现在策略返回的0或1就是你需要的决策,在step()里这样处理:
def step(self, action): # 假设当前观测值存在self.current_value中(100-200之间的整数) quantile = (self.current_value - 100) / 100.0 # 转换为0-1的分位数 # 计算奖励 if 0 <= quantile <= 0.1 or 0.9 <= quantile <= 1.0: reward = 1 else: reward = -1 # 根据动作执行对应操作 if action == 1: # 这里写提示逻辑,比如打印或触发告警 print(f"提示:当前数值{self.current_value}接近区间边界") # 处理步数与终止条件 self.step_count += 1 done = self.step_count >= self.max_steps # 生成下一个观测值(按你的需求随机生成或按规则生成) self.current_value = np.random.randint(100, 201) next_state = np.array([self.current_value]) return next_state, reward, done, {}
4. 验证模型输出匹配
你的模型最后一层Dense(2, activation='softmax')对应2个离散动作的概率分布,和修正后的nb_actions=2完全匹配,BoltzmannQPolicy会根据概率选择0或1的动作,这就符合你「在边界区间提示」的需求了。
额外注意点
- 不要混淆「动作」和「观测」:动作是智能体的决策(提示/不提示),观测是智能体用来做决策的输入(当前的100-200数值)。
- 训练时确保环境能正确生成下一个观测值,奖励机制严格遵循你设定的规则,这样智能体才能快速学到边界判断的逻辑。
内容的提问来源于stack exchange,提问作者Yaniv Sheffer
相关产品推荐
相关产品推荐

