コインをバラまいた画像から合計金額を推定するＡＩ

世間では、お正月が来たようです。
そこで、初詣に行ったついでに、賽銭箱の底をのぞいてみましょう！
#これいくら？
![scattered_overlapp_yen.jpg](https://qiita-image-store.s3.amazonaws.com/0/216556/cbb97768-0622-358a-9586-18fb0aef619a.jpeg)

こんな画像をパッと見て総額がわかれば、なにかと嬉しいのではないかと。大体でもいいので。
（たとえば神社さんの確定申告システムに直結するとか・・。）
まぁ応用はさておき、いまどきの時代なので、ＡＩに金額を数えさせてみましょう！

しかし、コインが重なりあったりしてると難航しそうな予感。
というわけで、最初は
#条件を単純化します。
![scatter_sparse_yen.jpg](https://qiita-image-store.s3.amazonaws.com/0/216556/74b94397-c883-2c71-c1d3-db1cebbf3af3.jpeg)
このように、コインどうしが重なってないなら、ちょっとハードル下げられるかな？
しかし日本の硬貨6種類（1円5円10円50円100円500円）全部を対象にしてやってみると、手元の環境の環境ではちょっとキビシいみたい。（モデルにもよるでしょうが・・）

あ、手元の環境というのは、[Google Colaboratory (略称:colab)](https://colab.research.google.com/notebooks/welcome.ipynb)　のGPU版です。
（手元・・とはいえないか？）
そこでもうちょっと単純化・・まあ実用の可能性を探るという目的で一歩づつ、いきます。はい、
#１円玉と5円玉と10円玉の3種類しかない貧乏世界
のバージョンで進めていきます。
![scatter_1_5_10yen_yen.jpg](https://qiita-image-store.s3.amazonaws.com/0/216556/6d402afd-2a97-4e02-505b-6306f162e98c.jpeg)
人間が計算する場合でも、コインの種類が少ないほうが易しそうですよね。

ただ、解像度が高いとメモリーとかの負荷が高くなって・・上の画像の場合、300×300ドットのフルカラー画像なんですが、ちょっとやってみると、もう一声、単純化しないとツラそうで・・。
で、こんなかんじにしました。50x50ドット：![scatter_50x50.jpg](https://qiita-image-store.s3.amazonaws.com/0/216556/28ad554a-3dd8-048e-8174-8c115a51a57e.jpeg) 　に圧縮。
・・日本人なら、なんとか金額を計算できる解像度かと。
（今回の colab さんは、米国人かもしれんが（爆））

# 学習／評価用データの生成
で、今回この3種類の硬貨を賽銭箱に投げこんだ、という想定のシミュレーション画像を1000枚生成しました。教師データは金額（=**円）です。
![#000900_0016yen_03(01_01_01_00_00_00).png](https://qiita-image-store.s3.amazonaws.com/0/216556/de34f1b9-030d-d86f-ef11-1b45a63ef498.png)=16円 ![#000901_0028yen_07(03_03_01_00_00_00).png](https://qiita-image-store.s3.amazonaws.com/0/216556/be51775d-e320-96e8-6810-9150dbb62df0.png)=28円 ![#000902_0012yen_03(02_00_01_00_00_00).png](https://qiita-image-store.s3.amazonaws.com/0/216556/fa59825a-3a97-2bf2-8351-2cac379082cf.png)=12円 ![#000903_0009yen_05(04_01_00_00_00_00).png](https://qiita-image-store.s3.amazonaws.com/0/216556/9a028df9-36f6-1527-510b-d41b21f614a2.png)=9円 ![#000904_0021yen_03(01_00_02_00_00_00).png](https://qiita-image-store.s3.amazonaws.com/0/216556/6d8a03ac-b465-e740-d63e-0eb0489852aa.png) =21円・・・・・

#モデリング
昔、取り組んだ、[keras でパターンを数える](https://qiita.com/uminor/items/9fcbba294369f619ac82) の応用で、ちょっとだけディープなモデル：
![image.png](https://qiita-image-store.s3.amazonaws.com/0/216556/98bbcb46-fd7c-b545-77a4-5da9599964e8.png)
（→各数字は，次元数の参考値。50x50といってもRGB3チャンネルあったりするので、まあ目安ということで。詳細は[ソースリスト](https://github.com/uminor/jcoins/blob/master/jcoins_counter.ipynb) を参照。回帰モデルなので、キモとしては、出力層の活性化関数は softmax ではなく、**linear** にしています。)

をつくって学習させてみたところ・・・
各コインの枚数を数えるところまでは、けっこうな精度で出来るようになったものの、シーケンシャルモデルでは、**意外と算数（合計＝各コインの額面と枚数の関和の計算）が苦手**なようなのです。。まあ計算量をつぎ込んだりすれば出来るかもしれませんが。

そこで、「各コインの枚数を数えるシーケンシャルモデル」を3本用意して、合計は「電子計算機」が担当する、という複合モデルにしました。
いわば、**ニューラルネットワークと電子計算機のハイブリッドモデル**ですな。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/216556/403c0ef5-8edb-fe04-8890-56f34c875d8a.png)

なにをいってるんだか・・と言われるかもしれませんが、20世紀後半に急激に発展した「人間が電子計算機を使う」モデルにおいて、「人間」の部分をＡＩに置き換える、という発想です。

#予測／評価
で、1000枚の生成画像のうち、900枚を学習用（各コイン500エポック）、残り100枚を評価用とした場合、評価用画像の予測値がこんな感じになりました。

| 入力画像      |       正解値 |    予測値<br>（=今回のモデル<br>　が認識した<br> 推定値）   |誤差率|
|:-----------------|:-----------------:|:-------------------:|:-------------------:|
| ![#000900_0016yen_03(01_01_01_00_00_00).png](https://qiita-image-store.s3.amazonaws.com/0/216556/c3cc4644-ff96-449c-7f6a-0e5344327fc1.png)            |16 円|16.41 円| 2.55 %|
| ![#000901_0028yen_07(03_03_01_00_00_00).png](https://qiita-image-store.s3.amazonaws.com/0/216556/efe26284-39e0-7ef5-a5af-946d56c516db.png)           |28 円|21.16 円|-24.44 %<br>(※)|
| ![#000902_0012yen_03(02_00_01_00_00_00).png](https://qiita-image-store.s3.amazonaws.com/0/216556/7342e885-e864-2892-f1c4-e33101c485c5.png)             |12 円|11.70 円| -2.51 %|
| ![#000903_0009yen_05(04_01_00_00_00_00).png](https://qiita-image-store.s3.amazonaws.com/0/216556/7cf9702a-d0c7-ce0e-1eaf-dd7f2380adfa.png)              |9 円 |9.13 円| 1.44 %|
| ![#000904_0021yen_03(01_00_02_00_00_00).png](https://qiita-image-store.s3.amazonaws.com/0/216556/082f9e1b-6021-7fb4-4626-ac8c8349b741.png)|             21 円|21.55 円| 2.64 %|
（以下略）

上から2枚目のやつ（※）なんかは、誤差が24.44% とデカいですが、これは学習用データの数を増やすことによって解消に向かうようです。
誤差の原因としては、後述しますが、5円玉に対する認識がわりと苦手のようです。

対して、学習の繰り返し＝エポック数を増やすだけでは、未知の画像に対する精度は、それほど高まらないようです。

#予測データの視覚化
###1円玉の個数推定のバラツキ
　横軸：各画像に含まれる真のコインの個数、
　縦軸：各画像から推定されたコインの個数
　x=y の直線に近いものほど精度が高い推定といえる。以下同様。
![1yen_count.png](https://qiita-image-store.s3.amazonaws.com/0/216556/4e559b80-dc40-978d-41cf-8351370d1e88.png)
(2019/01/27 データ訂正)
###5円玉の個数推定のバラツキ
　・・・5円玉に対しては、他と比べて精度が出にくい。
　さらにサンプル数を増やすことで精度が向上する見込み。
![5yen_count.png](https://qiita-image-store.s3.amazonaws.com/0/216556/8f54b943-2bf9-e878-7ec9-4ba5bce48b1e.png)
###10円玉の個数推定のバラツキ
まぁまぁの精度か。
![10yen_count.png](https://qiita-image-store.s3.amazonaws.com/0/216556/0921509c-f3d8-2aa1-c508-3cabe79f9b97.png)
###トータル金額推定のバラツキ
　横軸：真の金額
　縦軸：画像から推定された各コインの個数から電子計算機で求めた金額

  サンプル画像数：1000枚　の場合　↓
![value_prediction.png](https://qiita-image-store.s3.amazonaws.com/0/216556/d1ec5d75-0c4b-108d-97cd-90ef2cfdd322.png)
　さらにサンプル数を増やすことで精度が向上する。つまり分布が x=y の直線に近づく。

  サンプル画像数：3000枚　の場合　↓　（検証用データは上記と同一）
![value_prediction3000samplesx500ep.png](https://qiita-image-store.s3.amazonaws.com/0/216556/9761a33b-9afd-733a-b785-822519cea243.png)

#結論
以上、今回は実用レベルには達してないものの、**画像認識による計数という分野でポテンシャルを感じられる結果**となったと思います。

#今後の課題
・コインの種類を拡大（・・50円、100円、500円）
・重なり合ったコインの対応
・実写画像への対応、背景などのノイズ耐性向上
・賽銭箱への実装～神社への売り込み
など、考えられないこともないですけど・・・・・・・・・・・・・。

#ソースリスト
https://github.com/uminor/jcoins/blob/master/jcoins_counter.ipynb

#「打ち出の小槌」サービス（デモ）
(2019/01/27 追加)
本件で用いたデータ生成機能をサービス化してみたものです。 
https://qiita.com/uminor/items/d9a3123ce782451bea74