(深層学習の画像認識。)実装まちがい検証方法。[学習済みモデル編]

#目的
深層学習の画像認識に関して、いろいろなサイトの情報、コードを参考にしながら作業されると思う。

その際に、参照したサイトの情報そのものが誤っている場合や、自分なりの変更を加える際に誤りが入る場合がある。

しかし、
深層学習の画像認識の場合、その誤りの作用が、検出率等に現れるため、小さい誤りには、気づくことができない。

自分の実例として、

* kerasで、preprocess_inputの処理ヌケ

をやってしまったことあり。検出率が結構悪くなる。

|普通のプログラミングと同じように、なんかで検証したい。|
|:---:|

ここでは、
**imagenetの学習済みモデルを使う場合**の検証方法を示す。
残念ながら、**全然、つまらない内容です。**（将来、もっといい方法が提案できることを期待しての記事。）

#検証方法
##検証方法概要

|以下に示す正しい検出結果と比較し、大きな差がないか確認する。|
|:---:|

imagenetの画像（後に、URLを記載する）に対する、代表的なネットワークモデルでの検出結果を以下に示す。
この率と比較し、悪くなっている場合には、おそらく、どこかに実装まちがいがある。

* たぶん、適当な想像でいうと、1/10～1/50ぐらいの確率で間違いが入っているので、検証してみて下さい。fineチューニングとかされている方は、その手前のフェーズで確認下さい。

##正解作成のコード

https://keras.io/ja/applications/
に記載の以下のコードを利用。VGG16の場合は、該当部分をVGG16に変更して利用。

```python
from keras.applications.resnet50 import ResNet50
from keras.preprocessing import image
from keras.applications.resnet50 import preprocess_input, decode_predictions
import numpy as np

model = ResNet50(weights='imagenet')

img_path = 'elephant.jpg'
img = image.load_img(img_path, target_size=(224, 224))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)

preds = model.predict(x)
# decode the results into a list of tuples (class, description, probability)
# (one such list for each sample in the batch)
print('Predicted:', decode_predictions(preds, top=3)[0])
# Predicted: [(u'n02504013', u'Indian_elephant', 0.82658225), (u'n01871265', u'tusker', 0.1122357), (u'n02504458', u'African_elephant', 0.061040461)]


```


##imagenetの画像のURLと正解の例

###imagenetの画像のURL
（このページの画像は、あえて、直接リンクしていますので、
画像が表示されていなかった場合には、その画像は、imagenetの元画像のリンク先の消滅を意味します。その場合は、気づいたら見直します。）

■Indian elephant, Elephas maximus
画像EL01:
http://farm3.static.flickr.com/2154/1880985183_37d1b66617.jpg
<img src="http://farm3.static.flickr.com/2154/1880985183_37d1b66617.jpg" width=150>
画像EL02:
http://static.flickr.com/49/117174803_7f3ac571fb.jpg
<img src="http://static.flickr.com/49/117174803_7f3ac571fb.jpg" width=150>

■Pineapple, ananas
画像PI01:
http://farm1.static.flickr.com/144/387502364_5063d4b0f7.jpg
<img src="http://farm1.static.flickr.com/144/387502364_5063d4b0f7.jpg" width=150>

画像PI02:
http://static.flickr.com/109/256830232_c8cfe8ea58.jpg
<img src="http://static.flickr.com/109/256830232_c8cfe8ea58.jpg
" width=150>

■Harp
画像HA01:
http://www.museweb.com/harp/harp2.jpg
<img src="http://www.museweb.com/harp/harp2.jpg" width=150>
画像HA02:
http://cimg2.163.com/catchimg/20080328/4242764_3.jpg
<img src="http://cimg2.163.com/catchimg/20080328/4242764_3.jpg" width=150>

■Volcano
画像VO01:
http://static.flickr.com/1240/1475476681_78b02ab5ff.jpg
<img src="http://static.flickr.com/1240/1475476681_78b02ab5ff.jpg" width=150>

画像VO02:
http://ccn1.net/POTD7/mount-merapi-indonesia-lava-flow.jpg
↑↓（何かのマジックで、Qiita記事で画像が表示されないことがあるかも。ただ、リンクは正常なので、無視して下さい。htmlタグでの画像表示のメモリ制限？）
<img src="http://ccn1.net/POTD7/mount-merapi-indonesia-lava-flow.jpg" width=150>

　
###正解の値
当然、ぴったりにはならないと思うが、大きく違い場合には、誤りがある可能性大:tada:。
3個ぐらい確認されたら十分だと思う。


|画像|モデル|検出結果|備考|
|:---:|:---:|:---|:---|
|VGG16|EL01|Predicted: [('n02504013', 'Indian_elephant', **0.833636**), ('n01871265', 'tusker', 0.12866537), ('n02504458', 'African_elephant', 0.03769341)]||
|ResNet50|EL01|Predicted: [('n02504013', 'Indian_elephant', **0.9857305**), ('n01871265', 'tusker', 0.013525052), ('n02504458', 'African_elephant', 0.0007442717)]||
|VGG16|EL02|Predicted: [('n02504013', 'Indian_elephant', **0.75173104**), ('n01871265', 'tusker', 0.24751662), ('n02504458', 'African_elephant', 0.0007522634)]|やや難(for VGG16)|
|ResNet50|EL02|Predicted: [('n02504013', 'Indian_elephant', **0.97112095**), ('n01871265', 'tusker', 0.027640266), ('n02504458', 'African_elephant', 0.0012386243)]||
|VGG16|PI01|Predicted: [('n07753275', 'pineapple', **0.996912**), ('n13133613', 'ear', 0.00084473507), ('n07718747', 'artichoke', 0.0004579855)]|超簡単|
|ResNet50|PI01|Predicted: [('n07753275', 'pineapple', **0.9999776**), ('n07718747', 'artichoke', 1.2844453e-05), ('n07730033', 'cardoon', 4.376461e-06)]|超簡単|
|VGG16|PI02|Predicted: [('n07753275', 'pineapple', **0.99997294**), ('n13133613', 'ear', 8.0268e-06), ('n07730033', 'cardoon', 7.1270415e-06)]|超簡単|
|ResNet50|PI02|Predicted: [('n07753275', 'pineapple', **0.9998945**), ('n07753592', 'banana', 3.5718625e-05), ('n07730033', 'cardoon', 1.8827097e-05)]|超簡単|
|VGG16|HA01|Predicted: [('n03495258', 'harp', **0.99799997**), ('n04099969', 'rocking_chair', 0.0010214928), ('n04371774', 'swing', 0.0005899669)]||
|ResNet50|HA01|Predicted: [('n03495258', 'harp', **0.99999857**), ('n04099969', 'rocking_chair', 9.4274117e-07), ('n02672831', 'accordion', 1.4885055e-07)]||
|VGG16|HA02|Predicted: [('n03495258', 'harp', **1.0**), ('n03884397', 'panpipe', 6.816577e-11), ('n04366367', 'suspension_bridge', 2.1885547e-11)]|超簡単|
|ResNet50|HA02|Predicted: [('n03495258', 'harp', **1.0**), ('n04515003', 'upright', 2.1177697e-09), ('n04366367', 'suspension_bridge', 6.3267114e-10)]|超簡単|
|VGG16|VO01|Predicted: [('n09472597', 'volcano', **0.95020926**), ('n04613696', 'yurt', 0.014534893), ('n09468604', 'valley', 0.0025977397)]||
|ResNet50|VO01|Predicted: [('n09472597', 'volcano', **0.9997687**), ('n02403003', 'ox', 6.6148e-05), ('n03868242', 'oxcart', 4.8434395e-05)]||
|VGG16|VO02|Predicted: [('n09472597', 'volcano', **0.70913243**), ('n04456115', 'torch', 0.26235902), ('n03729826', 'matchstick', 0.018098248)]|やや難(for VGG16)|
|ResNet50|VO02|Predicted: [('n09472597', 'volcano', **0.99358094**), ('n04456115', 'torch', 0.0024112444), ('n04330267', 'stove', 0.0010505004)]||

##念のため、環境

Keras                    2.3.1
tensorflow               2.0.0
（※　tensorflow関係ある？）

おそらく、余程、古いバージョンでない限り関係ないかと。
また、別のフレームワーク（その学習済モデル）だとしても、おそらく、大きくは違わないはず。

#まとめ
特にありませんが、間違い等お気づきの場合には、コメントなどお願いします。:candy:
**ややこしい実装されている方、適当に、一度確認してみてください。実装誤りが入っているかも。**
当然、もう少し、簡便かつ精度のある（OK/NG見極めが定量的な）検出方法を考えたいとも思います。