Coursera Deep Learning Course4: Art Generation with Neural Style Transfer


deeplearning.aiが提供している[Coursera Deep Learning](https://www.coursera.org/specializations/deep-learning) コースのCourse 4のWeek 4ではFace RecognitionとNeutral Style Transferについて説明されています。
受講の復習も兼ねて、今回はNeutral Style Transferについて内容を簡潔にまとめたいと思います。

## Neural Style Transferとは？

Neural Style TransferはDeep Learningの中でもアート分野等で利用される技術で、元となる[論文](https://www.cv-foundation.org/openaccess/content_cvpr_2016/papers/Gatys_Image_Style_Transfer_CVPR_2016_paper.pdf)はGatys et al.によって2015年に発表されています。
一言でいうと2つの画像を用意し、一方から内容（コンテンツ）、もう一方からはスタイルを抽出し、それらを組み合わせた画像を生成するというものです。

## どのような仕組み？

畳み込みニューラルネットワーク（CNN）を利用しており、学習済みモデルを転移学習（訓練済みのニューラルネットワークを使って別の問題を解くこと）で利用されています。（元論文やCourseraの演習では2014年のILSVRCで優勝したVGGを利用しています。）
![image](https://qiita-image-store.s3.amazonaws.com/0/29039/2eef155e-af48-3a86-e775-cdebc29f2f49.png)
[Image Style Transfer Using Convolutional Neural Networksより](https://www.cv-foundation.org/openaccess/content_cvpr_2016/papers/Gatys_Image_Style_Transfer_CVPR_2016_paper.pdf)


上記の図はCNNの各層においてどのような画像が生成されているかを表しています。図の上段がスタイル画像、下段がコンテンツの画像です。
下段の画像を見ると、a, b, cの画像までは入力画像とさほど変わらないように見えますが、d, eあたりになると画像が崩れてきているように見えます。
これは、CNN自体が元々画像を分類する目的で訓練されているため、深い層に行くにつれて分類するにあたって重要なコンテンツが残り、それとはあまり関係のないスタイルなどの情報が落ちていっているのではないかと考えられます。つまり、コンテンツとスタイルを分離することができているとも考えられます。
このようにDeep Learningでは浅い層ほど角や単純な色彩など、低いレベルの特徴を抽出し、深い層では複雑な色彩や物体のような複雑な特徴を抽出する傾向があります。
Neural Style Transferではこの性質を利用して、コンテンツを保ったままスタイルを別のものへ変えることを行っています。

## 実装の手順

それではNeural Style Transferのコスト関数を算出する手順を示していきます。
コンテンツ画像をContentsの(C)、スタイル画像をStyleの(S)、最終的に生成する画像をGeneratedの（G）とし、それぞれのコスト関数をJ(C), J(S), J(G)と表現していきます。
大まかな流れとしては
1. コンテンツ用のコスト関数を設定
2. スタイル用のコスト関数を設定
3. コンテンツ用とスタイル用のコスト関数を合わせる
という流れになります。順番に見ていきます。

1. コンテンツ用のコスト関数
コンテンツのコスト関数はある隠れ層（論文ではconv4_2）において以下のようにコンテンツとGeneratedイメージ（G）を比較することによって計算します。

    ```math

    J_{content}(C, G)=\frac{1}{4 \times n_{H} \times n_{W} \times n_{C}} \sum_{all entries} (a^{(C)} - a^{(G)})^{2}
    ```

2. スタイル用のコスト関数を設定
    スタイルのコスト関数を算出するにはまずはスタイル行列（Gram行列とも呼ばれる）を算出します。

    ```math

    G_{ij} = v^{T}_{i} v_{j} 
    ```

    スタイル画像とGeneratedイメージのGram行列を以下の式で比較します。
    スタイルのコスト関数では以下のように複数の層を考慮することになります。
    この点がコンテンツの場合と異なります。コンテンツの時は隠れ層の1層のみ考慮していたのに対して、スタイルでは複数の層を考慮するほうが良い結果が出やすいそうです。

    ```math

    J_{style}(S, G)=\frac{1}{4 \times n_{C}^2 \times (n_{W} \times n_{C})^2} \sum_{i=1}^{n_{C}} \sum_{j=1}^{n_{C}} (G_{ij}^{(S)} - G_{ij}^{(G)})^{2}
    ```

3. コンテンツ用とスタイル用のコスト関数を合わせる
    最終的なコスト関数です。
    αとβはハイパーパラメータになります。

    ```math

    J(G)=αJ_{content}(C, G)+βJ_{style}(S, G)
    ```

以下の図が１〜３のプロセスを図示したものになります。

![スクリーンショット 2018-02-08 22.22.59.png](https://qiita-image-store.s3.amazonaws.com/0/29039/944adb4f-f8b2-57c4-d43f-99bfd57b72cb.png)
[Image Style Transfer Using Convolutional Neural Networksより](https://www.cv-foundation.org/openaccess/content_cvpr_2016/papers/Gatys_Image_Style_Transfer_CVPR_2016_paper.pdf)

上記のように構築したコスト関数を最適化関数を用いて最小化していきます。
（Courseraの演習では最適化関数としてAdamを使用しています。）
最小化していくことで、生成画像はスタイル画像に近づいていくことになります。

## まとめ
- Neural Style Transferはコンテンツ画像とスタイル画像を合わせて新たな画像を生成できる。
- トレーニング済みのCNNを利用し、隠れ層での出力結果を利用。
- コンテンツのコスト関数では1つの隠れ層の値を利用。
- スタイルのコスト関数はまずそれぞれの隠れ層からGram行列を算出し、各隠れ層から算出したその値を利用して算出。
- コンテンツとスタイルを合わせたコスト関数を最適化することで、新しい画像を生成する。

以上、Neural Style Transferについて書きました。