首页 文章

模型训练后的Keras预测

提问于
浏览
0

我训练了一个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个时期的培训过程,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}

格式与此无关 . 我的观点是,如何获得每个训练过的 class 的概率?我想我尝试使用所有模型预测方法,但没有一个给我我需要的东西 . 我在代码中做错了什么,或者它需要以某种方式完成不同的做法?

2 回答

  • 1

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

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

    Minimal要经历的代码越多,人们找到问题的可能性就越小 .

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

    其次,尝试预测一些您知道是正面的手工挑选的样本(我假设0 's are your negatives), i.e. that should give outputs close to 1; for all I know, with the info you have provided, it may be the case that there is nothing wrong, and simply the (few) test samples you have tried all happen to give probability 0 (negative) - maybe improbable, but not impossible, and you' d更好地明确检查它 .

    澄清最后一点:由于你的最后一层有一个节点,你的输出将是[0,1]中的一个数字,通常被视为你的一个类的概率 p (另一个的概率)一个只是二进制分类中的 1-p );所以,至少输出的格式根本不奇怪 .

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

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

  • 1

    我设法解决了这个问题并且它正在发挥作用 . 问题是我在训练模型时在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并且它正在工作 . 谢谢大家的帮助,再次抱歉代码的数量 .

相关问题