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

自定义Keras Sequence生成器报错:'generator'无'shape'属性

解决Keras自定义Sequence生成器的AttributeError问题

我之前帮朋友排查过几乎一模一样的问题,卡了好几天的错误终于找到根源了!先看看你遇到的报错:

/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/data_adapter.py in __init__(self, x, y, sample_weights, workers, use_multiprocessing, max_queue_size, model, **kwargs)
794         lambda x: model(x, training=False), args=(concrete_x,))
795     --> 796         self._first_batch_size = int(nest.flatten(peek)[0].shape[0])
797 
798       def _get_dynamic_shape(t):
AttributeError: 'generator' object has no attribute 'shape'

问题根源分析

你的自定义Mygenerator继承了Keras的Sequence类,但犯了几个关键错误:

  1. __getitem__不该用yield:Sequence的设计逻辑是让这个方法直接返回单个batch的数据集,而不是作为生成器返回。你用了yield之后,Keras拿到的不是张量batch,而是一个生成器对象,自然会去访问它的shape属性,这就触发了错误。
  2. __len__计算逻辑错误:你用len(self.x[1])来计算总步数,这完全不对——应该基于总样本数来计算batch数量,而且要保证所有输入的样本数一致。
  3. 切片写法错误:self.x[:][int(idx * self.batch_size):int((idx + 1) * self.batch_size)[:]]这种写法是无效的,对于多输入的列表,需要遍历每个输入元素单独截取batch区间。
  4. 不必要的数组转换:在__init__里把x_set和y_set转成np.array是多余的,HDF5Matrix本身支持切片操作,在取batch的时候再转成数组就好。

修正后的自定义生成器代码

class Mygenerator(Sequence):
    def __init__(self, x_set, y_set, batch_size):
        # x_set是多输入列表,每个元素对应模型的一个输入,形状为(n_samples, n_steps, n_features)
        # y_set是多输出列表,每个元素对应模型的一个输出,形状为(n_samples, 1)
        self.x = x_set
        self.y = y_set
        self.batch_size = batch_size
        # 总样本数,假设所有输入/输出的样本数一致
        self.n_samples = len(self.x[0])

    def __len__(self):
        # 计算总batch数,向上取整确保最后一个batch也被处理
        return int(np.ceil(self.n_samples / self.batch_size))

    def __getitem__(self, idx):
        # 计算当前batch的起始和结束索引,避免越界
        start_idx = idx * self.batch_size
        end_idx = min((idx + 1) * self.batch_size, self.n_samples)
        
        # 为每个输入截取对应的batch,并转成numpy数组
        X_batch = [np.array(x[start_idx:end_idx]) for x in self.x]
        # 为每个输出截取对应的batch,并转成numpy数组
        y_batch = [np.array(y[start_idx:end_idx]) for y in self.y]
        
        # 直接返回batch,不要用yield!
        return X_batch, y_batch

额外的模型构建小问题

你的模型构建代码里还有个小bug:concatenate之后直接用了dense变量,但这个变量没有定义,需要先加一个Dense层:

merge = concatenate([output_y[s] for s in range(len(output_y))])
# 新增这一行,定义dense层
dense = Dense(64, activation=lambda x: tf.nn.leaky_relu(x, alpha=0.2))(merge)
listDense = list()
for x in range(7): #len(floodplain)
    output = Dense(1, activation= lambda x : tf.nn.leaky_relu(x, alpha=0.2), name="output{}".format(x+1))(dense)
    listDense.append(output)
    update_progress((x+1)/7)

修正后的fit调用

不需要手动指定steps_per_epoch,因为Sequence的__len__已经返回了总步数,Keras会自动识别:

hist = model.fit(
    Mygenerator([X_tr_list[i] for i in range(len(X_tr_list))], [Y_tr[i] for i in range(Y_tr.shape[0])], 32),
    epochs=1000,
    verbose=1,
    callbacks=[checkpoint, es, best],
    validation_data=Mygenerator([X_te_list[i] for i in range(len(X_te_list))], [Y_te[i] for i in range(Y_te.shape[0])], 32)
)

这些修改应该能彻底解决你遇到的AttributeError问题,核心就是严格遵循Sequence类的设计规范,别把它当成普通生成器来写。

内容的提问来源于stack exchange,提问作者손상우

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 18:58:13