動機
正直に言うと動物病院に来る犬で、たまに犬種が分からないのがいる。もちろん問診票に犬種を書いてもらうから心配する必要はないが、獣医として自分の力で犬種を特定したい。いくら犬種を勉強しても、「ああ、この子は珍しい犬種で日本で5頭しかいないんですよ~」とか言われることもある。
こうなったら機械学習を使おうと思う。備え付けカメラで犬を撮影し、機械学習で犬種を特定する。自分の力で犬種を特定したと言えるのかは甚だ疑問だが、仕方ない。
方法
画像分類タスクは、Convolutional Neural Network(CNN)が得意。CNNを使う事を決めた。さてどう学習させるか。作戦は3つ。
- 作戦1 犬種ごとに写真を用意 + CNNを0から学習させる
- 作戦2 犬種ごとに写真を用意 + 学習済みCNNの最終層を再学習させる(fine tuning)
- 作戦3 犬種ごとに写真を用意 + 重みを固定した学習済みCNNの後に層を追加して学習させる(transfer learning)
作戦1は犬種ごとの写真が大量に必要だ。珍しい犬種なんてどうしよう。作戦2・作戦3は既に画像の特徴を捉える能力を持ったCNNを使うために、少ない画像で済むそうだ。作戦2・作戦3を使うしかない。作戦2・作戦3のどちらにするかは、精度を見て決めればいいのでまずは作業を開始する。
どの学習済みモデルを使うべきか。tensorflowの中に複数の学習済みモデルがあるけど、どれにしよう。以下のgithubレポジトリを見ると他のモデルよりもefficientnetの方がパラメータも少なくて精度が出ている。
https://github.com/tensorflow/tpu/tree/master/models/official/efficientnet
efficientnetを使う事にした。さて、efficientnetはどういった画像を学習させているのだろうか、1400万枚以上の画像を学習させて(imagenet)1000クラスも分類できるらしい、すごいな!!
とりあえず、適当にうちの犬の写真を分類させてみた。これは、犬ですとか出るのかな。
from tensorflow.keras.applications import EfficientNetB0
from tensorflow.keras.preprocessing.image import load_img, img_to_array
import numpy as np
import tensorflow as tf
# 写真の前処理を行う※
pic = load_img("/content/dog.jpg", target_size= (224,224,3))
pic = img_to_array(pic).astype('float32')
pic = np.expand_dims(pic,axis=0)
processedpic = tf.keras.applications.efficientnet.preprocess_input(pic)
# efficientnetのモデルを読み込む
model = EfficientNetB0(weights='imagenet')
# modelを使って犬種・猫種を予想する
prediction = model.predict(processedpic)
tf.keras.applications.efficientnet.decode_predictions(prediction)
[[(‘n02099712’, ‘Labrador_retriever’, 0.42502728),
(‘n02093428’, ‘American_Staffordshire_terrier’, 0.04134651),
(‘n02109961’, ‘Eskimo_dog’, 0.032269508),
(‘n02110185’, ‘Siberian_husky’, 0.031741217),
(‘n02093256’, ‘Staffordshire_bullterrier’, 0.024241285)]]
Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/imagenet_class_index.json
犬どころか、かなり具体的な犬種を区別できているぞ。まさか、すでに犬種の分類タスクをできるのではないか。あと、結果のところにjsonのURLがでてきた。見てみると、分類できる1000クラスが載っている!
犬はコードn02085620からn02116738の125犬種、猫はn02123045~n02124075の5種類を区別できることがわかった。
急に、終わりが訪れた。もう私のすることはないのだ。こうなったら、意地悪をして遊んでみよう。このミックス犬はどの犬種と判断しますか。
PxHere[[('n02087046', 'toy_terrier', 0.2920945),
('n02110806', 'basenji', 0.14723742),
('n02085620', 'Chihuahua', 0.101308264),
('n02113023', 'Pembroke', 0.03310363),
('n02113186', 'Cardigan', 0.024589175)]]
...いいところでしょう。
google colab
すぐに犬種・猫種の特定ができるように、google colabのサンプルを作りました。
https://colab.research.google.com/github/yuta-vet/Dog-Cat-breed-indentify/blob/main/DogCatbreed_identify.ipynb
参考