我最近一直在使用TF2.0。我已经训练了一个简单的CNN模型(使用Keras顺序API)来对图像进行二进制分类。我已经使用tf.data.Dataset从磁盘加载图像。实际上,该模型具有非常好的准确性,其训练精度binary_accuracy为0.9831,验证精度binary_accuracy为0.9494。
尝试使用model.evaluate()评估模型。二进制精度为0.9460。但是,当我尝试使用predict_classes()手动计算二进制精度时,我得到约0.384。我不知道这是什么问题。请帮帮我。
我添加了用于编译和训练模型的代码。还有评估我的模型的代码。
train_data = tf.data.Dataset.from_tensor_slices((tf.constant(train_x),tf.constant(train_y)))
val_data = tf.data.Dataset.from_tensor_slices((tf.constant(val_x),tf.constant(val_y)))
train_data = train_data.map(preproc).shuffle(buffer_size=100).batch(BATCH_SIZE)
val_data = val_data.map(preproc).shuffle(buffer_size=100).batch(BATCH_SIZE)
model.compile(optimizer=Adam(learning_rate=0.0001),
loss='binary_crossentropy',
metrics=[tf.keras.metrics.BinaryAccuracy()])
checkpointer = ModelCheckpoint(filepath='weights.hdf5', verbose=1, save_best_only=True)
time1 = time.time()
history = model.fit(train_data.repeat(),
epochs=EPOCHS,
steps_per_epoch=STEPS_PER_EPOCH,
validation_data=val_data.repeat(),
validation_steps=VAL_STEPS,
callbacks=[checkpointer])
29/29 [==============================] - 116s 4s/step - loss: 0.0634 - binary_accuracy: 0.9826 - val_loss: 0.1559 - val_binary_accuracy: 0.9494
现在使用看不见的数据进行测试
test_data = tf.data.Dataset.from_tensor_slices((tf.constant(unseen_faces),tf.constant(unseen_labels)))
test_data = test_data.map(preproc).batch(BATCH_SIZE)
model.evaluate(test_data)
9/9 [==============================] - 19s 2s/step - loss: 0.1689 - binary_accuracy: 0.9460
同一模型,当我尝试使用具有相同数据集的model.predict_classes计算准确性时,预测结果与评估报告相去甚远。二进制精度约为38%。
修改1: 我在训练时使用的预处理功能
def preproc(file_path,label):
img = tf.io.read_file(file_path)
img = tf.image.decode_jpeg(img)
img = (tf.cast(img, tf.float32)/127.5) - 1
return tf.image.resize(img,(IMAGE_HEIGHT,IMAGE_WIDTH)),label
手动预测代码
from sklearn.metrics import classification_report
#Testing preprocessing function
def preproc_test(file_path):
img = tf.io.read_file(file_path)
img = tf.image.decode_jpeg(img)
img = (tf.cast(img, tf.float32)/127.5) - 1
return tf.image.resize(img,(IMAGE_HEIGHT,IMAGE_WIDTH))
unseen_faces = []
unseen_labels = []
for im_path in glob.glob('dataset/data/*'):
unseen_faces.append(im_path)
if 'real' in i:
unseen_labels.append(0)
else:
unseen_labels.append(1)
unseen_faces = list(map(preproc_test,unseen_faces))
unseen_faces = tf.stack(unseen_faces)
predicted_labels = model.predict_classes(unseen_faces)
print(classification_report(unseen_labels,predicted_labels,[0,1]))
precision recall f1-score support
0 0.54 0.41 0.47 34
1 0.41 0.54 0.47 26
accuracy 0.47 60
macro avg 0.48 0.48 0.47 60
weighted avg 0.48 0.47 0.47 60
答案 0 :(得分:1)
您的模型在training
和testing
期间都表现良好。评估准确性是基于预测的,因此使用model.predict_classes()
时可能会犯一些逻辑错误。评估时,请检查您是否使用训练有素的模型权重,而不是任何随机初始化的模型。
evaluate
:模型将分开训练数据的这一部分,不对其进行训练,并且将在每个时期结束时评估该数据的损失和任何模型度量。 model.evaluate()
用于评估您训练有素的模型。它的输出是准确或丢失,而不是对输入数据的预测。
predict
:为输入样本生成输出预测。 model.predict()
实际上是预测值,其输出是根据输入数据预测的目标值。
P.S .:对于二元分类问题,准确度<= 50%比随机猜测差。
答案 1 :(得分:1)
在我的情况下,这是因为我的地面真理和预测结果的形状不同。我正在按(x_train, y_train), (x_test, y_test) = cifar10.load_data()
加载数据,其中y_train
是形状为(50000,1)
的二维数组,但是来自model.predict_classes
的预测是形状为(50000,)
。如果我直接用np.mean(pred==y_train)
比较它们,我将得到0.1
的结果,这是不正确的。而是np.mean(pred==np.squeeze(y_train))
给出正确的结果。