KERAS模型在训练时恢复高验证精度,但是评估时准确性很低
我正在尝试在keras.applications
下训练简单的mobilenetv3small
,如下所示,
base_model = keras.applications.MobileNetV3Small(
input_shape= INPUT_SHAPE,
alpha=.125,
include_top=False,
classes=1,
dropout_rate = 0.2,
weights=None)
x = keras.layers.Flatten()(base_model.output)
preds = keras.layers.Dense(1, activation="sigmoid")(x)
model = keras.Model(inputs=base_model.input, outputs=preds)
model.compile(loss="binary_crossentropy",
optimizer='RMSprop',
metrics=["binary_accuracy"])
train_datagen = ImageDataGenerator(
rescale=1.0 / 255,
rotation_range=40,
horizontal_flip=True,
vertical_flip=True,
)
train_generator = train_datagen.flow_from_directory(
os.path.join(DATA_ROOT, 'train'),
target_size=(56,56),
batch_size=128,
class_mode="binary",
)
validation_datagen = ImageDataGenerator(rescale=1.0 / 255)
validation_generator = validation_datagen.flow_from_directory(
os.path.join(DATA_ROOT, 'val'),
target_size=(56,56),
batch_size=128,
class_mode="binary",
)
model_checkpoint_callback = keras.callbacks.ModelCheckpoint(
filepath=SAVE_DIR,
save_weights_only=True,
monitor='val_binary_accuracy',
mode='max',
save_best_only=True)
es_callback = keras.callbacks.EarlyStopping(patience=10)
model.fit(train_generator,
epochs=100,
validation_data=validation_generator,
callbacks=[model_checkpoint_callback, es_callback],
shuffle=True)
当我训练模型时,我在0.94左右获得验证精度。但是,当我在完全相同的验证数据上调用model.evaluate
时,精度变为0.48。当我调用model.predict
的任何数据时,它会输出常数值0.51 ...
学习率,优化器或指标没有错。这里有什么问题?
编辑:
在训练后,
pred_results = model.evaluate(validation_generator)
print(pred_results)
它为我提供了1个时期训练的网络的输出:
6/6 [=================================================== binary_accuracy:0.8461
但是,当我使用model.save()
或tf.keras.models.save_model()
> tf.keras.models()时,我将模型保存并加载模型时。输出成为这样的事情:
6/6 [====================================================== binary_accuracy:0.5028 [0.6935192346572876,0.5027709603309631]
和model.dredict.predict(validation_generator)
is的输出
[[0.5080832] [0.5080832] [0.5080832] [0.5080832] 。 。 。 [0.5080832] [0.5080832]
我到目前为止尝试过的
- :
- 全球张量子和Numpy种子。
- 在另一个 so so post 中,发现了类似的问题。并减少
动量
Mobilenet batchnoralization层的参数一一。
for layer in model.layers[0].layers:
if type(layer) is tf.keras.layers.BatchNormalization:
layer.momentum = 0.9
前两个动作没有效果,在应用第三步之后,我对任何输入都不再获得相同的预测。但是,estaution()
和predict()
仍然具有不同的精度值。
I am trying to train a simple MobileNetV3Small
under keras.applications
as shown below
base_model = keras.applications.MobileNetV3Small(
input_shape= INPUT_SHAPE,
alpha=.125,
include_top=False,
classes=1,
dropout_rate = 0.2,
weights=None)
x = keras.layers.Flatten()(base_model.output)
preds = keras.layers.Dense(1, activation="sigmoid")(x)
model = keras.Model(inputs=base_model.input, outputs=preds)
model.compile(loss="binary_crossentropy",
optimizer='RMSprop',
metrics=["binary_accuracy"])
train_datagen = ImageDataGenerator(
rescale=1.0 / 255,
rotation_range=40,
horizontal_flip=True,
vertical_flip=True,
)
train_generator = train_datagen.flow_from_directory(
os.path.join(DATA_ROOT, 'train'),
target_size=(56,56),
batch_size=128,
class_mode="binary",
)
validation_datagen = ImageDataGenerator(rescale=1.0 / 255)
validation_generator = validation_datagen.flow_from_directory(
os.path.join(DATA_ROOT, 'val'),
target_size=(56,56),
batch_size=128,
class_mode="binary",
)
model_checkpoint_callback = keras.callbacks.ModelCheckpoint(
filepath=SAVE_DIR,
save_weights_only=True,
monitor='val_binary_accuracy',
mode='max',
save_best_only=True)
es_callback = keras.callbacks.EarlyStopping(patience=10)
model.fit(train_generator,
epochs=100,
validation_data=validation_generator,
callbacks=[model_checkpoint_callback, es_callback],
shuffle=True)
When I train the model I got validation accuracy around 0.94. But when I call model.evaluate
on the exact same validation data, the accuracy becomes 0.48. When I call model.predict
with any data it outputs constant value 0.51...
There is nothing wrong with learning rate, optimizer or metrics. What could be wrong here?
EDIT:
After training when I run
pred_results = model.evaluate(validation_generator)
print(pred_results)
it gives me the output for 1 epoch trained network:
6/6 [==============================] - 1s 100ms/step - loss: 0.6935 -
binary_accuracy: 0.8461
However, when I save and load the model with either model.save()
or tf.keras.models.save_model()
. The output becomes something like this:
6/6 [==============================] - 2s 100ms/step - loss: 0.6935 -
binary_accuracy: 0.5028 [0.6935192346572876, 0.5027709603309631]
and output of the model.predict(validation_generator)
is:
[[0.5080832] [0.5080832] [0.5080832] [0.5080832]
.
.
. [0.5080832] [0.5080832]]
What I've tried so far:
- Used
tf.keras.utils.image_dataset_from_directory()
instead ofImageDataGenerator
- Fixed tensorflow and numpy seeds globally.
- Found similar problem in another SO post, and decreased
momentum
parameter of MobileNet BatchNormalization layers one by one.
for layer in model.layers[0].layers:
if type(layer) is tf.keras.layers.BatchNormalization:
layer.momentum = 0.9
First two moves do not have an effect, the after applying the third step, I get no longer same predictions for any input. However, evaluate()
and predict()
still have different accuracy values.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您是否尝试过设置
shuffle = false
invalidation_datagen.flow_from_directory()
?这有点具有误导性,但是.flow_from_directory()
方法默认情况下会随机混乱,在生成验证数据集时,这是有问题的。当您尝试调用.predict
时,这将使您的验证数据改组。尽管在您的培训循环中,.fit
方法隐含地不会使验证集进行洗牌。我之所以认为这是问题,是因为您在验证集网络上呼叫
.predict()二进制交叉熵损失),如果您(错误地)将验证数据改组,这是非常有意义的。平衡数据集上未经训练的二进制分类器通常会达到50%的精度约为50%(0.5 f in 0,为1),因为这只是在猜测这一点。
Source :我以前构建并培训了许多图像分类模型,这发生在我身上。
Have you tried setting
shuffle = False
invalidation_datagen.flow_from_directory()
? It's a little misleading but the.flow_from_directory()
method shuffles by default, which is problematic when generating your validation dataset. This is shuffling your validation data when you try to call.predict
. Whereas in your training loop, the.fit
method implicitly DOESN'T shuffle the validation set.The reason I think this is the issue, is because you state that calling
.predict()
on the validation set nets you ~.5 accuracy, and you're also running a binary classification (sigmoid output with binary cross entropy loss), which makes perfect sense IF you're (mistakenly) shuffling your validation data. Untrained binary classifiers on balanced datasets will usually do around 50% accuracy (.5 for 0, .5 for 1) since it's just guessing at that point.Source: I've built and trained a lot of image classification models before, and this happened to me a lot.
可能值得尝试
model.save_weights('Directory')
,然后重建模型(我认为这里是通过base_model = ...
代码重新运行的)model.load_weights('Directory')
。这就是我在自己的型号中所做的,当我这样做时,保存和加载前后的准确性/损失保持完全相同。It might be worth trying
model.save_weights('directory')
and then rebuilding your model (i think here that is re-running thebase_model = ...
code) throughmodel.load_weights('directory')
. That is what i do in my own models, and when i then do that, the accuracy/loss stay the exact same before and after saving and loading.如果您运行
pred_results = model.evaluate(validation_generator)
适合模型后,此刻的重量是上次训练时期更新的权重。
您要做的是
model.fit
正在加载从model_checkpoint_callback
与类似If you run
pred_results = model.evaluate(validation_generator)
after you fit the model, the loaded weights at this moment are the ones updated on last training epoch.
What you have to do is after
model.fit
is loading the weights saved frommodel_checkpoint_callback
with something like