【python】画像から犬種・猫種を特定する方法（読み物）

# 動機
正直に言うと動物病院に来る犬で、たまに犬種が分からないのがいる。もちろん問診票に犬種を書いてもらうから心配する必要はないが、獣医として自分の力で犬種を特定したい。いくら犬種を勉強しても、「ああ、この子は珍しい犬種で日本で５頭しかいないんですよ～」とか言われることもある。
こうなったら機械学習を使おうと思う。備え付けカメラで犬を撮影し、機械学習で犬種を特定する。自分の力で犬種を特定したと言えるのかは甚だ疑問だが、仕方ない。

# 方法
画像分類タスクは、Convolutional Neural Network（CNN）が得意。CNNを使う事を決めた。さてどう学習させるか。作戦は３つ。
<ul><li>作戦１　犬種ごとに写真を用意　＋　CNNを０から学習させる</li>
<li>作戦２　犬種ごとに写真を用意　＋　学習済みCNNの最終層を再学習させる(fine tuning)</li>
<li>作戦３　犬種ごとに写真を用意　＋　重みを固定した学習済みCNNの後に層を追加して学習させる(transfer learning)</li></ul>

作戦１は犬種ごとの写真が大量に必要だ。珍しい犬種なんてどうしよう。作戦２・作戦３は既に画像の特徴を捉える能力を持ったCNNを使うために、少ない画像で済むそうだ。作戦２・作戦３を使うしかない。作戦２・作戦３のどちらにするかは、精度を見て決めればいいのでまずは作業を開始する。

どの学習済みモデルを使うべきか。tensorflowの中に複数の学習済みモデルがあるけど、どれにしよう。以下のgithubレポジトリを見ると他のモデルよりもefficientnetの方がパラメータも少なくて精度が出ている。
https://github.com/tensorflow/tpu/tree/master/models/official/efficientnet

efficientnetを使う事にした。さて、efficientnetはどういった画像を学習させているのだろうか、1400万枚以上の画像を学習させて（imagenet）1000クラスも分類できるらしい、すごいな！！

とりあえず、適当にうちの犬の写真を分類させてみた。これは、犬ですとか出るのかな。

```python:dog_breed.py
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)
```
![labrador.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/695506/1469d740-2968-84f9-fbaa-c4084c3ee4f6.jpeg)

[[(‘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の５種類を区別できることがわかった。

急に、終わりが訪れた。もう私のすることはないのだ。こうなったら、意地悪をして遊んでみよう。このミックス犬はどの犬種と判断しますか。

<img src="https://c.pxhere.com/photos/84/2f/dog_chihuahua_animal_pet_puppy_cute_terrier_domestic-1168296.jpg!d" srcset="https://c.pxhere.com/photos/84/2f/dog_chihuahua_animal_pet_puppy_cute_terrier_domestic-1168296.jpg!d" alt="白, 子犬, 犬, 動物, 可愛い, イヌ, 夏, 女性, ペット, ポートレート, 若い, マクロ, 小さい, 褐色, 哺乳類, 黒, 閉じる, 楽しい, ハッピー, 脊椎動物, チワワ, ミックス, 国内の, 犬種, テリア, 繁殖, 犬, 哺乳類のような犬, カルニボラン, 犬の品種グループ, ノルウェー・ルンドンド, おもちゃのキツネのテリア, 無料画像 In PxHere">
<a href=https://pxhere.com/ja/photo/1168296>PxHere</a>

[[('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

# 参考
https://meknowledge.jpn.org/2021/05/28/efficient-net-breed-identify/