Pythonで画像認識をしてみました!
この記事では、画像認識をしてみたいけど、手順がわからない方へ向けて、画像認識の手順をまとめていきます。
なお、今回行う画像認識は、CIFAR-10という10種類の約6万枚の画像にあらかじめラベル付け(タグ付け)されているデータセットを使います。
そのため、画像にラベル付けを行う作業の説明は省かせていただくので、ご了承ください。
しかしながら、CIFAR-10のデータセットを使うことで、画像認識の基礎的な流れについて学ぶことができるので、この記事で画像認識の手順を学ぶ意義は大いにあると思います。
開発環境は以下の通りです。
OS:Windows10
Python 3.6.5
Tensorflow-gpu 1.9.0
CUDA v9.0
cudnn v7.0.5
記事最下部のまとめにコードを全部まとめて貼ってあるので、そちらもご参照ください。
ではさっそく見ていきましょう!
■画像認識をする手順【CIFAR-10】
以下に画像認識の手順をまとめています。初めに説明したとおり、今回はあらかじめラベル付けがされている画像を使うので、ラベル付けの方法の説明はないのでご了承ください。
インポートしたライブラリは以下の6つです。
1 2 3 4 5 |
import keras from keras.datasets import cifar10 from keras.models import Sequential from keras.layers import Dense, Dropout, Activation, Flatten from keras.layers import Conv2D, MaxPooling2D |
・データセットの読み込み、変換
初めにCIFAR-10から画像データセットを読み込みます。以下のコードで読み込みを行えます。
1 |
(X_train, y_train), (X_test, y_test) = cifar10.load_data() |
あらかじめラベル付けされたデータを訓練データ(X_train, y_train)とテスト用データ(X_test, y_test)に分けて読み込んでいます。Xが画像データで、yがラベルデータになります。
ここで読み込まれた画像をそのままの状態では、学習することができません。理由は、tensorflowで扱える配列と次元が異なるためです。 CIFAR-10の画像は3次元の配列で構成されているため、tensorflowで扱える1次元配列に変換する必要があるとのこと。 以下のコードで、画像データを1次元配列に変換しています。
1 2 |
X_train = X_train.astype("float32")/255 X_test = X_test.astype("float32")/255 |
また、ラベルデータをOne-Hot形式に変換する必要もあります。 One-Hot形式というのは、[0, 0, 0, 0, 0, 0, 0, 1, 0, 0]のような形式です。1の要素に該当するラベルが出力としてでるようになります。 以下のコードで、変換できます。
1 2 |
y_train = keras.utils.to_categorical(y_train, 10) y_test = keras.utils.to_categorical(y_test, 10) |
・学習モデルの定義、コンパイル
学習モデルを定義しましょう。
といってもここは、参考書籍のコピペになります。
以下のコードをそのままコピペでOKです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
model = Sequential() model.add(Conv2D(32,(3,3), padding="same", input_shape=(32,32,3))) model.add(Activation("relu")) model.add(Conv2D(32,(3,3))) model.add(Activation("relu")) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.25)) model.add(Conv2D(64,(3,3), padding="same")) model.add(Activation("relu")) model.add(Conv2D(64,(3,3))) model.add(Activation("relu")) model.add(MaxPooling2D(pool_size=(2,2))) model.add(Dropout(0.25)) model.add(Flatten()) model.add(Dense(512)) model.add(Activation('relu')) model.add(Dropout(0.5)) model.add(Dense(10)) model.add(Activation("softmax")) |
次に定義したモデルをコンパイルしていきます。
以下のコードでコンパイルします。
1 2 3 4 |
model.compile( loss="categorical_crossentropy", optimizer="adam", metrics=["accuracy"] |
お次はいよいよ学習の開始です。
・学習の実行、評価
画像認識のための学習を行います。tensorflow内でトレーニング画像データの特徴を学習し、テスト画像データを判定しています。
学習の実行は以下のコードです。
1 2 3 4 |
hist = model.fit(X_train, y_train, batch_size=32, epochs=50, verbose=1, validation_data=(X_test, y_test)) |
次にテストデータを判定し、正解率を評価していきます。
1 2 |
score = model.evaluate(X_test, y_test, verbose=1) print("accuracy=", score[1], "loss", score[0]) |
学習したモデルにテスト画像データを与えて、画像認識を行っています。
2行目のprint文で、正解率を出力しています。
私が行ってみた結果、正解率79.0%とまあまあの結果でした。
1 |
accuracy= 0.7895 loss 0.6928192703723908 |
・モデルの保存
せっかく学習したモデルなんですから使わないのはもったいない。
ということで、学習したモデルを保存しておきましょう。
以下のコードでモデルデータ、重みデータを保存できます。
1 2 |
model.save("cifar10_model.h5") #モデルデータ保存 model.save_weights("cifar10_weight.h5") #重みデータ保存 |
(“保存したいファイル名.h5”)のようにコーディングします。
モデルデータがモデル定義でつくったデータで、重みデータが学習した画像の特徴をまとめたデータになります。
も少し詳しく説明。。。
今回使ったモデルでは正解率が約80%ということで、実用的ではありませんよね。
なので、別のモデルを使いたいとか、モデルを改良したいって場合には、今回保存した重みデータを別モデルに読み込ませることもできます。
・モデルデータ→画像認識の仕組みのデータ
・重みデータ→今回学習した画像の特徴を記録したデータ
以上のような認識でだいたいあってると思います。
■まとめ
以上で説明したコードをまとめると、以下のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
import keras from keras.datasets import cifar10 from keras.models import Sequential from keras.layers import Dense, Dropout, Activation, Flatten from keras.layers import Conv2D, MaxPooling2D #画像データの読み込み (X_train, y_train), (X_test, y_test) = cifar10.load_data() #画像データを1次元配列に変換 X_train = X_train.astype("float32")/255 X_test = X_test.astype("float32")/255 #ラベルをOne-Hot形式へ変換 y_train = keras.utils.to_categorical(y_train, 10) y_test = keras.utils.to_categorical(y_test, 10) #モデルを定義 model = Sequential() model.add(Conv2D(32,(3,3), padding="same", input_shape=(32,32,3))) model.add(Activation("relu")) model.add(Conv2D(32,(3,3))) model.add(Activation("relu")) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.25)) model.add(Conv2D(64,(3,3), padding="same")) model.add(Activation("relu")) model.add(Conv2D(64,(3,3))) model.add(Activation("relu")) model.add(MaxPooling2D(pool_size=(2,2))) model.add(Dropout(0.25)) model.add(Flatten()) model.add(Dense(512)) model.add(Activation('relu')) model.add(Dropout(0.5)) model.add(Dense(10)) model.add(Activation("softmax")) #モデルをコンパイル model.compile( loss="categorical_crossentropy", optimizer="adam", metrics=["accuracy"]) #学習を実行 hist = model.fit(X_train, y_train, batch_size=32, epochs=50, verbose=1, validation_data=(X_test, y_test)) #テストデータを評価する score = model.evaluate(X_test, y_test, verbose=1) print("accuracy=", score[1], "loss", score[0]) #学習モデル、重みデータの保存 model.save("cifar10_model.h5") model.save_weights("cifar10_weight.h5") |
今回はあらかじめラベル付けされた画像を使ったので、ラベル付けという作業を行わずに画像認識を行うことができました。
といってもまだ、自分で用意した画像を読み込むことができていないので、実用には程遠いところですね。
次回は今回学習したモデルを使って、自分で用意した画像を判定をしていきたいと思います。
最後まで読んでいただきありがとうございました。
今回参考にした書籍はこちら