高校生なので、人工知能にインスタ映えさせてみた vol.1

#hello, world
Qiita初投稿です、宜しくお願いします。
2001年生まれの高校2年です、去年まで全日制高校に通っていましたが、
時間の無駄だと感じたので今年から通信制高校に転学しました。

プログラミングは小学生の頃に始めましたが、ずば抜けた技術はありません。
人並み程度、言語仕様を理解して関数ググりながら、なんとか動作するものが書けるくらいです。
というか、コードを書くより、アルゴリズムを考えたり、
プログラミングを使って造れる未来を妄想する方が好きです。

最近は、"ドローンをAIで操作したら何が出来る？"をひたすら考えてます。

ほぼ、Twitterで生きているのでフォローしてください:)
[@Noll_programmer](https://twitter.com/noll_programmer)

#What is?
Qiitaを始めるにあたって、
「技術力は他の投稿者より明らかに低いし、俺が技術的な事を書いてもつまらねえな（コメント恐いし）」
と思ったので、特にdeepな技術の記事と言うよりは、「最新技術を使って出来ること」を書いてみようと思いました。

技術的に詳しい事を知りたい時は、
同じジャンルに投稿している投稿者さんの記事を見るか、[こちら](https://google.com/)で。

#How do?
今、とても人工知能に興味があります。
そして、今考えているプロジェクトの実現には、人工知能の実装が必須です。
なので、僕の備忘録と兼ねて何章かにわけて、人工知能について記事を書いていきたいと思います。
最終的には、ドローンをAI制御する所までの成長記録を書いていけたらいいなあ、なんて思ってます。

記念すべき（?）、第一弾となるこの記事では、**「人工知能にインスタ映えさせてみた」**。


#着想に至るまで
僕、一応男子高校生なわけですよ。
キラキラしたDKやJKに囲まれながら生きていると、みんなインスタグラムやってるんですよね。

？？「ｳﾜｯ!!!これめっちゃインスタ映えじゃ～～ん」

？？「（インカメで動画を撮影しながら）（インスタグラムの）ストーリーだよ～～～＾ｑ＾（カメラを意識）」
「ｷｬｯ、突然ヤメテヨー（建前）（キメ顔）」

？？「（意味の分からない落書きされた壁を見て）これ背景にしてインスタ撮ろ～～（????????）」

そう、みんなインスタ映えインスタ映え。
なにか"それっぽい物"があると、すぐにインスタ行きです。

別に、それに対して何か異議があるとかではないんですよ。
ただ、「インスタ映えめんどくさくね？」って思う瞬間もあるわけです。

インスタ映えって結構労力を使うんですよ。
素材そのまま綺麗だったら良いんですけど、レンズを通してデータになると結構「あれ？」って思うものもあって。
そうすると、"加工"をするわけなんですね。

スマホなどのアプリを使って、色々数値を変えるんです。
「フィルターを使ったり」「文字やアイコンを入れてみたり」「彩度を変えたり」「明瞭度を変えたり」、「露出」、「コントラスト」、「ハイライト」。
ここまでしてようやく、"インスタ映え"となる。


**「めんどくさいっしょ？」**


そんなことを思っている時、こんな論文を見つけたわけです。
[Image-to-Image Translation with Conditional Adversarial Networks](https://arxiv.org/pdf/1611.07004v1.pdf)

これは、カリフォルニア大学バークレー校のBerkeley AI Research Laboratoryという研究室の論文で、
人工知能に学習をさせるアルゴリズムが開発されました。
どのようなアルゴリズムかというと、

まず人工知能に対して2枚で対になった画像を与えます。
そうすると人工知能は、その画像と画像の関係性を学習していきます。
結構頑張って学習した人工知能は、任意の画像から学習した関係性をもとに新しい画像を生成する事が出来ます。

学習には、
「二枚の関係性をもとに、新しい画像を生成するネットワーク」(generator)、
「生成された画像が本物なのか作り出された偽物なのかを判断するネットワーク」(discriminator)
の二つが用いられ、方や「本物に近づけようとする」、方や「本物かを判断する」、二つが切磋琢磨して、
最終的にはgeneratorの精度がdiscriminatorの精度によって向上し、良い感じの新しい画像が生成出来るわけです。

敵対的生成ネットワーク（Generative adversarial networks）をより使いやすくしたアルゴリズムに、
DCGANやcGANがありますが、このアルゴリズム（conditional adversarial networks）はcGANの構造を元にしています。

**「・・・これならイケる！！」**

#画像集め
まず、人工知能に与えてやる画像が沢山必要です。
しかし、今回は単純明快。画像でインスタ映えの特徴を捉える事が出来ればいいわけです。

そこで、「国内外のトップインスタグラマーの写真」を沢山集めることにしました。
・・・だって、インスタ映えの基準なんて明確な数値はないけど、
みんながインスタ映えだと思ってるからインスタグラマーなんでしょ？
実際、僕が「綺麗だな、インスタ映えだな」と思う写真をアップロードしているユーザーの事を、
高校生の友達が結構フォローしていた、なんて沢山あるわけです。

インスタグラマーの写真を収集して、「白黒写真」と「インスタグラマーの写真」を対にすることにしました。

inputに白黒写真、outputにインスタグラマーの写真をまとめます。
データとしては片方232,591枚を魔法の力（PHP）で集めました。
![スクリーンショット (61).png](https://qiita-image-store.s3.amazonaws.com/0/249338/a9d4c194-a948-1c63-7dee-52ec96ccba7a.png)
※Instagramに負担を掛けないよう、何日も掛けて集めました。

これを、学習用のデータとモデルテスト用に分けて終了です。
train(学習用):186,072枚
val(テスト用):46,519枚
![スクリーンショット (62).png](https://qiita-image-store.s3.amazonaws.com/0/249338/46bbb42f-fa73-9061-0ffc-969e8e6b6eb9.png)

最終的に人工知能に学習させるデータは、こんな感じです。（[Nollのインスタ](https://instagram.com/noll_photographer)より）
僕はインスタグラマーではないので、もちろん学習には使っていません。著作権的な配慮です。

![232591.png](https://qiita-image-store.s3.amazonaws.com/0/249338/63fd7ac0-b207-e6d6-190c-7976da19f612.png)
(モデル:[DAttSU](https://twitter.com/dattsu_))
![232596.png](https://qiita-image-store.s3.amazonaws.com/0/249338/80aa86aa-e221-c3e3-1906-55d90e0e0bdc.png)

![232628.png](https://qiita-image-store.s3.amazonaws.com/0/249338/5567ece9-9493-3c79-47e6-de3fd18fc3bf.png)

#学習
本家だと、torchで構築されていてluaは全く分からないので、
同じアルゴリズムをtensorflowで書いてくれた先人に感謝をし、今回はそれで学習を行います。

Windowsを使っていて、どうしてもGPUで動かしたかったので環境構築が結構大変でした。
![スクリーンショット (63).png](https://qiita-image-store.s3.amazonaws.com/0/249338/8690122c-b74c-aba5-42c7-63f8b75c907b.png)
![スクリーンショット (64).png](https://qiita-image-store.s3.amazonaws.com/0/249338/9fd6ae9b-e9d9-c35d-bfc7-4cca5508008a.png)
![スクリーンショット (65).png](https://qiita-image-store.s3.amazonaws.com/0/249338/701f0acc-8c73-1634-dfd2-04854e822b14.png)
※ただのツンデレです、Windows大好きです

この記事の反響が良ければ、詳しい導入方法とかも追記します。

エポック数は15、ミニバッチ数は4で、学習を開始しました。
（論文に記載されている値を元に、調整を重ねてこのパラメータにしました）
3日とちょっとで終わりました。

#モデルテスト
ようやくです。
学習したモデルを使って、任意の画像（学習に使っていない画像）でモデルのテストを行います。
実際には、先ほど用意したvalのデータを使っているんですが、
著作権の関係で、スクリーンショットは[Nollのインスタ](https://instagram.com/noll_photographer)から作ったデータです。

「入力画像:**生成画像**:出力画像」の順番です。

![スクリーンショット (70).png](https://qiita-image-store.s3.amazonaws.com/0/249338/7d538c7d-fcbe-02ba-1035-9bf6a5b11c17.png)
（・・・え？）

![スクリーンショット (71).png](https://qiita-image-store.s3.amazonaws.com/0/249338/0f9a5637-02ca-3a32-3a30-3c2b945781d8.png)
（・・・これはもしかして。）

![スクリーンショット (72).png](https://qiita-image-store.s3.amazonaws.com/0/249338/d1b245af-4f62-b44d-8225-7d3fa3de4412.png)
（失敗だ！！！！）

インスタ映えからは、程遠い画像になってしまいました.......

**～ここまでは、Nollの家の電気代の提供でお送りしました～**

**～ここからは、Nollの気合の提供でお送りします～**

#失敗の原因を考察
実は、学習を初めて間もない頃に、多分こうなるだろうなあというのは予想していました。
奇跡を信じて、3日間待ってみましたが、やはりダメダメな結果になってしまいました。

原因を、こう考えます。
1.そもそも、「人工知能でインスタ映え」は着色する為のものではない。→inputを白黒にする必要はない（学習範囲の増加）
2.「インスタ映え」の範囲が広すぎる。→インスタグラマーの写真をそのまま持ってきているので、クラス分けなどがされていない

ここで、諦めて記事を終わりにしたら、面白くありません。
戦いは、ここからです。

#プログラムを修正する
上記で仮定した失敗の原因をもとに、プログラムを修正したいと思います。

##入力画像の修正
現在の学習方法だと、白黒画像をカラー画像にする学習をさせてしまっています。
今回の目的は、
「インスタ映え=インスタグラマーが実施する画像加工の雰囲気の学習」
なので、元の画像をそれっぽく加工させた画像を生成させることです。

ということで、白黒画像ではなく、新しい入力画像の定義を以下とします。
インスタグラマーの元画像から、
「輝度をランダムで変更」「彩度をランダムで変更」
の処理を施します。
(スクリプトをPHPで書いたので結構大変だった)

##転移学習の実装
~~学習の効率を図るために、元のアルゴリズムに転移学習のネットワークをぶち込みたいと思った。~~
~~転移学習については、Google先生か先人達の記事を読んでもらった方が分かりやすいと思う。~~
~~簡単に言うと、膨大な学習済みのモデルを利用して、物体の認識を手助けしてもらう方法です。~~

~~学習済みモデルの必要な部分を、~~
~~今回のネットワークの前に打ち込んで精度を上げる方法を、**Fine-tuning**と呼ぶみたいです。~~

既存のアルゴリズムに組み込むのが難しすぎたので今回はやめました。
次はkerasでがんばります...(汗

#再度学習
白黒ではなくなったので、ヒントが増えたと思います。
なのでデータセットの数を減らして25epochにしました。
約24時間くらいです。

がんばれー！

#二度目の正直
さて、先ほど惨敗したインスタ映えはどのように精度があがったのでしょうか。
先ほどと同じく、[Nollのインスタ](https://instagram.com/noll_photographer)からです。

「入力画像:**生成画像**:出力画像」の順番です。

![スクリーンショット (74).png](https://qiita-image-store.s3.amazonaws.com/0/249338/e0100a40-0418-4c23-936e-e791705bc6d1.png)
![スクリーンショット (75).png](https://qiita-image-store.s3.amazonaws.com/0/249338/d6ee0cb1-fa0a-8d5f-6d70-8b9dce580d4c.png)
![スクリーンショット (76).png](https://qiita-image-store.s3.amazonaws.com/0/249338/ced775f0-bf9a-9452-4732-a633f2a80c65.png)

うーん、ちょっとノイズが残りますが、
「明るい方が綺麗だ」「明るすぎるので暗くしよう」
くらいはやってくれているようです。

ちょっとあんまりいじめないで、実際に撮ったそのままのデータをあげてみましょう。

![fa-inputs.png](https://qiita-image-store.s3.amazonaws.com/0/249338/e51c009f-426d-3d2b-0c5a-4617e02844e5.png)
いつだかに撮ったダイバーシティのガンダムです。
これをインスタにあげるとすると、少し明るくなって色味ももう少し濃かったらいいなーというところです。

![fa-outputs.png](https://qiita-image-store.s3.amazonaws.com/0/249338/22a7cc92-4dfe-059e-75b9-4b61870d1a0e.png)
ん～なんか分かりづらいですけど、右下のモニターを見ると若干明るさを上げてくれてるのが分かります。

![fgh-inputs.png](https://qiita-image-store.s3.amazonaws.com/0/249338/91167cf9-6d07-d40f-4fe2-0b317b0cc9f0.png)
一応人が入ったバージョンも。ガンダム撮ろうとしたら偶然カップルが入ってしまった失敗作品です。

![fgh-outputs.png](https://qiita-image-store.s3.amazonaws.com/0/249338/8a101b96-3eca-31a3-29c9-a7739820c26c.png)
より見えやすくなってしまった・・・。

個人的に一番好きな写真はこれです。
![232608-inputs.png](https://qiita-image-store.s3.amazonaws.com/0/249338/dbf5dc6b-588a-abcc-f7d2-8c333573d1d5.png)
![232608-outputs.png](https://qiita-image-store.s3.amazonaws.com/0/249338/6071241d-079c-5493-033b-5cffae833847.png)

#今後の展望
急ぎでこの記事を書き上げたかったので、学習をサボりすぎてしまった感があります。
もうちょっと色々なデータを学習させてあげれば、もう少し良い感じになりそうな雰囲気は感じました。

でも初めての人工知能だったので、結構楽しかったです。
これから、自分で1からネットワーク作って学習させてみたりもしてみたいと思っていますが、
まだまだ初心者なのでコンスタントに記事を出したりするのは難しいかなあと思ってます。

次は、こいつにfine-tuningを実装して、もっとインスタ映えを効率化してやるぞ！
もっとブラッシュアップして、エモい感じになったらWEBサービスとして出してみたいです。

**良いGPUが欲しい！！！**

ありがとうございました。
ちょっとでも「良いな」「わろたWW」とか思ったらSNSとかでシェアしてもらえると喜んでバンバン記事書きます。