事前準備

保存に関する設定

5.5 ニューラルスタイル変換

CycleGAN では、訓練セットの画像は対(pair)になっている必要はない。

ニューラルスタイル変換では、訓練セットを一切持たずに画像の画風を変換する。 以下の3つの異なる損失関数の和を最小化する。

5.5.1 コンテンツ損失

画像のテーマと、その内容の全体的な配置、との観点から、2つの画像がどれだけ異なっているかを計測する。 ピクセル単位の比較ではなく、もっと大きな単位での比較が必要となる。 既に訓練されたディープラーニングのモデルを用いることによって、与えられた入力画像の高レベルの特徴を抽出できる。 このモデルに、ベース画像を入力したときの出力(特徴量)と、現時点での合成画像を入力したときの出力(特徴量)の間の平均2乗誤差を計算すればよい。

本例では、既に訓練済みのネットワークとして VGG-19 を使う。

2つの画像の間のコンテンツ損失を計算するプログラムは Keras の公式リポジトリにある ニューラルスタイル変換の例 https://keras.io/examples/generative/neural_style_transfer/ を参照するとよい。 本にはリンクが http://bit.ly/2FlVU0P であると記述されていたが 2021/10/17 現在上記URLに移動したようだ)。

5.5.2 スタイル損失

スタイル損失を定量化することは難しい問題である。 ニューラルスタイルの原論文で示されているのは「 通常スタイルが似ている画像は、所定の層における特徴マップ間の相関パターンが同じである」 という考え方を取っている。

ニューラルネットワークのある層がある特徴について特定するように学習されているとする。 そのような特徴が3種類あったとする。 3つの入力に対して、3特徴それぞれの特徴マップが次の例のようであったとする。

>>
画像特徴1特徴2特徴3
画像1
1 0 0 0 0
2 1 0 0 0
2 2 1 0 0
2 2 2 1 0
1 0 0 0 0
2 1 0 0 0
2 1 1 1 0
2 2 2 1 0
2 2 0 1 2
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
画像2
0 0 0 0 0
2 2 2 2 1
0 2 2 2 1
0 0 0 0 0
0 0 0 0 1
1 2 2 2 1
0 2 2 2 1
0 0 0 0 0
0 0 0 2 0
0 0 0 2 0
1 0 0 2 0
2 2 2 2 2
画像3
2 2 2 2 2
2 1 1 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
1 2 2 2 2
2 2 2 2 2
2 2 2 2 2
0 0 0 0 0
1 1 1 2 2
2 2 2 2 2
2 2 2 2 2

特徴1のマップおよび特徴2のマップが似た分布をしていることから、 画像1と画像2は互いスタイルが似ているといえる。

2つの特徴マップを平坦化(Flatten())して内積を取れば、どれだけ同じように活性化しているかを計算できる。 ある層のすべての可能な特徴ペアの間の内積を格納した行列を Gram 行列と呼ぶ。 スタイルが似ている画像1と画像2が、似たGram行列を持っている。

したがって、スタイル損失を計算するために必要なことは、 ネットワーク中の一連の層で ベース画像と合成画像の両方に対するGram行列 (GM) を計算し、 2乗誤差の和を使ってその類似性を比べることである。

ある層 $l$ でのサイズ $M_1$ $(\mbox{高さ}\times\mbox{幅})$ , $N_1$ チャネルのベース画像 $S$ と生成された画像 $G$ の間のスタイル損失:
$\displaystyle L_{GM} (S, G, l) = \frac{1}{4 N_{l}^{2} M_{l}^{2}} \sum_{ij} (GM[l](S)_{ij} - GM[l](G)_{ij})^2$

全スタイル損失は、各層のチャネル数 $N_l$ とサイズ $M_l$ を考慮して以下の通り。
$\displaystyle L_{style}(S,G) = \sum_{l=0}^{L} L_{GM} (S, G, l)$

5.5.3 全変動損失

全変動損失は合成画像内のノイズを計測する。 画像を1ピクセルだけ右にずらして、元の画像との間の2乗誤差を計算する。 また、1ピクセルだけ下にずらして、元の画像との間の2乗誤差を計算する。 この和が全変動損失である。

Neural style transfer

以下、Keras 公式の Neural style transfer https://keras.io/examples/generative/neural_style_transfer/ にしたがって話を進める。

Introduction

Style Transfer は、元画像と同じコンテンツを持ちながら、異なる画像のスタイル(芸術的な意味での)を備えた画像を生成する。

[自分へのメモ] VGG16 や VGG19 の入力画像サイズのデフォルトは 224x244x3 である。 幅と高さはそれぞれ 32 以上である必要がある。

画像の前処理と後処理

vgg16やvgg19などでは、各モデルで preprocess_input() という前処理用関数が用意されている。 preprocess_input() を省略しても結果は得られるが、きちんと適用した方が精度が出ると考えられる。

preprocess_input(x, data_format=None, imode='caffe', **kwargs) は imagenet_utils.py で定義されている。 preprocess_input() では引数 modeで 'caffe', 'tf', 'torch' を指定し、フレームワークを選ぶ。

vgg16 や vgg19 は caffe で重みが訓練されているので、結果をcaffe フォーマットから逆変換する必要がある。

スタイル損失の計算

VGG19の途中までの層を抜き出す

loss と gradient の計算に tf.function デコレータを追加する

python の関数を <code>@tf.function</code> で decorate すると、次の利点がある。

この例では AutoGraph による自動微分の機能を使っている。

training