Keras CNN + Google Colab始终预测1级(高级培训+验证准确性)

时间:2019-02-27 21:45:50

标签: keras

嗨,我正在使用以下代码在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))

结果:

enter image description here

请建议您是否在代码中看到任何错误

1 个答案:

答案 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激活的节点。这样的预测调用模型可提供01范围内的输出概率。

您正在模型上调用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')