使用tf.data.Dataset.from_generator时Keras报NoneType不可调用错误
核心问题定位
两个关联问题共同导致了当前的运行异常:
- 输出张量维度冗余异常:核心原因是未给
tf.data.Dataset.from_generator指定输出静态形状,TF无法识别生成器每次yield的就是已经组装好的批量数据,在后续测试时叠加.batch(1)操作后,生成了多层无意义的1维维度,最终输出形状变为(1,1,1,128,105624)。 - 训练时TypeError报错:Keras在构建训练计算图时,需要知道输入张量的固定静态形状才能编译可执行的
train_function;缺失形状定义会导致编译流程失败,train_function被赋值为None,调用时就抛出'NoneType' object is not callable的错误。
修复方案
- 显式给
from_generator补全参数,明确指定每次yield的x、y的固定形状:- 训练样本x的固定形状为
(batch_size, 105624) - 标签y的固定形状为
(batch_size, 405415) - 移除不必要的额外
.batch()操作(旧生成器本身已经完成了批量组装)
- 训练样本x的固定形状为
- 增加预取配置,利用tf.data的并行加载能力提升大稀疏矩阵场景下的加载效率
- 统一使用TensorFlow原生数据类型指定输出类型,避免numpy类型的推断兼容问题
修复后代码示例
bs = 128 # 训练集Dataset Gt = tf.data.Dataset.from_generator( lambda: get_generator(Xt, yt, bs), output_types=(tf.float32, tf.int32), output_shapes=((bs, 105624), (bs, 405415)) ).prefetch(tf.data.AUTOTUNE) # 验证集Dataset Gv = tf.data.Dataset.from_generator( lambda: get_generator(Xv, yv, bs), output_types=(tf.float32, tf.int32), output_shapes=((bs, 105624), (bs, 405415)) ).prefetch(tf.data.AUTOTUNE) model.fit( Gt, epochs=epochs, verbose=1, callbacks=[mc, es, rlr], validation_data=Gv )
常见踩坑提示
- 不要给已经内置批量逻辑的生成器Dataset重复调用
.batch(),否则会额外叠加一层批量维度,导致输入形状和模型输入层不匹配 - 如果仍然出现
'NoneType' object is not callable报错,检查TF/Keras的版本兼容性,TF2.x需要搭配对应版本的Keras接口,TF1.x的遗留Keras代码和新版tf.data适配存在已知问题 - 大内存场景下可以配合tf.data的并行预取配置减少GPU空等,当前基于内存稀疏矩阵的生成器方案在补全形状定义后即可正常运行
内容的提问来源于stack exchange,提问作者Rakesh Raj
相关产品推荐
相关产品推荐

