我已经训练了一个Keras模型,并将模型和权重分别保存到了两个文件中。我的训练数据和验证数据被分为两个类别,如下所示:
training_data/ positive/ negativevalidation_data/ positive/ negative/
训练数据目录中每个类别包含90万个样本,验证数据目录中每个类别包含2万个样本。所有样本的尺寸为43×43像素。
我的模型和学习过程定义如下:
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 modelmodel = 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,180万个训练样本和4万个验证样本,耗时约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}
格式在这里并不重要。我的意思是,如何获取每个已训练类别的概率?我认为我尝试了所有模型预测方法,但没有一个能给我我需要的结果。我在代码中做错了什么,还是需要以某种不同的方式来做?
回答:
让我尝试提供一个方法论,既可以帮助你追踪问题的根本原因,也可以让Stack Overflow的回答者更容易帮助你…
首先,正如我在评论中所说,Stack Overflow上的代码应该是最简化的,即只需足够重现问题;由于我们无法访问你的数据,因此根本没有必要包括像你的training_generator
、validation_generator
、目录结构或[…]这样的细节,这些对回答者来说毫无用处,只会分散注意力(只有在你使用像MNIST或CIFAR这样的公开数据集时,这些才可能有用):
最简化
代码越多,人们找到你问题的地方就越困难。
可以说,同样的原则也适用于问题中的文本…
其次,尝试预测一些你知道是正样本(我假设0是你的负样本)的手动挑选的样本,即应该给出接近1的输出;根据你提供的信息,我所知道的是,可能根本没有问题,只是你尝试的(少数)测试样本碰巧都给出了0的概率(负样本) – 这虽然不太可能,但并非不可能,你最好明确地检查一下。
关于最后一点的澄清:由于你的最后一层只有一个节点,你的输出将是[0,1]之间的一个单一数字,通常被视为一个类别的概率p
(另一个类别的概率在二分类中简单地为1-p
);因此,至少你的输出的格式并不奇怪。
第三,尝试在保存模型之前进行一些预测,因为关于模型保存和加载的问题已经有多个报告(谷歌一下),并将它们与从加载的模型中进行的相同预测进行比较;如果有差异,你就大大缩小了寻找原因的范围。
希望这对你有帮助;希望,如果确实有问题,按照这些步骤,你要么能自己解决问题,要么能将问题缩小到一个特定的点,然后你可以在这里提出一个新的、更集中的问题。在这种情况下,遵循Stack Overflow关于如何创建一个最简化、完整且可验证的示例的指导方针,将显著提高你从某人那里得到有用答案的几率…