画像の高速スタイル変換を行う論文の紹介

# 画像の高速スタイル変換

画像のスタイルを変換するアルゴリズムとしてGatysらの["A Neural Algorithm of Artistic Style"](http://arxiv.org/abs/1508.06576)が知られていますが、これを高速に行う手法が現れました。
以下のつぶやきを見て驚愕したので早速調べました。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="en" dir="ltr">testing real-time style transfer published in the last week with <a href="https://twitter.com/hashtag/chainer?src=hash">#chainer</a> and <a href="https://twitter.com/hashtag/openFrameworks?src=hash">#openFrameworks</a> <a href="https://t.co/KrQaN8TSs9">pic.twitter.com/KrQaN8TSs9</a></p>&mdash; Yusuke Tomoto (@_mayfa) <a href="https://twitter.com/_mayfa/status/718079116705005569">2016年4月7日</a></blockquote>

2016/4/12追記 Yusuke Tomoto氏による実装が公開されました。Chainerを使っています。
https://github.com/yusuketomoto/chainer-fast-neuralstyle

実装の元になった論文は以下にあります。
Justin Johnson, Alexandre Alahi, Li Fei-Fei, ["Perceptual Losses for Real-Time Style Transfer and Super-Resolution"](http://arxiv.org/abs/1603.08155)

本記事ではConvolutional Neural Network(CNN)の知識を前提とします。CNNについてよく知らないという方は以下の記事を読んでおくと良いと思います。
[Convolutional Neural Networkとは何なのか](http://qiita.com/icoxfog417/items/5fd55fad152231d706c2)
[Convolutional Neural Networkを実装する](http://qiita.com/icoxfog417/items/5aa1b3f87bb294f84bac)

# 画像のスタイル変換とは？

コンテンツ画像とスタイル画像の２つの画像を用意し、以下の特徴を持つ画像を出力します。
[Preferred Researchブログ](https://research.preferred.jp/2015/09/chainer-gogh/)に例が載っています。

* 描かれている物体はコンテンツ画像と同じ
* スタイルがスタイル画像に似ている

# 従来手法

Gatysらの手法については先ほど紹介した[Preferred Researchブログ](https://research.preferred.jp/2015/09/chainer-gogh/)に詳しく書かれています。
この手法では、入力画像（ランダムな値を初期値とすることが多い）を少しずつ修正してスタイル変換後の画像を生成します。

# 提案手法

これに対して提案手法では入力画像のスタイルを変換するニューラルネットワーク(NN)を学習します。

![style_transfer.png](https://qiita-image-store.s3.amazonaws.com/0/58026/6b6fc269-86c5-2cf4-bb8f-d0d011af94b3.png)

$f_{W}$ がスタイル変換を行うNNで、$x$ にコンテンツ画像を入力するとスタイル変換後の画像 $\hat{y}$ が得られます。
この手法では $x$ を $f_{W} $に入力するだけでスタイル変換を行えるので高速に変換を行うことができます。
ただし $f_{W}$ を学習するのに時間がかかり、また $f_{W}$ はスタイル毎に学習する必要があります。


# スタイル変換NNの構成

論文では、スタイル変換を行う $f_{W}$ の構成は以下のようになっています。

* Downsamplingレイヤ  
    ストライド2のCNN(論文では2層)を通してDownsamplingを行います
* 複数のResidual block  
    Downsampling後のデータをResidual networkに通して変換を行います  
    Residual networkは複数のCNN, ReLU, Batch normalizationと恒等変換を組み合わせることでレイヤが多数になっても学習を行いやすくしたものです。
    詳しくは[[Survey]Deep Residual Learning for Image Recognition](http://qiita.com/supersaiakujin/items/935bbc9610d0f87607e8)
    や[Training and investigating Residual Nets](http://torch.ch/blog/2016/02/04/resnets.html)を参照してください
* Upsamplingをするレイヤ  
    ストライド1/2のCNN(論文では2層)を通してUpsamplingを行います

Residual block以外のレイヤでは、CNNの後にBatch normalizationととReLUを適用します。
ただし最終レイヤはReLUの代わりにtanhを使った後に定数を掛けて、出力が[0, 255]の範囲になるようにします。

# スタイル変換NNの学習

学習時には、$f_{W}$ とは別に損失関数に使用するLoss Network $\phi$ を用意します。
Loss Networkには画像のカテゴリ分類で使用するNNが使われ、論文では[VGG-16](https://gist.github.com/jimmie33/27c1c0a7736ba66c2395)を使っていました。
学習手順は以下に記述しますが、記号が多いのでまとめておきます。

$f_{W}$: スタイル変換NN
$\phi$: Loss Network
$x$: 入力画像
$y_{c}$: コンテンツ画像
$y_{s}$: スタイル画像
$\hat{y}$: $x$を$f_{W}$で変換した画像
$\phi_{i}(x)$: $\phi$ に $x$ を入力した時のレイヤ $i$ の値($\phi_{i}(y)$, $\phi_{i}(\hat{y})$)についても同様)

## 事前準備

1. 事前に1つのスタイル画像と複数のコンテンツ画像を用意する  
    論文では[MS COCO](http://mscoco.org/)に含まれる8万枚の画像を使用していました。
1. スタイル画像を$\phi$に入力し、$\phi_{i}(y_{s})$を得る

## 学習

以下を繰り返し行います

1. コンテンツ画像を $f_{W}$ に入力し出力 $\hat{y}$ を得る
1. $\hat{y}$をLoss Network $\phi$ に入力し、$\phi$ の各レイヤの値 $\phi_{j}(\hat{y})$ を得る
1. コンテンツ画像を$\phi$に入力し、$\phi_{i}(y_{c})$ を得る
1. $\phi_{j}(\hat{y}), \phi_{i}(y_{c})$ と $\phi_{i}(y_{s})$ からFeature Loss $l_{feat}^{\phi}$ とStyleをLoss $l_{style}^{\phi}$ を求める
1. $l_{feat}^{\phi}$ と $l_{style}^{\phi}$ の重みつき和を減らすように $f_{W}$ を更新する

### レイヤ j のFeature Loss:

Feature Lossは $\phi_{j}(\hat{y})$ と $\phi_{j}(y_{c})$ のユークリッド距離の2乗です。
学習時には $\phi_{j}(y_{c})$ は $f_{W}$ の入力 $x$ に一致します。

```math
l_{feat}^{\phi,j}(\hat{y}, y_{c}) = \frac{1}{C_{j}H_{j}W_{j}}||\phi_{j}(\hat{y}) - \phi_{j}(y_{c})||_2^2
```

$C_{j}, H_{j}, W_{j}$ はそれぞれレイヤ $j$ のチャンネル数、高さ、幅です。

### レイヤ j の Style Loss:

まずレイヤ $j$ のグラム行列を定義します。
グラム行列の要素は、レイヤ $j$ のチャンネル $c$ の要素をベクトル化（1列に並べた）したものと別のチャンネル $c^\prime$ の要素をベクトル化したものとの内積を定数で割った値です。
論文ではFeature Lossの計算対象になっているレイヤは1つです。

```math
G_j^{\phi}(x)_{c,c^\prime}=\frac{1}{C_{j}H_{j}W_{j}}\sum_{h=1}^{H_j}\sum_{w=1}^{W_j}\phi_j(x)_{h,w,c}\phi_j(x)_{h,w,c^\prime}
```

次にStyle Lossを求めます。
Style Lossはグラム行列のフロベニウスノルムの2乗です。

```math
l_{style}^{\phi,j}(\hat{y},y_{s})=||G_{j}^{\phi}(\hat{y})-G_{j}^{\phi}(y_{s})||_{F}^2
```

論文ではStyle Lossを計算するために4つのレイヤを使っています。
[Preferred Researchブログ](https://research.preferred.jp/2015/09/chainer-gogh/)だとグラム行列をチャンネル間の相関として説明しているのですが、私は相関を近づけることによって画像のスタイルが近づく理由を理解できていません。

実際に学習する時には画像を滑らかにするために上記のLossの他に $\hat{y}$ の分散を減少させるような正則化項も使用しています。詳しくは論文を参照してください。
Loss Networkの選び方によってはスタイル変換とは別の画像変換も行うことができます。
論文では別の変換として画像の高解像度化も行っていました。

# まとめ

提案手法では、スタイル変換NNである $f_W$ を学習することで実行時に高速にスタイル変換を行うことができます。
この手法はスタイル変換に限定されず、学習データによっては別の変換も学習することができると考えられます。
今回紹介していませんが、論文では画像の高解像度化も行っていました。
実行時のパフォーマンスが重要になる局面で活用できそうな手法だと思います。

# 参考文献

* Leon A. Gatys, Alexander S. Ecker, Matthias Bethge, ["A Neural Algorithm of Artistic Style"](http://arxiv.org/abs/1508.06576)
* Justin Johnson, Alexandre Alahi, Li Fei-Fei, ["Perceptual Losses for Real-Time Style Transfer and Super-Resolution"](http://arxiv.org/abs/1603.08155)
* [Training and investigating Residual Nets](http://torch.ch/blog/2016/02/04/resnets.html)
* Preferred Research [画風を変換するアルゴリズム]
(https://research.preferred.jp/2015/09/chainer-gogh/)
* [Convolutional Neural Networkとは何なのか](http://qiita.com/icoxfog417/items/5fd55fad152231d706c2)
* [Convolutional Neural Networkを実装する](http://qiita.com/icoxfog417/items/5aa1b3f87bb294f84bac)
* [[Survey]Deep Residual Learning for Image Recognition](http://qiita.com/supersaiakujin/items/935bbc9610d0f87607e8)