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

TensorFlow Keras中自定义Sequence生成器配合model.fit训练时的ValueError问题排查

解决自定义Sequence生成器无法适配Keras模型的问题

这个错误的核心原因是你混用了原生Keras和TensorFlow集成的Keras(tf.keras)模块,导致自定义的MyDataGenerator(继承自tf.keras.utils.Sequence)和你创建的keras.Sequential模型属于不同的Keras实例,数据适配器无法识别这种跨模块的组合。

修复步骤

1. 统一使用tf.keras模块

把所有Keras相关的导入替换为tf.keras,彻底避免原生Keras和tf.keras的冲突:

import tensorflow as tf
import numpy as np
from tensorflow.keras.utils import Sequence
from tensorflow.keras import Sequential
from tensorflow.keras.layers import InputLayer, Dense, Flatten
import math  # 补充导入math,你的__len__方法用到了但代码里没写

2. 确保生成器返回的标签类型兼容

虽然你用numpy数组训练时uint32的标签能运行,但为了更稳妥,建议把生成器中y的类型改为int32或float32(符合二分类任务的常规类型):

def __getitem__(self, index):
    index = self.index[index * self.batch_size:(index + 1) * self.batch_size]
    batch = [self.indices[k] for k in index]
    X = np.zeros((self.batch_size, *self.dim), dtype=np.float32)
    y = np.zeros((self.batch_size,), dtype=np.int32)  # 修改标签类型
    return X, y

3. 验证生成器的完整性

检查你的MyDataGenerator是否完全符合Sequence的规范:

  • __len__方法正确计算了每个epoch的步数(你已经用math.ceil实现,记得导入math)
  • __getitem__返回的是(输入数据, 标签)的元组
  • on_epoch_end正确实现了索引打乱逻辑

为什么会出现这个错误?

在TensorFlow 2.x中,官方推荐使用tf.keras而不是原生Keras,两者的内部实现和数据适配逻辑是独立的。你用tf.keras.utils.Sequence写的生成器,无法被原生keras模型的数据适配器识别,所以抛出了"找不到数据适配器"的错误。而直接用numpy数组训练时,numpy数组是通用数据类型,两个模块都能处理,所以没问题。

修复后的完整训练代码示例

# 统一导入tf.keras
import tensorflow as tf
import numpy as np
from tensorflow.keras.utils import Sequence
from tensorflow.keras import Sequential
from tensorflow.keras.layers import InputLayer, Dense, Flatten
import math

class MyDataGenerator(Sequence):
    def __init__(self, df, x_col='filename', y_col='class', batch_size=32, path='./', num_classes=None, shuffle=True, dim=(634,513,1), nfft=1024, hstep=256, sr=16000):
        self.batch_size = batch_size
        self.df = df
        self.indices = self.df.index.tolist()
        self.num_classes = num_classes
        self.path = path
        self.shuffle = shuffle
        self.x_col = x_col
        self.y_col = y_col
        self.on_epoch_end()
        self.dim = dim
        self.nfft = nfft
        self.hstep = hstep
        self.sr = sr

    def __getitem__(self, index):
        index = self.index[index * self.batch_size:(index + 1) * self.batch_size]
        batch = [self.indices[k] for k in index]
        X = np.zeros((self.batch_size, *self.dim), dtype=np.float32)
        y = np.zeros((self.batch_size,), dtype=np.int32)
        # 后续记得补充实际加载数据的逻辑,当前只是占位
        return X, y

    def __len__(self):
        return math.ceil(len(self.indices) / self.batch_size)

    def on_epoch_end(self):
        self.index = np.arange(len(self.indices))
        if self.shuffle == True:
            np.random.shuffle(self.index)

# 假设df_training和df_validation是已定义的DataFrame
train_datagen = MyDataGenerator(df_training)
valid_datagen = MyDataGenerator(df_validation, shuffle=False)

# 用tf.keras创建模型
model = Sequential(name='Test_model')
model.add(InputLayer((634, 513, 1), name='Input'))
model.add(Flatten(name='Flatten'))
model.add(Dense(1, activation='sigmoid', name='Output'))
model.summary()
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

# 训练模型
model.fit(
    train_datagen,
    epochs=1,
    verbose=1,
    validation_data=valid_datagen
)

这样修改后,你的自定义生成器就能被tf.keras模型正确识别,正常进行训练了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 17:54:08