You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Keras RL构建Space Invaders智能体时遇'int'无'shape'属性错误

解决Keras RL训练Space Invaders时的AttributeError问题

问题描述

在使用Keras RL构建DQN智能体训练SpaceInvaders-v4时,执行dqn.fit()触发以下错误:

AttributeError: 'int' object has no attribute 'shape'

错误源自keras-rl2的zeroed_observation函数,具体报错行:obs[key] = np.zeros(observation[key].shape)。

错误原因

该错误核心是模型输入维度与SequentialMemory的帧堆叠逻辑不匹配,导致keras-rl2误将numpy数组类型的观测当成字典处理,进而访问shape属性失败。此外,未对Atari环境原始观测做预处理(灰度转换、尺寸压缩),也加剧了维度匹配问题。

解决方案

以下提供两种可行修复方案,推荐使用方案一(标准Atari处理流程):

方案一:使用AtariProcessor预处理观测(推荐)

AtariProcessor是keras-rl2专为Atari环境设计的预处理工具,自动完成灰度转换、尺寸压缩、帧堆叠等操作,确保观测数据符合模型输入要求。

修改代码步骤:

  1. 导入AtariProcessor:
from rl.processors import AtariProcessor
  1. 调整模型构建函数,适配预处理后的观测形状(84x84灰度图,4帧堆叠):
def build_model(width, height, channels, actions):
    model = Sequential()
    # 输入形状对应预处理后的84x84x4(4帧灰度图堆叠)
    model.add(Convolution2D(32, (8,8), strides=(4,4), activation='relu', input_shape=(height, width, channels)))
    model.add(Convolution2D(64, (4,4), strides=(2,2), activation='relu'))
    model.add(Convolution2D(64, (3,3), activation='relu'))
    model.add(Flatten())
    model.add(Dense(512, activation='relu'))
    model.add(Dense(256, activation='relu'))
    model.add(Dense(actions, activation='linear'))
    return model
  1. 调整智能体构建函数,添加processor参数并增大记忆库容量:
def build_agent(model, actions):
    policy = LinearAnnealedPolicy(EpsGreedyQPolicy(), attr='eps', value_max=1., value_min=.1, value_test=.2, nb_steps=10000)
    # window_length设为4,与预处理的帧堆叠数一致
    memory = SequentialMemory(limit=100000, window_length=4)
    processor = AtariProcessor()
    dqn = DQNAgent(model=model, memory=memory, policy=policy,
                  enable_dueling_network=True, dueling_type='avg', 
                   nb_actions=actions, nb_steps_warmup=1000,
                   processor=processor
                  )
    return dqn
  1. 修改模型初始化代码,使用预处理后的观测尺寸:
model = build_model(84, 84, 4, actions)

方案二:直接匹配模型输入维度与帧堆叠逻辑

若不使用预处理工具,需确保模型输入形状与SequentialMemory的window_length严格匹配:

  1. 调整模型输入形状,将帧堆叠维度放在最后(适配TensorFlow的channels_last默认设置):
def build_model(height, width, channels, actions):
    model = Sequential()
    # 输入形状为(高度, 宽度, 通道数, 堆叠帧数)
    model.add(Convolution2D(32, (8,8), strides=(4,4), activation='relu', input_shape=(height, width, channels, 3)))
    model.add(Convolution2D(64, (4,4), strides=(2,2), activation='relu'))
    model.add(Convolution2D(64, (3,3), activation='relu'))
    model.add(Flatten())
    model.add(Dense(512, activation='relu'))
    model.add(Dense(256, activation='relu'))
    model.add(Dense(actions, activation='linear'))
    return model
  1. 保持SequentialMemory的window_length为3,与模型输入的堆叠帧数一致:
memory = SequentialMemory(limit=10000, window_length=3)

额外建议

  • 若仍存在兼容性问题,可降低TensorFlow版本至2.8.0(keras-rl2 1.0.4对高版本TensorFlow支持有限)。
  • 增大SequentialMemory的limit参数(如100000),提升智能体的经验学习能力。

完整修改后代码示例

import gym 
import random
import numpy as np
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Flatten, Convolution2D
from tensorflow.keras.optimizers import Adam
from rl.agents import DQNAgent
from rl.memory import SequentialMemory
from rl.policy import LinearAnnealedPolicy, EpsGreedyQPolicy
from rl.processors import AtariProcessor

def build_model(width, height, channels, actions):
    model = Sequential()
    model.add(Convolution2D(32, (8,8), strides=(4,4), activation='relu', input_shape=(height, width, channels)))
    model.add(Convolution2D(64, (4,4), strides=(2,2), activation='relu'))
    model.add(Convolution2D(64, (3,3), activation='relu'))
    model.add(Flatten())
    model.add(Dense(512, activation='relu'))
    model.add(Dense(256, activation='relu'))
    model.add(Dense(actions, activation='linear'))
    return model

def build_agent(model, actions):
    policy = LinearAnnealedPolicy(EpsGreedyQPolicy(), attr='eps', value_max=1., value_min=.1, value_test=.2, nb_steps=10000)
    memory = SequentialMemory(limit=100000, window_length=4)
    processor = AtariProcessor()
    dqn = DQNAgent(model=model, memory=memory, policy=policy,
                  enable_dueling_network=True, dueling_type='avg', 
                   nb_actions=actions, nb_steps_warmup=1000,
                   processor=processor
                  )
    return dqn

env = gym.make('SpaceInvaders-v4')
actions = env.action_space.n
print(env.unwrapped.get_action_meanings())

model = build_model(84, 84, 4, actions)
model.summary()

dqn = build_agent(model, actions)
dqn.compile(Adam(learning_rate=1e-4))

dqn.fit(env, nb_steps=10000, visualize=False, verbose=2)

内容的提问来源于stack exchange,提问作者Thomas Burns

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 23:02:35