Deep Learningの判断根拠を可視化する手法でサイゼリヤの間違い探しを解く

# サイゼリヤ
サイゼリヤはその圧倒的なコストパフォーマンスと独自の色を持った本格的イタリアンメニューを兼ね備えた，老若男女に人気のレストランである．その硬派で心意気を感じる料理たちは食通やイタリア出身者を唸らせるほどでもある．そしてそのルネッサンス期の絵画を基調とした美しい内装に囲まれながら，異国の味に舌鼓をうつ瞬間は万人にとって至福のひと時である．さて，サイゼリヤを彩るものはおいしい食事と優美な内装だけではない．ともすれば酒飲みのための店ともなりかねないサイゼにファミリーレストランとしての強度を与えている強力なエンターテインメントがあるのだ．そう，**キッズメニューの間違い探し**である．
以下に引用するのがサイゼリヤの間違い探しの例である．かなり簡単に見つかる間違いもあるが，大人が探しても結構難しいものもある．
![matigaisagashi.jpg](https://qiita-image-store.s3.amazonaws.com/0/142264/fb0b5e5f-3340-820b-d532-2cbb294b6f20.jpeg)
(出典:https://www.saizeriya.co.jp/entertainment/)

# 先行研究
根を上げた大人たちが画像処理技術を用いて解いた例がいくつかあった．
https://qiita.com/takacpu55/items/88e2e2fceb4e9fa22c91
http://kawalabo.blogspot.com/2014/11/blog-post.html

前者は，写真からの検出というよりチャレンジングなタスク，後者は公式HPで配布されている画像からの検出というやや優しめのタスクに取り組んでいる．差分をとったからといって必ずしも簡単に特定できるわけではないようだ．前者の方が結果としては上手くいっている．局所差分をとることがポイントのようで，false-positiveを許容すればほぼ確実に間違いを特定することができるようだ．

# Grad-CAM
さて最近は画像処理の研究では猫も杓子もディープラーニングを使っている．今回のタスクもディープラーニングを使って解けないかということを考えた．しかし間違い探しをするようなネットワークはおそらく提案されていないように思える．
そこで今回は間違い探しとは画像中に間違いがあるかないかの二値分類であるとかんがえ，**オリジナルと間違いが含まれる画像を判別するDNNをトレーニングし，DNNの判断根拠を説明する手法によって，間違いの場所を特定する**という手法をとることにした．
今回はGrad-CAMという手法を用いた．
Grad-CAMは，まずNNに対してクラス判定を行わせ，目的のクラス出力に対するconv最終層の出力の勾配に基づいて，conv最終層の出力の重みづけ平均をとることで，クラス判定に重要な位置を特定する手法である．2年ほど前に提案された手法であり，日本語での解説も多く出ている．同論文ではGrad-CAMはGuided-BackPropと組み合わせることで，より反応位置を詳細に知ることができるとされている．Guided-BackPropは負のgradientを伝播しないようにしたうえで，対象となるconv層の出力の入力に対するグラディエントをとる（conv層の出力は位置ごとに（チャネルの中で）最大値をとったうえで合計をとっている）という手法である．これを用いると，チャネルも含めたより詳細な反応位置を知ることが可能である．


# 手法
今回は画像の下準備の手間を考えて，サイゼリヤのホームページから直接画像を引っ張ってくることにした．
まず適当に画像を間違いなしのものとありのものに分割する．
左右の画像をそのまま供給して分類させても，なぜなら分かりやすい間違いだけで分類するようになると考えられるので，そこで今回は元画像のサイズから180*180の画像をランダムにクロップして判定させるNNをトレーニングさせることにした．
しかし問題が発生した．全然間違いを検出せず，謎の場所を根拠として出力してしまうのである．よく見るとその付近にはJPEGのエンコードノイズっぽいものが乗っていることが分かった．これに基づいて判断しているかは謎だが，想定していないなartifactを取り除くため，供給する画像にはGaussian BlurをかけGaussian noiseを乗せることとした．

ネットワークはConv4層FC2層のCNNを使用した．short cut connectionは，ResnetとGradCAMがあまり相性が良くないという話もあったので使わなかった．学習済みモデルを使うことも考えたが，今回の間違い探しはイラスト風なのでImagenetによるpretrainingでは良い成果が出にくいと考え，使わなかった．また大域的な特徴をとるために一層目のConvは9x9にした．最適化はAdamでlr=1e-3とし，ほかはデフォルト値で1000エポックほど回した．

コードは長くなるのでGithubに上げている．(https://github.com/caprest/Spot_The_Difference_with_Grad_CAM)注意する点としてはGrad CAMを評価する際にナイーブにGradCAM+Guided-back propをfor文で回したりすると1000倍ぐらい時間がかかってしまうという点がある．

# 結果
以下の画像はGrad-CAMのヒートマップ(150*150)をストライドを10として畳み込みの要領で得て，画像全体で平均を計算したものである．
![left.png](https://qiita-image-store.s3.amazonaws.com/0/142264/504d4927-2006-d807-4b25-3b30fba4aab8.png)
![right_1.png](https://qiita-image-store.s3.amazonaws.com/0/142264/18353a8a-dd8c-82f8-40ea-a71b440f68d4.png)
下が正しい画像．
間違いは9つあり
1.トリノ付近の地図の形状，
2.ランプルスコの蓋
3.Menn->Menu
4.プロシュート<->豚
5.ローマの位置
6.スパゲッティ
7.トマトの形状
8.ピスタチオの数
9.魚の有無
10.サルディニア島の形状
であるが，なんとなくその付近が光っていることもあれば，それ以外の部分に反応していることもあるだろう．比較的うまくいっているのは2,4,6,9.全く検出できていないのは3であろうか．間違いとしては特に何もないはずのメニュー右端にかなり強く反応してしまっている．
部分部分をピックアップすると（ネットワークから直接導出したGrad-CAM）と以下のような例が挙げられる．
![list.png](https://qiita-image-store.s3.amazonaws.com/0/142264/3449ed42-e8b7-8819-f36c-9ec0e034b692.png)
![list2.pn.png](https://qiita-image-store.s3.amazonaws.com/0/142264/7f8c7865-d863-814a-79ef-ee2ad334abf2.png)


Guided Back Propagationと積をとったものは画像も暗くあまりよく分からない結果となってしまった．魚にかろうじて反応していることが読み取れるようにも思える．
![ダウンロード.png](https://qiita-image-store.s3.amazonaws.com/0/142264/049341d7-89f7-75fa-23bd-291512b1f3d4.png)

結果としては，OpenCVでマッチングしたものより100倍以上の時間と計算量がかかっているのにもかかわらず，性能は大したことはなかった．といえよう．

# 考察
端の方にエラーが多いのはランダムに領域をクロッピングする際に，端の方の桝はサイズの関係上選ばれにくいということがあるだろう．これは適当に重みづけしてやってサンプルされる頻度を改善すればうまくいく可能性はあるように思える．

# 感想
当たり前だが，この問題を解く手法としてGrad-CAMを使う手法はおそらく良い方法ではない．結局学習は1000エポックほど回す必要があり，Grad-CAM自体の計算もGPUなしではそこそこ時間を要する．いずれにしろGPUなしでは現実的でない手法である．ただし古典的アルゴリズムでなくDeepを使うとよいかもしれない可能性はあって，Deepな手法ならば人にとって本質的な間違いとそうでない間違いの判別ができる可能性があるかもしれない．特に撮影時のノイズに寄らない判別が可能になることはありうる．
意外とFuture Workは考えられて，「豚が生ハムに代わっている」のように自然言語で間違いを指摘出来るようになったら論文にもなる気がしないでもない．Semantic Segmentationや画像annotationの手法をうまく活用すればそういったことも可能になるかもしれない．このように考えると間違い探しというタスクは画像処理のタスクとして面白いようにも思える．応用先としては異常検知やデザインなどの支援にも使える可能性はある．
また実際にカメラを用いて間違い探しを解くとなったら，ページ検出の問題が重要になる．ここらへんを全部自動化していけるようなモデルは全く考えつかない．なんやかんや言って頑張れば間違いを自然言語で指摘できる人間はすごい．また人間からすると"イタリアの地図の形の微妙な違い"のような言語化しにくい間違いはやはり見つけにくい．annotation的なことは人間の視覚の本質的な部分にかかわっているようにも思える．

# 画像出典
https://www.saizeriya.co.jp/entertainment/
2006年の間違い探しより．
サイゼリヤのサラミは本当においしいので食べてほしい．

# 参考
Grad-CAMの論文　https://arxiv.org/pdf/1610.02391.pdf
Grad-CAMの実装　https://qiita.com/icoxfog417/items/8689f943fd1225e24358
Guided-BackPropの実装 https://github.com/jacobgil/keras-grad-cam/blob/master/grad-cam.py
Guided-BackPropの解説　https://www.cs.toronto.edu/~guerzhoy/321/lec/W07/HowConvNetsSee.pdf
Grad-CAMの解説など
https://urusulambda.wordpress.com/2018/01/13/grad-cam%E3%81%AE%E8%AB%96%E6%96%87%E3%82%92%E6%B5%81%E3%81%97%E8%AA%AD%E3%82%80/
DNNの判断根拠を求める手法のサーベイ
https://qiita.com/icoxfog417/items/8689f943fd1225e24358