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張預測正確。

發佈了1033 篇原創文章 · 獲贊 999 · 訪問量 340萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章