嗨,我正在使用以下代码在Keras中训练分类器,但是在测试新图像时,尽管我的验证测试显示出80%的准确性,但我总是得到预测类为1。请提出我在做什么错。
代码:
classifier=Sequential()
#--------------- 2. Convolution --------------------------
classifier.add(Conv2D(input_shape=(64,64,3),filters=32,kernel_size=(3,3),strides=(1,1),activation='relu'))
#--------------- 3. Max Pooling --------------------------
classifier.add(MaxPool2D(pool_size=(2,2)))
classifier.add(BatchNormalization())
#--------------- 4. Convolution --------------------------
classifier.add(Conv2D(filters=64,kernel_size=(3,3),strides=(1,1),activation='relu'))
#--------------- 5. Max Pooling --------------------------
classifier.add(MaxPool2D(pool_size=(2,2)))
classifier.add(BatchNormalization())
#--------------- 4. Convolution --------------------------
classifier.add(Conv2D(filters=128,kernel_size=(3,3),strides=(1,1),activation='relu'))
#--------------- 5. Max Pooling --------------------------
classifier.add(MaxPool2D(pool_size=(2,2)))
classifier.add(BatchNormalization())
#--------------- 4. Convolution --------------------------
classifier.add(Conv2D(filters=256,kernel_size=(3,3),strides=(1,1),activation='relu'))
#--------------- 5. Max Pooling --------------------------
classifier.add(MaxPool2D(pool_size=(2,2)))
classifier.add(BatchNormalization())
#--------------- 6. Flattening ---------------------------
classifier.add(Flatten())
#--------------- 7. Full Connection ----------------------
classifier.add(Dense(units=128,activation='relu',kernel_initializer='uniform'))
classifier.add(Dropout(0.6))
classifier.add(Dense(units=96,activation='relu',kernel_initializer='uniform'))
classifier.add(Dropout(0.4))
classifier.add(Dense(units=64,activation='relu',kernel_initializer='uniform'))
classifier.add(Dropout(0.2))
classifier.add(Dense(units=1,activation='sigmoid',kernel_initializer='uniform'))
#--------8. Deal with the weights and Loss function --------
classifier.compile(optimizer='adam',loss='binary_crossentropy', metrics=['accuracy'])
#-------- 9. Fitting CNN with Images --------
from keras.preprocessing.image import ImageDataGenerator
train_datagen = ImageDataGenerator(
rescale=1./255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
test_datagen = ImageDataGenerator(rescale=1./255)
training_set = train_datagen.flow_from_directory(
'dataset/training_set',
target_size=(64,64),
batch_size=128,
class_mode='binary')
test_set = test_datagen.flow_from_directory(
'dataset/test_set',
target_size=(64,64),
batch_size=128,
class_mode='binary',
shuffle=False)
filepath="bestcatvsdogmodel.h5"
save_best_model=ModelCheckpoint(filepath, monitor='val_acc', verbose=1, save_best_only=True, mode='max')
ReduceLR=ReduceLROnPlateau(monitor='val_acc', factor=0.6, patience=5, verbose=2,cooldown=1, min_delta=0.0020, min_lr=0.)
classifier.fit_generator(
training_set,
steps_per_epoch=7928/128,
epochs=10,
validation_data=test_set,
validation_steps=2000/128,
callbacks=[ReduceLR,save_best_model])
import numpy as np
from skimage.io import imread
from skimage.transform import resize
class_labels={v:k for k,v in training_set.class_indices.items()}
img_d=imread('dog.jpg')
img_c=imread('cat.jpg')
img_d=resize(img_d,(64,64))
img_c=resize(img_c,(64,64))
img_dog=np.expand_dims(img_d,axis=0)
img_cat=np.expand_dims(img_c,axis=0)
if(np.max(img_dog)>1):
img_dog=img_dog/255.0
if(np.max(img_cat)>1):
img_cat=img_cat/255.0
prediction_cat = classifier.predict_classes(img_cat)
print("Cat Prediction: "+str(prediction_cat))
prediction_dog = classifier.predict_classes(img_dog)
print("Dog Prediction: "+str(prediction_dog))
结果:
请建议您是否在代码中看到任何错误
答案 0 :(得分:0)
您正在做
prediction_cat = classifier.predict_classes(img_cat)
print("Cat Prediction: "+str(prediction_cat))
prediction_dog = classifier.predict_classes(img_dog)
print("Dog Prediction: "+str(prediction_dog))
在您的模型中,我可以看到最后一层具有一个由sigmoid
激活的节点。这样的预测调用模型可提供0
至1
范围内的输出概率。
您正在模型上调用predict_classes
。它的基本作用类似于np.argmax(model.predict(test))
。因此,在您的情况下,由于模型仅给出1D向量,因此输出始终为1
。
要使模型正确获取输出,必须使用model.predict()
,如下所示。
prediction_cat = classifier.predict(img_cat)
print("Cat Prediction: "+str(prediction_cat))
prediction_dog = classifier.predict(img_dog)
print("Dog Prediction: "+str(prediction_dog))
然后您将获得类似这样的输出
Cat Prediction: 0.05
Dog Prediction: 0.98
您可以使用阈值将预测的概率映射到类标签。常用阈值为0.5
,但建议根据f1-score
选择阈值。由于您的数据集是平衡的,因此您不必为此担心。您可以进行预测并映射到类标签,如下所示。假设您将cat
编码为0
,将dog
编码为1
# suppose test contains image to predict
threshold = 0.5
pred = model.predict(test)
if pred > threshold:
print('Dog')
else:
print('Cat')