CNN神经网络猫狗分类经典案例

AI:CNN神经网络猫狗分类经典案例

猫狗的训练数据可以在kaggle下载:

https://www.kaggle.com/tongpython/cat-and-dog/data

本例使用ImageDataGenerator在迭代生成训练数据时候,需要把训练数据和验证,测试数据分类放置到data下面三个不同目录文件夹下。如图:

因为有猫和狗两类,所有在data/train目录下,再建两个目录data/train/dog和data/train/cat:

同理,其他的data/validation和data/test目录下,再建两个目录:cat和data/,在cat和dog目录下,放置对应的图片。

分类建立完成后,Keras会在ImageDataGenerator迭代过程中,自动的为data/train,data/test,data/validation内部生产训练标签,标签依据就是在data/train,data/test,data/validation下面的分类目录,本例是/dog和/cat目录文件夹作为两分类。

import numpy as np
import matplotlib.pyplot as plt
from keras.preprocessing.image import ImageDataGenerator, image
from keras import layers
from keras import models
from keras.layers import Dropout
from keras import optimizers
from keras.models import load_model

train_dir = './data/train/'
validation_dir = './data/validation/'
model_file_name = 'cat_dog_model.h5'


def init_model():
    model = models.Sequential()

    KERNEL_SIZE = (3, 3)

    model.add(layers.Conv2D(filters=32, kernel_size=KERNEL_SIZE, activation='relu', input_shape=(150, 150, 3)))
    model.add(layers.MaxPooling2D((2, 2)))

    model.add(layers.Conv2D(filters=64, kernel_size=KERNEL_SIZE, activation='relu'))
    model.add(layers.MaxPooling2D((2, 2)))

    model.add(layers.Conv2D(filters=128, kernel_size=KERNEL_SIZE, activation='relu'))
    model.add(layers.MaxPooling2D((2, 2)))

    model.add(layers.Conv2D(filters=128, kernel_size=KERNEL_SIZE, activation='relu'))
    model.add(layers.MaxPooling2D((2, 2)))

    model.add(layers.Flatten())
    model.add(layers.Dense(512, activation='relu'))

    model.add(Dropout(0.5))

    model.add(layers.Dense(1, activation='sigmoid'))

    model.compile(loss='binary_crossentropy',
                  optimizer=optimizers.RMSprop(lr=1e-3),
                  metrics=['accuracy'])

    return model


def fig_loss(history):
    history_dict = history.history
    loss_values = history_dict['loss']
    val_loss_values = history_dict['val_loss']
    epochs = range(1, len(loss_values) + 1)
    plt.plot(epochs, loss_values, 'b', label='Training loss')
    plt.plot(epochs, val_loss_values, 'r', label='Validation loss')
    plt.title('Training and validation loss')
    plt.xlabel('Epochs')
    plt.ylabel('Loss')
    plt.legend()
    plt.grid()
    plt.show()


def fig_acc(history):
    history_dict = history.history
    acc = history_dict['accuracy']
    val_acc = history_dict['val_accuracy']
    epochs = range(1, len(acc) + 1)
    plt.plot(epochs, acc, 'g', label='Training acc')
    plt.plot(epochs, val_acc, 'r', label='Validation acc')
    plt.title('Training and validation accuracy')
    plt.xlabel('Epochs')
    plt.ylabel('Accuracy')
    plt.legend()
    plt.grid()
    plt.show()


def fit(model):
    train_datagen = ImageDataGenerator(rescale=1. / 255)
    validation_datagen = ImageDataGenerator(rescale=1. / 255)

    train_generator = train_datagen.flow_from_directory(
        train_dir,
        target_size=(150, 150),
        batch_size=256,
        class_mode='binary')

    validation_generator = validation_datagen.flow_from_directory(
        validation_dir,
        target_size=(150, 150),
        batch_size=64,
        class_mode='binary')

    history = model.fit_generator(
        train_generator,
        # steps_per_epoch=,
        epochs=10,
        validation_data=validation_generator,
        # validation_steps=,
    )

    model.save(model_file_name)

    fig_loss(history)
    fig_acc(history)


def predict():
    model = load_model(model_file_name)
    print(model.summary())

    img_path = './data/test/cat/cat.4021.jpg'
    img = image.load_img(img_path, target_size=(150, 150))
    img_tensor = image.img_to_array(img)
    img_tensor = img_tensor / 255
    img_tensor = np.expand_dims(img_tensor, axis=0)
    # 其形状为 (1, 150, 150, 3)
    plt.imshow(img_tensor[0])
    plt.show()

    result = model.predict(img_tensor)
    print(result)


# 画出count个预测结果和图像
def fig_predict_result(model, count):
    test_datagen = ImageDataGenerator(rescale=1. / 255)
    test_generator = test_datagen.flow_from_directory(
        './data/test/',
        target_size=(150, 150),
        batch_size=256,
        class_mode='binary')

    text_labels = []
    plt.figure(figsize=(30, 20))
    # 迭代器可以迭代很多条数据,但我这里只取第一个结果看看
    for batch, label in test_generator:
        pred = model.predict(batch)
        for i in range(count):
            true_reuslt = label[i]
            print(true_reuslt)
            if pred[i] > 0.5:
                text_labels.append('dog')
            else:
                text_labels.append('cat')

            # 4列,若干行的图
            plt.subplot(count / 4 + 1, 4, i + 1)
            plt.title('This is a ' + text_labels[i])
            imgplot = plt.imshow(batch[i])

        plt.show()

        # 可以接着画很多,但是只是随机看看几条结果。所以这里停下来。
        break


if __name__ == '__main__':
    model = init_model()
    fit(model)

    # 利用训练好的模型预测结果。
    predict()

    model = load_model(model_file_name)
    #随机查看10个预测结果并画出它们
    fig_predict_result(model, 10)

由于太耗时,本例只训练了10轮。

训练损失和验证损失:

训练精度和验证精度:

随机测试在data/test/目录下的猫狗图片,10张,看看 模型预测的结果:

其中1张预测失败,剩余9张预测正确。

发布了1029 篇原创文章 · 获赞 987 · 访问量 336万+

猜你喜欢

转载自blog.csdn.net/zhangphil/article/details/103581736