Keras预测和predict_generator方法产生不同结果

5

我目前正在使用Keras进行卫星图像分类,但是我在使用predict和predict_generator时遇到了一些问题,无法获得正确的预测结果。

以下是我的代码:

import os
import numpy as np  
import pandas as pd
from keras.optimizers import Adam, SGD
from tools import load_val_datas, load_test_datas, make_predictions, make_submissions
from keras_tools import save_model, load_model

from callbacks import CustomCallbacks
from data_generator import ImageDataGenerator
from model import base_cnn

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'

TRAIN_SIZE, VAL_SIZE, TEST_SIZE, TEST_SIZE_ADD = 30000, 10479, 40669, 20522
IMAGE_FIRST_DIM, N_COLORS = 32, 3
IMAGE_SIZE = IMAGE_FIRST_DIM * IMAGE_FIRST_DIM * N_COLORS
LABEL_SIZE = 17
DROPOUT = 0.25
BATCH_SIZE = 96
N_EPOCHS = 2
CHECKPOINTS_FOLDER = "checkpoints/"
MODEL_JSON = "epoch-10.json"
MODEL_H5 = "epoch-10.h5"
TO_LOAD = False

df_train_labels = pd.read_csv("datas/train_labels.csv")
label_dict = df_train_labels.set_index("image_name").T.to_dict("list")

val_x, val_y = load_val_datas(VAL_SIZE, IMAGE_FIRST_DIM, N_COLORS, LABEL_SIZE)

if TO_LOAD:
    model, is_loaded = load_model(CHECKPOINTS_FOLDER + MODEL_JSON, CHECKPOINTS_FOLDER + MODEL_H5)
else:
    model = base_cnn(IMAGE_FIRST_DIM, N_COLORS)

adam = Adam(lr=0.01)
sgd = SGD(lr=0.01, momentum=0.9, decay=0.0005)
model.compile(loss='binary_crossentropy', optimizer=sgd)

my_callbacks = CustomCallbacks()
datagen = ImageDataGenerator(rescale=1./255)
train_generator = datagen.flow_from_directory("datas/train", target_size=(IMAGE_FIRST_DIM, IMAGE_FIRST_DIM),
                                              batch_size=BATCH_SIZE,
                                              class_mode="multilabel", multilabel_classes=label_dict)

val_generator = datagen.flow_from_directory("datas/validation", target_size=(IMAGE_FIRST_DIM, IMAGE_FIRST_DIM),
                                              batch_size=BATCH_SIZE, shuffle=False,
                                              class_mode="multilabel", multilabel_classes=label_dict)

model.fit_generator(train_generator, steps_per_epoch=TRAIN_SIZE/BATCH_SIZE, epochs=N_EPOCHS,
                    verbose=2)
save_model(model, MODEL_JSON, MODEL_H5)

from time import time
st = time()
p_valid = model.predict_generator(val_generator, steps=VAL_SIZE/BATCH_SIZE, pickle_safe=True)
print("time: ", time() - st)
print(p_valid)
from sklearn.metrics import fbeta_score
print(fbeta_score(val_y, np.array(p_valid) > 0.2, beta=2, average='samples'))

st = time()
p_valid1 = model.predict(val_x)
print("time: ", time() - st)
print(type(p_valid1))
print(fbeta_score(val_y, np.array(p_valid1) > 0.2, beta=2, average='samples'))

我正在使用另一个能够处理多标签的版本的ImageDataGenerator(我已经检查过实现方式并确认批处理中的数据已被正确加载)。问题出在预测和predict_generator部分,两者得到的结果不同。我用一个没有生成器训练的模型再次检查了predict的输出是正确的(且与predict_generator的输出非常不同)。在predict中输入的数据与生成器将要使用的数据构造方式相同(也已检查)。
Using TensorFlow backend.
validation images loaded in 0.01 seconds
validation labels loaded in 0.00 seconds


Found 30000 images belonging to 1 classes.
Found 10479 images belonging to 1 classes.
Epoch 1/2
63s - loss: 0.2762
Epoch 2/2
66s - loss: 0.2288
time:  22.098024606704712
beta_score: 0.667686382255
time:  3.3181281089782715
beta_score: 0.740394519272

感谢您,Nicolas。

可能是由于洗牌引起的。尝试将网络训练更多个时期。 - Marcin Możejko
我在验证生成器中设置了shuffle=False。训练是正确的。我还测试了5和10个epochs,结果相同。我将尝试在val_x中使用1张图像以获得更多可视性。 - nyounes
可能与此相关:http://stackoverflow.com/questions/43938176/why-differ-metrics-calculated-by-model-evaluate-from-tracked-metrics-during-tr? - Nassim Ben
1
好的,我只是个白痴... ImageDataGenerator 获取文件名的顺序很“奇怪”,不同于我手动操作的顺序... 但看起来一切都没问题。 - nyounes
1个回答

0

我认为这个在GitHub上类似问题的评论可能会帮助到某些人 https://github.com/keras-team/keras/issues/3477#issuecomment-360022086

predict()和predict_generator()的输出实际上是相同的,但它们看起来不同,因为它们被标记为不同的标签。你提供了predict()的标签,而predict_generator()则从训练数据的目录结构中推断标签(因为它使用flow_from_directory()而不是flow())。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接