Tensorflow 即使使用相同的数据集进行培训和验证,Keras验证精度也远低于培训精度

Tensorflow 即使使用相同的数据集进行培训和验证,Keras验证精度也远低于培训精度,tensorflow,keras,deep-learning,Tensorflow,Keras,Deep Learning,我们尝试使用Keras ResNet50应用程序(Tensorflow作为后端)进行迁移学习,使用我们自己的2000个班级的数据集,14000张图像作为训练集,5261张图像作为验证集。我们得到的训练结果在训练和验证的损失和准确性方面都有很大的不同。然后,我们尝试使用相同的图像进行训练和验证,即使用14000张图像进行训练和使用相同的14000张图像进行验证,尝试的训练结果相似,即高训练精度和低验证精度 Keras版本:2.1.6 Tensorflow版本:1.8.0 代码(用于培训和验证的数据

我们尝试使用Keras ResNet50应用程序(Tensorflow作为后端)进行迁移学习,使用我们自己的2000个班级的数据集,14000张图像作为训练集,5261张图像作为验证集。我们得到的训练结果在训练和验证的损失和准确性方面都有很大的不同。然后,我们尝试使用相同的图像进行训练和验证,即使用14000张图像进行训练和使用相同的14000张图像进行验证,尝试的训练结果相似,即高训练精度和低验证精度

Keras版本:2.1.6

Tensorflow版本:1.8.0

代码(用于培训和验证的数据集相同),如下所示

from\uuuuu future\uuuuu导入打印功能
从keras.applications.resnet50导入resnet50
从keras.applications.resnet50导入预处理输入,解码预测
从keras.models导入*
从keras.layers导入*
从keras.callbacks导入*
从keras.preprocessing.image导入ImageDataGenerator
从日期时间导入日期时间
从keras.optimizers导入新加坡元
将numpy作为np导入
batch_size=28#调整您的GPU容量
img#u height=224#resneticeptionv2和类似299的异常,ResNet50和类似224的VGG
img_宽度=img_高度
频道=3
输入形状=(img\u高度、img\u宽度、通道)
最佳_模型='最佳_模型.h5'
列车数据发生器=图像数据发生器(预处理功能=预处理输入)
train_generator=来自目录的train_datagen.flow_(
“数据/列车”,这是目标目录
目标尺寸=(图像高度、图像宽度),
批次大小=批次大小,
class_mode='classifical')
等级=len(列发电机等级指数)
n列样本的数量=列生成器。样本
回调=[ModelCheckpoint(filepath=best\u model,verbose=0,save\u best\u only=True),
提前停止(监视器='val_acc',耐心=3,详细=0)]
基本模型=ResNet50(输入形状=输入形状,权重='imagenet',包括顶部=假)
#第一:只训练顶层(随机初始化)
#即冻结所有卷积ResNet50层
对于基本模型层中的层:
layer.trainable=错误
pool_layer=[基本_模型中的层对应层。如果layer.name=='avg_pool'][0]
base\u model=model(base\u model.input,pool\u layer.input)
base_model.layers.pop()
辍学率=[.25,.25]
密度=1024
last=基本模型输出
a=MaxPooling2D(池大小=(7,7),name='maxpool')(最后一个)
b=平均池2D(池大小=(7,7),名称='avgpool')(最后一个)
x=连接([a,b],轴=1)
x=展平()(x)
x=稠密(稠密,初始='均匀',激活='relu')(x)
x=BatchNormalization()(x)
x=辍学(辍学[0])(x)
x=密集(类,激活='softmax')(x)
模型=模型(基本模型输入,输出=x)
打印(“开始时间:%s”%str(datetime.now())
#编译模型(应在*将图层设置为不可训练后*完成)
compile(优化器=SGD(lr=1e-2,动量=0.9),loss='classifical\u crossentropy',metrics=['accurity'])
#根据新数据对模型进行几个时期的培训
1.2型拟合发生器(
列车发电机,
每个历元的步数=每列样本的n步//批量大小,
纪元=3,
验证数据=列车发电机,
验证步骤=系列样品数量//批量大小,
回调=回调)
打印(“结束时间:%s”%str(datetime.now())
培训结果如下

找到了14306张属于2000个类的图像。
开始时间:2018-05-21 10:51:34.459545
纪元1/3
510/510[==================================================================-10459s 21s/阶跃-损耗:5.6433-附件:0.1538-val_损耗:9.8465-val_附件:0.0024
纪元2/3
510/510[===========================================================================-10258s 20s/阶跃-损耗:1.3632-附件:0.8550-val_损耗:10.3264-val_附件:0.0044
纪元3/3
510/510[=======================================================================================-63640s 125s/阶跃-损耗:0.2367-acc:0.9886-val_损耗:10.4537-val_acc:0.0034
结束时间:2018-05-22 10:17:42.028052
我们理解,我们不应该在培训和验证中使用相同的数据集,但我们无法理解,当数据集在培训和验证中都相同时,为什么Keras会在培训和验证的损失和准确性方面给我们带来很大的差异

另外,我们尝试了相同的数据集,即2000个班级,14000张图像作为训练集,5261张图像作为验证集,使用fast.ai库ResNet50,训练损失和验证损失没有太大差异。fast.ai库的代码和结果如下

从fastai.import导入*
从fastai.com导入*
来自fastai.conv_学习者导入*
从fastai.model导入*
从fastai.dataset导入*
从fastai.sgdr导入*
从fastai.com导入*
从日期时间导入日期时间
PATH=“data/”
sz=224
arch=resnet50
bs=28
tfms=tfms_来自_模型(arch,sz)
数据=ImageClassifierData.from_路径(路径,tfms=tfms,bs=bs)
learn=ConvLearner.pretrained(arch、数据、预计算=False)
打印(“开始时间:%s”%str(datetime.now())
学习。适应(1e-2,5)
打印(“结束时间:%s”%str(datetime.now())
开始时间:2018-05-02 18:08:51.644750

0%| | 1/487[00:14不是答案,而是建议查看每批未受影响的损失/指标:

def batchEnd(batch,logs):
    print("\nfinished batch " + str(batch) + ": " + str(logs) + "\n")

metricCallback = LambdaCallback(on_batch_end=batchEnd)

callbacks = [  metricCallback, 
               ModelCheckpoint(filepath=best_model, verbose=0, save_best_only=True),
               EarlyStopping(monitor='val_acc', patience=3, verbose=0)]

这样,您将看到每个批次的指标,而不受其他批次的影响。(假设Keras在显示一个历元的指标时进行某种平均/合计).

您不是第一个遇到同样问题的人……此链接没有答案,但您可以询问提问者是否找到了解决方案?我认为这值得在keras github存储库中创建一个问题。。。