画像枚数50枚で機械学習させようと思ったときの手段メモ

# 概要
機械学習超初心者の僕が、画像を使ったWebアプリを思いついたので、
「ディープラーニング使えばなんとかなるやろ〜」
って思っていたら上手く行かず、社内の名だたる機械学習の先輩方に相談させていただいたときのメモ。

# 今回やりたいこと
**飲み会で「好きなタイプの芸能人はだれ？」と訊かれたときに答えることができるWebサイト**
# 必要なUX

1. ユーザーがWebサイトに来訪する
2. 50人位のモデルの画像が出てくるので、1枚1枚に対して「タイプ」「ちょっと好き」「普通」「少し苦手」「だいぶ苦手」のうち1つを選択して入力する
3. その結果から、ユーザーが好きになるであろう芸能人の顔写真と、「あなたはこの方が好きになるでしょう」的な文言が表示される
4. **飲み会で「俺、人工知能に堀北真希がタイプだって言われたんすよ」って回答できる**

めっちゃ欲しくないですか？
飲み会で定番のあの質問が社会人になってから結構面倒だったので、こんな感じでネタっぽく返答できるのとっても欲しい。

# 事前検証
とりあえずディープラーニングについては多少の知識があったので、今回の要件を実現するために考えたこととしては、

- 「モデルの画像」に対して、判定結果が「タイプや苦手といったユーザーの5段階評価」になるようにディープラーニングさせる

ことで、

- 「芸能人の画像」に対して、5段階の内どの評価になるかを予測できる

ような学習モデルを作り上げることでした。
ところが、例えば[JINS BRAIN](https://brain.jins.com/about/)のように、数万枚規模の学習データが有ればまた予測精度も高まるのでしょうが、今回は「50枚程度のモデルの画像」から学習させるので、いくらなんでも枚数が少なすぎまして、まったく予測が成り立ちませんでした。


# そして
社内日報に「50枚で学習精度上がらなくて苦しんでいる」とコメントしていたら、社内でAIに見識のあるエンジニアの先輩や同期からコメントをいただいたので、その内容と、自分の感想をペアにしてまとめていきたいと思います。
あくまでメモなので特に中身はありませんが、あわよくば同じような機械学習超初心者の方が見て、この世界の奥深さを実感していただけたらなと思っています。

# 画像水増し
まず、今回の件に対しての根本解決にはなりませんが、そもそも枚数が少ない場合に定番のテクニックとしては、似たような画像をプログラマブルに生成して水増しをする方法があります。
http://qiita.com/bohemian916/items/9630661cd5292240f8c7
こちらの記事を参考にコントラストを変更するなどして学習させることができます。
とはいえ水増しに頼りすぎると過学習を容易に引き起こすので過信すべきではありません。

# 特徴量の追加
こんなコメントもいただきました。
>単純なDNNの実装で判別するなら５０枚では無理です。しかし、学習データとして画像だけでなく簡単に入れられる特徴量を追加することで少ないデータ量でも精度を上げることができます。
例えば、建物外観の写真からそれがマンションなのかアパートなのか戸建てなのかを判別したいが、画像データが５０枚しか集められないというときに、画像データと建物の階数や金額などの別で取れる特徴量を加えれば、精度が上がります。

なるほど、今回の例だと特徴量は黒髪とか目が大きいとかそういうところでしょうか。
>画像で特徴点抽出して処理（SVMなどの分類器にかける）する方法があると思います

ふむふむ、画像分類といってもDNN以外にも方法があるってことですね。
もちろんSVMは訊いたことはあったけど、個人的には人工知能の発展の中にあるものでもう過去の遺産になっているものかとばかり思っていました。

# 機械学習以外の画像分類技術を使う
>例えば「あるロゴが含まれているなら一意になる」みたいなやつだったらsift,surf特徴量とか使うのもありだと思います。
個人的に「画像認識＝機械学習」は思考停止な気がする

そうだなぁ。人間の顔ってどういうところに特徴があるのかとか言葉で説明できるのであれば機械学習させる必要はないっていう見方もありますね。
sirf、surf特徴量は初耳でした。
参考：https://www.slideshare.net/lawmn/siftsurf

# 協調フィルタリング
今回やろうとしていることは過去の入力に基づいて未来に好きになるであろう人を出力するわけなので、感覚的にはレコメンデーションに近いという意見も頂きました。
▼参考
http://qiita.com/ynakayama/items/59beb40b7c3829cc0bf2

しかし、協調フィルタリングに関して言うと、他の人の入力情報も参考に予測をするわけなので、今回のサービス要件には合っていないと判断しました。
例えば音楽アプリで、ある程度リリース後時間が経ってから、一般的にこの曲を好きなユーザーはこの曲も好きになるはずだ、と知見が溜まってきて使うようなイメージです。

# 主成分分析
この辺になってくるとあまり頭がついてこなくなりました。が、一応メモしておきます。
http://blog.amedama.jp/entry/2017/04/02/130530
頭がついていっていないけど、多次元のデータを次元を減らして出来る限り意味合いの損失を減らすことができるような仕組みなのでしょうか。
これができるなら画像の特徴を2次元とかで表すことができる・・・？

# Factorization Machines
http://qiita.com/wwacky/items/b402a1f3770bee2dd13c
？？？？
もはやどんな用途で使われるかどうかもピンとこない。。。
改めてもう一度訊きます。一度じゃ理解できない。。。

# クラスタ分析 （K-means 法）
http://pythondatascience.plavox.info/scikit-learn/%E3%82%AF%E3%83%A9%E3%82%B9%E3%82%BF%E5%88%86%E6%9E%90-k-means
今回のサービス仕様を考えたときにわりとしっくり来たのがこれです。
教師なし学習に分類されるみたいで、
モデルの画像を分類しておいて、芸能人の画像がどれに近いかも予め本手法で求めることができるそうです。
つまり、ユーザーが入力した画像で、各クラスのうちどれが一番好みに近いかを考えて、それを出力することができます。
学習済みのモデルを作るというよりかは、本当にシンプルに分類って感じがします。

当初思っていたイメージとは異なりますが、画像を分類できる技術がディープラーニング以外でも実現できるのであれば、ディープラーニングを使う必要性はなさそうです。

問題はこれをどうやってクラス分けするかってことですが、、、
単純に画像のピクセル値を値にするか、肌の色とか髪の色とか目の大きさとかを評価して数値化してそれを分類させるって感じなのかな？

# 強化学習
http://qiita.com/PonDad/items/2410c55b2d21e7cad7bc
強化学習も割とありえるやり方である気がしてきていて、
画像を読み込ませて、「タイプ」だったら報酬を与えるし「苦手」だったら罰を与える的なやりかたをする。
でもなんか趣旨が違う気がするので、クラスタ分析よりこちらを採用する理由はないかな、と結論づけました。

# ナイーブベイズ分類器
http://qiita.com/ynakayama/items/ca3f5e9d762bbd50ad1f
このモデルを好きになった人はこのモデルも好きになる確率が高いといったことを学習させていくイメージのようです。
でも、これだとサービスを成長させるときには使えるけど、初期リリースには導入ができないのではという気がします。
協調フィルタリングと近い感覚でした。

# 画像分類
クラスタリングの発想の延長で、画像の類似度さえ求めておいて、事前にサンプル用のモデルさんの画像と有名人の顔の類似度を相互に求めておいて、ユーザーの入力に対して一番類似度の合計が高くなるような有名人を選べばいい、という発想が出てきました。
下記の記事をひと通り見た感じ、できそうな気がしています。

- ディープラーニングを使わない顔認識3 CNN編 - ニートがプログラミングするブログ（はてな出張所） http://suzuichiblogpg.hatenadiary.jp/entry/2016/10/31/220809

- AIを使って顔画像から「常連さん」を判定しよう！ | Future Tech Blog - フューチャーアーキテクト https://future-architect.github.io/articles/20170526/ #future_architect @future_techblogさんから

- Python + OpenCVで画像の類似度を求める by @best_not_best on @Qiita http://qiita.com/best_not_best/items/c9497ffb5240622ede01

特にPython＋OpenCVで柴犬を分類する記事が、ヒトの顔写真から好みの芸能人を探し出すユースケースに近いように思います。

- レコメンドに浸透していくDeep Learning： 大手サービスの実用例から最新アルゴリズムを概観する | DeepAge https://deepage.net/deep_learning/2016/09/26/recommend_deeplearning.html

ざっと調べた感じ、このあたりの記事が参考になりそうです。

# 結論
ディープラーニングしかないと思っていたけど、いろいろな手段を聞くと画像の類似度を求めるアルゴリズムを使うのが最も現実的なようです。

# 所感
自分の中に手段の引き出しがなさすぎて、こんなに沢山の方法があるものだとびっくりしました。
いくつかは名前や概要は知っていたものの、AIができていく過程で化石になった技術だと勝手に決めつけていたのだが、それも適材適所であることを肝に銘じておこうと思いました。