飼い猫の種類を判別するAIを作ってみる。


画像認識とQiitaの記事投稿の勉強のために大好きな飼い猫２匹の種類を判別するプログラムを作ってみました。

個人の学習用なのでソースはほぼコピペです（お恥ずかしい。。）

さらに画像を用意するのが面倒だったので飼い猫と同じ種類の画像をネットから拾ってきました…(∩ˊ꒳​ˋ∩)

まず画像をnumpy配列型に変換し保存しておきます。

```Python:data.py
from PIL import Image
import os, glob
import numpy as np
import random, math

#学習用画像が保存されているディレクトリ
train_dir = "./train"

#テスト用画像が保存されているディレクトリ
test_dir = "./test"

# 猫の種類
categories = ["ノルウェージャン","アビシニアン"]
# 画像データ用配列
X = []
# ラベルデータ用配列
Y = []

#画像データごとにadd_sample()を呼び出し、X,Yの配列を返す関数
def make_sample(files):
    global X, Y
    X = []
    Y = []
    for cat, fname in files:
        add_sample(cat, fname)
    return np.array(X), np.array(Y)

def add_sample(cat, fname):
    img = Image.open(fname)
    img = img.convert("RGB")
    img = img.resize((150, 150))
    data = np.asarray(img)
    X.append(data)
    Y.append(cat)

#学習用画像
trainfiles = []
#テスト用画像
testfiles = []

for idx, cat in enumerate(categories):
    image_dir = train_dir + "/" + cat
    files = glob.glob(image_dir + "/*.jpg")
    for f in files:
        trainfiles.append((idx, f))
        
for idx, cat in enumerate(categories):
    image_dir = test_dir + "/" + cat
    files = glob.glob(image_dir + "/*.jpg")
    for f in files:
        testfiles.append((idx, f))

X_train, y_train = make_sample(trainfiles)
X_test, y_test = make_sample(testfiles)
xy = (X_train, X_test, y_train, y_test)
#データを保存する
np.save("./data/tea_data.npy", xy)
```

続いて学習と、結果の確認ですー。

```Python:test.py
from keras import layers, models,optimizers

from PIL import Image
import os, glob
import numpy as np
import random, math
import matplotlib.pyplot as plt
from keras.utils import np_utils

#カーネルが死なないようにするおまじない。。
os.environ ['KMP_DUPLICATE_LIB_OK'] = 'True'

model = models.Sequential()
model.add(layers.Conv2D(32,(3,3),activation="relu",input_shape=(150,150,3)))
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.Conv2D(64,(3,3),activation="relu"))
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.Conv2D(128,(3,3),activation="relu"))
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.Conv2D(128,(3,3),activation="relu"))
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.Flatten())
model.add(layers.Dense(512,activation="relu"))
#ここの「２」は判別する猫の種類数
model.add(layers.Dense(2,activation="sigmoid")) 
model.compile(loss='categorical_crossentropy',optimizer='adadelta',metrics=['accuracy'])

#保存した画像データ
X_train, X_test, y_train, y_test = np.load("./data/tea_data.npy")

#データの正規化
X_train2 = X_train.astype("float") / 255
X_test2  = X_test.astype("float")  / 255

#kerasで扱えるようにcategoriesをベクトルに変換
y_train2 = np_utils.to_categorical(y_train2, nb_classes)
y_test2  = np_utils.to_categorical(y_test2, nb_classes)

model = model.fit(X_train2,y_train2,epochs=2,batch_size=1,validation_data=(X_test2,y_test2))

score = model.model.evaluate(x=X_test,y=y_test)

print('loss=', score[0])
print('accuracy=', score[1])

# データの可視化（テストデータの先頭の5枚）
for i in range(5):
    plt.subplot(2, 5, i+1)
    plt.imshow(X_test[i], 'gray')

# 予測（テストデータの先頭の5枚）
pred = np.argmax(model.predict(X_test[0:5]), axis=1)
print(pred)
```


出力結果↓
0がノルウェージャンフォレストキャット、１がアビシニアンです。無事全問正解してくれました。
画像を水増ししたせいなのか、エポック数は２回がベストでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401957/5f2160ba-977d-0037-21d8-60e7c4597ff9.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401957/6076c9e2-23cf-c5cb-e8bb-89fed0a53968.png)