Python ワンちゃんネコちゃん判定~成功版~

ディープラーニングの例でよく取り上げられる「犬or猫判定」をKerasでやってみた!
Kaggleはデータセットもお手本モデルも提供されててすごい

^--^データセット^--^
Kaggle: Cat and Dog

^--^パクったモデル^--^
Cat or Dog Classification (3 - Models Comparision)

import keras  
from keras.models import Sequential  
from keras.layers.convolutional import Conv2D  
from keras.layers.convolutional import MaxPooling2D  
from keras.layers.core import Activation  
from keras.layers.core import Flatten  
from keras.layers.core import Dropout  
from keras.layers.core import Dense  
from keras import backend as K  
from keras.optimizers import RMSprop, Adam  
from keras.regularizers import l2  
from keras.utils import np_utils  

import numpy as np  
import cv2  
from matplotlib import pyplot as plt  
%matplotlib inline  

# 画像の場所  
TRAIN_DIR = './cat-and-dog/training_set/training_set'  
TEST_DIR = './cat-and-dog/test_set/test_set'  
# 画像をリサイズする大きさ  
IMG_WIDTH = 100  
IMG_HEIGHT = 100  

# 学習画像を読み込む  
# 学習データをリストにする  
train_data = []  
train_label = []  

# ねこ画像4000枚(training_set/cats/cat.1.jpg~cat.4000.jpg)  
for i in range(1,4001):  
    image_name = 'cat.' + str(i) + '.jpg'  
    # opencvで画像を読み込む  
    image = cv2.imread(TRAIN_DIR + '/cats/' + image_name)  
    # opencvで画像を100×100にリサイズ  
    image = cv2.resize(image, (IMG_WIDTH, IMG_HEIGHT))  
    # リサイズした画像を学習データリストに追加  
    train_data.append(image)  
    # 2クラス分類(犬or猫)なのでラベルは0と1を使用  
    train_label.append(0)  

# いぬ画像4000枚(training_set/dogs/dog.1.jpg~dog.4000.jpg)  
for i in range(1,4001):  
    image_name = 'dog.' + str(i) + '.jpg'  
    image = cv2.imread(TRAIN_DIR + '/dogs/' + image_name)  
    image = cv2.resize(image, (IMG_WIDTH, IMG_HEIGHT))  
    train_data.append(image)  
    train_label.append(1)  

# ニューラルネットワークに画像データを入れるためにリスト→配列に変換  
train_data = np.array(train_data)  

# 正解ラベル(cat,dog)をone-hotエンコード  
train_label = keras.utils.to_categorical(train_label, 2)  

# テスト画像を読み込む  
# テストデータをリストにする  
test_data = []  
test_label = []  

# ねこ画像1000枚(training_set/cats/cat.4001.jpg~cat.5000.jpg)  
for i in range(4001,5001):  
    image_name = 'cat.' + str(i) + '.jpg'  
    image = cv2.imread(TEST_DIR + '/cats/' + image_name)  
    image = cv2.resize(image, (IMG_WIDTH, IMG_HEIGHT))  
    test_data.append(image)  
    test_label.append(0)  

# いぬ画像1000枚(training_set/dogs/dog.4001.jpg~dog.5000.jpg)  
for i in range(4001,5001):  
    image_name = 'dog.' + str(i) + '.jpg'  
    image = cv2.imread(TEST_DIR + '/dogs/' + image_name)  
    image = cv2.resize(image, (IMG_WIDTH, IMG_HEIGHT))  
    test_data.append(image)  
    test_label.append(1)  

# ニューラルネットワークに画像データを入れるためにリスト→配列に変換  
test_data = np.array(test_data)  

# 正解ラベル(cat,dog)をone-hotエンコード  
test_label = keras.utils.to_categorical(test_label, 2)  

# CNNモデルを構築  
model = Sequential()  

model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(100, 100, 3)))  
model.add(MaxPooling2D((2, 2)))  
model.add(Conv2D(64, (3, 3), activation='relu'))  
model.add(MaxPooling2D((2, 2)))  
model.add(Conv2D(128, (3, 3), activation='relu'))  
model.add(MaxPooling2D((2, 2)))  
model.add(Conv2D(256, (3, 3), activation='relu'))  
model.add(MaxPooling2D((2, 2)))  

# 一次元に変換する層  
model.add(Flatten())  

# 50%の入力ノードを無効にする(過学習の防止)  
model.add(Dropout(0.5))  
model.add(Dense(512, activation='relu'))  
model.add(Dense(2, activation='softmax'))  

# モデルの精度を評価する方法を設定  
model.compile(loss='categorical_crossentropy', optimizer=RMSprop(lr=1e-4), metrics=['accuracy'])  

# モデルの構成を表示  
model.summary()  

# 学習・テスト実行  
history = model.fit(x=train_data, # 学習データ  
                    y=train_label, # 学習ラベル  
                    batch_size=32, # バッチサイズ  
                    epochs=5, # エポック数  
                    verbose=1, # 標準出力に進捗を表示するか  
                    validation_data=(test_data,test_label) # バリデーション(テスト)データ  
                   )  

# グラフのサイズ  
plt.figure(figsize=(10,6))  

# 青線:学習結果  
plt.plot(history.history['accuracy'], color='b')  
# 赤線:テスト結果  
plt.plot(history.history['val_accuracy'], color='r')  

plt.tick_params(labelsize=18)  
plt.title('epoch - accuracy graph')  
# 縦軸:正解率(モデルの精度)  
plt.ylabel('accuracy')  
# 横軸:エポック数  
plt.xlabel('epoch')  
plt.legend(['train','test'])  
plt.show()