fit_generator与predict_generator验证结果存在差异的问题求助
这种情况我碰到过好几次,核心问题基本都出在数据处理的一致性或者标签匹配上,下面是几个最可能的原因和对应的解决办法:
1. 训练/验证与测试数据的预处理不一致
你用了val_datagen和test_datagen两个生成器,如果它们的预处理配置不一样(比如一个做了归一化,另一个没做;或者一个加了训练时才用的数据增强,另一个参数不同),模型看到的输入分布就会有差异,自然预测结果不准。
比如如果你的val_datagen是这样的:
val_datagen = ImageDataGenerator(rescale=1./255)
那test_datagen必须完全一致,不能漏掉rescale参数,也不能额外加rotation_range这类只适合训练的数据增强操作。
解决办法:直接复用同一个数据生成器配置给测试集,比如:
# 统一预处理配置 common_datagen = ImageDataGenerator(rescale=1./255) # 验证生成器 validation_generator = common_datagen.flow_from_directory( directory=val_data_dir, target_size=(img_width, img_height), batch_size=batch_size, shuffle=True, classes=["0", "1"], class_mode="categorical" ) # 测试生成器 test_generator = common_datagen.flow_from_directory( directory=test_data_dir, target_size=(img_width, img_height), batch_size=batch_size, shuffle=False, classes=None, class_mode=None )
2. 真实标签与预测结果的对应关系错误
你把验证集的两个子文件夹合并成了单个测试文件夹,这意味着你需要手动生成真实标签,但很容易出现标签顺序和预测结果顺序不匹配的问题:
validation_generator会自动给0文件夹的样本打标签[1,0],1文件夹的样本打[0,1];- 而
test_generator的shuffle=False,样本顺序是按文件夹内的文件排序,但合并后无法直接从生成器获取标签,手动生成时如果顺序错了,计算F1肯定会偏差。
解决办法:通过test_generator.filenames获取样本文件名,然后根据文件名反向映射到原来的类别:
# 假设原来的验证集里,文件名包含类别信息,或者你有原路径映射 true_labels = [] for filename in test_generator.filenames: # 根据实际情况判断,比如原路径是val_data_dir/0/xxx.jpg,现在filename是xxx.jpg # 这里需要你根据自己的文件命名规则调整 if "class0" in filename: # 示例条件,替换成你的判断逻辑 true_labels.append(0) else: true_labels.append(1) # 把预测结果转成类别 predictions_classes = np.argmax(predictions, axis=1) # 计算F1 from sklearn.metrics import f1_score print(f1_score(true_labels, predictions_classes))
3. 类别映射顺序不匹配
在validation_generator里你指定了classes=["0", "1"],这意味着模型输出的第一个维度对应类别0,第二个对应类别1;但test_generator里classes=None,虽然是单个文件夹,但模型的输出顺序还是和训练时一致的。如果你计算F1时把预测的argmax结果对应错了类别(比如把0当成1,1当成0),分数会骤降。
解决办法:明确类别映射关系,比如:
# 训练时的类别顺序是["0", "1"],所以argmax=0对应类别0,argmax=1对应类别1 predictions_classes = np.argmax(predictions, axis=1) # 确保true_labels里的0和1和这个顺序完全对应
4. 预测的样本数量计算错误
你手动计算steps的方式可能有误差,比如nbr_test_samples和test_generator.samples的实际数量不一致,导致预测时只处理了部分样本,或者重复处理,结果不完整。
解决办法:直接用生成器的samples属性计算,或者让Keras自动处理:
# 方式1:用math.ceil计算准确的steps import math steps = math.ceil(test_generator.samples / batch_size) predictions = myModel.predict_generator(test_generator, steps=steps, verbose=1) # 方式2:Keras 2.2及以上版本可以省略steps,自动计算 predictions = myModel.predict_generator(test_generator, verbose=1)
5. 模型状态异常
确认在调用predict_generator之前,模型没有被重新编译、加载其他权重或者修改过结构。比如如果训练完后你不小心执行了myModel.compile(...),模型的权重会被重置,预测结果自然不对。
解决办法:训练完成后直接调用predict_generator,不要对模型做任何额外修改;如果需要保存模型,训练后用myModel.save()保存,预测时再加载。
内容的提问来源于stack exchange,提问作者Quang Hieu

