【问题标题】:Keras prediction after the model is trained模型训练后的 Keras 预测
【发布时间】:2018-04-15 12:13:39
【问题描述】:

我已经训练了一个 Keras 模型并将模型和权重保存到两个单独的文件中。我的训练数据和验证数据分为这样的两类:

training_data/
    positive/
    negative
validation_data/
    positive/
    negative/

两个训练数据目录各包含 900k 个样本,验证数据目录各包含 20k 个样本。所有样本均为 43x43px。

我的模型和学习过程是这样定义的:

def get_model(img_width, img_height):
    model = Sequential()
    model.add(Conv2D(32, (3, 3), input_shape=(img_width, img_height, 3)))
    model.add(Activation('relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))

    model.add(Conv2D(32, (3, 3)))
    model.add(Activation('relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))

    model.add(Conv2D(64, (3, 3)))
    model.add(Activation('relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))

    model.add(Flatten())
    model.add(Dense(64))
    model.add(Activation('relu'))
    model.add(Dropout(0.5))
    model.add(Dense(1))
    model.add(Activation('sigmoid'))

    return model

model = get_model(43, 43)
model.compile(loss='binary_crossentropy', optimizer='rmsprop',
              metrics=['accuracy'])

train_datagen = ImageDataGenerator(
    rescale=1. / 255,
    shear_range=0.2,
    zoom_range=0.2,
    rotation_range=20,
    width_shift_range=0.2,
    height_shift_range=0.2)

test_datagen = ImageDataGenerator(rescale=1. / 255)

train_generator = train_datagen.flow_from_directory(
    train_data_dir,
    target_size=(img_width, img_height),
    batch_size=batch_size,
    class_mode='binary')

validation_generator = test_datagen.flow_from_directory(
    validation_data_dir,
    target_size=(img_width, img_height),
    batch_size=batch_size,
    class_mode='binary')

history = model.fit_generator(
    train_generator,
    steps_per_epoch=nb_train_samples // batch_size,
    epochs=epochs,
    validation_data=validation_generator,
    validation_steps=nb_validation_samples // batch_size)

model.save(os.path.join('model.h5'))
model.save_weights(os.path.join('weights.h5'))
save_model_info(params)

20 个 epoch、1024 批大小、1.800.000 个训练样本和 40.000 个验证样本的训练过程大约需要 5 个小时。 history 对象在这里,因为我还保存了准确性和学习图。

现在,我试图让这个模型预测给定的测试样本中存在经过训练的两个类别中的哪一个。因此,我创建了模型,加载了权重并尝试运行预测。

model = get_model(43, 43)
model.load_weights(args.weights_file)
model.compile(loss='binary_crossentropy', optimizer='rmsprop',
              metrics=['accuracy'])

result = []
files = os.listdir(input_dir)
for file in files:
    image = load_img(file)
    image = np.asarray(image)
    image = np.expand_dims(image, axis=0)
    result.append(model.predict(image))

print(result)

它正在工作,但不是我想要的方式。输出是这样的:

[array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32), array([[ 0.]], dtype=float32)]

这是我的问题。我需要它对每个给定的文件进行预测,例如

{'negative': 0.925, 'positive': 0.0725}

这里的格式不相关。我的观点是,如何获得已训练的每个班级的概率?我想我尝试使用所有的模型预测方法,但没有一个能满足我的需要。我在代码中做错了什么还是需要以某种不同的方式完成?

【问题讨论】:

  • 1) 你提供了一堆不相关的信息(批量大小、数据集大小等),但你没有提供最基本的信息——你的模型到底是做什么的?二进制分类还是其他? 2) 忘记for file in files 和文件附加等(此处的代码应该是minimal),请发布single model.predict() 命令的结果
  • @desertnaut 这是二元分类(正/负),抱歉没有这么说,我发布了predict结果列表,单个结果将是array([[ 0.]], dtype=float32)
  • 有几个可能的原因。旧版本的 Keras IIRC 区分了 predict_proba(预测概率)和 predict(用于类,即 0/1 预测)。新版本使用 predict/predict_classes,但也许您使用的是旧版本。所以尝试 predict_proba 而不是 predict。接下来,尝试在小批量上只运行一个 epoch,以检查您是否以某种方式过度训练,并且您的网络不只是收敛于零。最后,可能是您的输出类型错误,但快速查看二进制分类看起来不错。想知道你是怎么过的。

标签: machine-learning keras neural-network conv-neural-network prediction


【解决方案1】:

让我尝试提供一种方法,既可以用于追踪问题的根本原因,也可以让 SO 的受访者更容易帮助您...

首先,正如我在评论中所说,SO 中的代码应该是minimal,即足以重现该问题;由于我们无权访问您的数据,因此根本没有必要包含您的training_generatorvalidation_generator、目录结构或 [...] 等详细信息,这些对受访者来说毫无用处,只会分散注意力(它们仅在您使用公开可用的数据集(如 MNIST 或 CIFAR)时才有用):

最小

要经过的代码越多,人们找到的可能性就越小 你的问题

可以说,同样的原则也适用于问题中的文本...

其次,尝试预测一些您知道的精选样本(我假设0是你的负数),即应该给出接近1的输出;据我所知,根据您提供的信息,可能没有任何问题,而且您尝试过的(少数)测试样本都恰好给出概率 0(阴性) - 可能不太可能,但并非不可能,你最好明确检查一下。

澄清最后一点:由于您的最后一层只有一个节点,因此您的输出将是[0,1]中的一个单个数字,通常被视为概率@987654325 @ 代表你的一个班级(另一个班级的概率只是 1-p 在二进制分类中);所以,至少你输出的格式一点都不奇怪。

第三,尝试在保存模型之前做出一些预测,因为在保存和加载模型时报告了几个问题(谷歌搜索),并将它们与加载模型的相同预测进行比较;如果存在差异,则您已大大缩小了对原因的搜索范围。

希望这会有所帮助;希望如果确实有问题,遵循这些步骤将帮助您自己解决问题,或者将其缩小到您可以在此处打开一个新的、更集中的问题的特定点。在这种情况下,遵循How to create a Minimal, Complete, and Verifiable example 上的 SO 指南将大大提高您从某人那里获得有用答案的机会...

【讨论】:

  • 感谢您的回答。我不想给你太多代码,但我刚开始学习 keras(和机器学习),我不知道代码的哪些部分很重要,我会记住的。我会照你说的做,如果有帮助,我会告诉你。
【解决方案2】:

我设法解决了这个问题并且它正在工作。问题是我在训练模型时在 ImageGenerator 中添加了rescale 参数:

train_datagen = ImageDataGenerator(
    rescale=1. / 255,
    shear_range=0.2,
    zoom_range=0.2,
    rotation_range=20,
    width_shift_range=0.2,
    height_shift_range=0.2)

而且我在运行预测时没有添加这个:

for file in files:
    image = load_img(file)
    image = np.asarray(image)
    image = np.expand_dims(image, axis=0)
    result.append(model.predict(image))

我改变了这一行

image = np.expand_dims(image, axis=0)

现在看起来像这样

img = np.expand_dims(img / 255, axis=0)

我还更新了加载模型,更改了那里的行(但仅用于预测,而不是训练):

model = get_model(43, 43)
model.load_weights(args.weights_file)
model.compile(loss='binary_crossentropy', optimizer='rmsprop',
          metrics=['accuracy'])

进入这个:

model = load_model(args.model_file)

我用我的所有样本运行预测并用结果填充一个 numpy 数组,然后将该数组更改为 image 并且它正在工作。感谢大家的帮助,再次为代码量感到抱歉。

【讨论】:

    猜你喜欢
    • 2017-05-29
    • 2019-06-21
    • 1970-01-01
    • 2017-07-16
    • 1970-01-01
    • 2022-10-19
    • 2018-02-22
    • 2018-07-31
    • 2019-12-30
    相关资源
    最近更新 更多