画像生成モデルでの品質評価指標（StyleGAN2)

画像生成モデルでの品質評価（Metric)について、StyleGAN２のオリジナルコードで実装されているモデルをベースに整理してみました。

記載内容等に間違えがあれば随時ブラッシュアップしますのでご指摘をお願いします。

# <font color=royalblue>はじめに</font>
StyleGAN2での品質評価（Metrics)は、モデルの学習には関与せず、論文上で提示された各アイデアの有効性を定量的に検証するために使われています。  
以下のMetricsが用意されており、論文の論調としては「PPL」が他の評価より優れているとしています。

+ is50K: Inception Score
+ fid50K: Fréchet Inception Distance
+ ppl: Perceptual Path Length
<font color=gray>オプションにより ppl_zfull, ppl_wfull, ppl_zend, ppl_wend, ppl2_wend に細分化</font>
+ Is: Linear Separability
+ pr50k3: Precision & Recall

上記のうちStyleGAN2の学習コードではデフォルトで fid50K のみが使用されます。

GitHubにあるオリジナルのコードは以下になります。
<https://github.com/NVlabs/stylegan2/tree/bf0fe0baba9fc7039eae0cac575c1778be1ce3e3/metrics>

以下に順番に説明します。

# <font color=royalblue>is50k:&nbsp;&nbsp;Inception Score</font>
+ 目標
    + 生成された画像１枚１枚が意味のある内容であって欲しい  
    + 様々な入力単数から生成された画像群は、様々な内容を含んで欲しい
+ 画像分類に用いられるInceptionモデルを用いて、Generatorの出力画像xを評価
　　　　（この時5万枚の出力画像で評価するので名称に50kとついている）
+ 画像の分布に対する以下の式を指標として用いる

``` math
\begin{align}
&exp(\mathbb{E}_x \hspace{1mm}KL\hspace{1mm}(p(y \mid x) \parallel p(y)\hspace{1mm})) \\
\\
&ここで、 \\
&KL: KLダイバージェンス、確率分布間が離れているほど大きい \\
&p(y \mid x): 生成された画像1枚に対する識別結果の確率分布 \rightarrow １つのラベルに対応する確率が高いのが良い \\
&p(y): 様々な画像を識別機に入れた結果の平均 \rightarrow 様々なラベルに対する出力が均等になるのが良い
\end{align}
````

+ StyleGAN２での実装概要 ([metrics/inception_score.py](https://github.com/NVlabs/stylegan2/blob/bf0fe0baba9fc7039eae0cac575c1778be1ce3e3/metrics/inception_score.py))
    + Generator(Gs)にランダムな潜在変数を与えて画像を50K枚生成
    + inception V3 modelで評価、画像ごとに1000クラスの確率 -> activations
    + 全画像（ただし分割している）のactivationsの平均と、各画像のactivationsのKLダイバージェンスを計算する

[参考]
[Improved Techniques for Training GANs](https://arxiv.org/abs/1606.03498)

# <font color=royalblue>fid50k:&nbsp;&nbsp;Fréchet Inception Distance</font>
+ Inception Scoreの改良版
+ Inception Scoreでは、リアル画像に対するInceptionモデルの挙動が使われていなかった
+ 目標
    + リアル画像セットと生成(Fake)画像セットの分布が集合として類似してほしい
+ 画像特徴量抽出にInceptionモデルを使用（分類結果ではなく最終のAverage Pooling後の2048次元）
+ リアル画像から抽出された特徴量の分布をガウス分布で近似 m_w、C_w(平均、分散）
+ Generatorでランダムに生成した画像から抽出された特徴量も同様 m、C
+ ガウス分布の類似度を測るFréchet distanceに代入

``` math
d^2 ((m, C), (m_w, C_w)) = \parallel m - m_w \parallel_2^2 + T_r(C + C_w -2(CC_w)^{\frac{1}{2}} )
```

+ SytleGAN2での実装([metrics/frechet_inception_distance.py](https://github.com/NVlabs/stylegan2/blob/bf0fe0baba9fc7039eae0cac575c1778be1ce3e3/metrics/frechet_inception_distance.py))
    + 学習済みinception V3 model(特徴抽出器）をロード
    + データセットのリアル画像をinception modelに与えて、特徴量を取得
    + データセット全体に対して計算した結果から、平均(np.mean)・共分散行列(np.cov(対角ではなくフルランク））を計算 $\Rightarrow$ mu_real、sigma_real
    + Generator(Gs)を用いて同様にランダムな潜在ベクトル・ラベルから画像を生成、平均・共分散行列を計算 $\Rightarrow$ mu_fake, sigma_fake
    + 上記数式に従ってFIDを計算

[参考]
[GANs Trained by a Two Time-Scale Update Rule Converge to a Local Nash Equilibrium](https://arxiv.org/abs/1706.08500)
[The Fréchet distance between multivariate normal distributions](https://www.sciencedirect.com/science/article/pii/0047259X8290077X)
[フレシェ開始距離（FID）を使用してGANの品質を評価する方法は？](https://wandb.ai/wandb_fc/japanese/reports/-FID-GAN---Vmlldzo0MzY2ODY)


# <font color=royalblue>PPL:&nbsp;&nbsp;Perceptual Path length</font>

+ 目標
    + 潜在空間 $\to$ 画像の対応関係の滑らかさを測定する  
+ StyleGAN2では、「潜在空間 $\to$ 画像の対応関係の滑らかさとして提案されたPPLが画像の品質自体を評価するのに有効だった  
+ 潜在変数 z から生成した画像と、 z + ε から生成した画像の距離を測定  
    + 距離：２枚の画像から計算したVGG16の特徴量間の距離であり、人間が画像を見た時の違いに近づくような重みづけが事前に学習されたモデルを用いる
+ 様々な z で計算した結果の平均を評価値として出力（小さい方が良い）
+ z の代わりに w(mapping networkで出力された潜在変数）空間で微小変化させるパターンもある
+ SytleGAN2での実装([metrics/perceptual_path_length.py](https://github.com/NVlabs/stylegan2/blob/bf0fe0baba9fc7039eae0cac575c1778be1ce3e3/metrics/perceptual_path_length.py))
    + 微小変化させる区間を計算
       - 正規乱数lat_t01 で線分の始点と終点を定める
       - 0 〜 1 の乱数 lerp_t でその中の内分位置を定める
       - 線分を lerp_t および lerp_t + epsilon　で内分してGeneratorの入力にする
    + 画像を生成(Gs_clone.components.syntheis.get_output_for)
    + 中央クロップ・縮小などの前処理
    + 画像間の距離計算モデル「vgg16_zhang_perceptuak.pkl」を用いて２枚の画像間の距離を計算 $\to$ distance_expr
    + 5万枚で計算した距離を all_distance に代入
    + 外れ値を除去： 1% 〜 99%の範囲だけを抽出
    + all_distancesを平均を PPL と出力
 
[参考]
[The Unreasonable Effectiveness of Deep Features as a Perceptual Metric](https://arxiv.org/abs/1801.03924)

# <font color=royalblue>Is:&nbsp;&nbsp;Linear Separability</font>
+ 目標
潜在変数 z の空間内で、顔に関する既知の属性が線形分類可能かを測定
    + 属性：性別、年齢、表情等４０種類
+ 潜在変数 z　から生成された画像の属性によって、z 空間に識別面が弾ける = OK
+ アルゴリズム
    + CelebAデータセットで学習された、属性分類機40種類を用意
    + 以下、各分類機について計算
    + ライダムな潜在変数 z で画像Xを多数生成
    + 画像Xを属性分類機で分類 $\to$ 属性の有無 Y
    + 線形SVMで、z から Y を推定する識別機を学習
    + 識別機を用いて z を分類 $\to$ 線形分類結果 P (train/testの分離はない）
    + Y と P の相互情報量を計算(理想的な条件では Y と P は一致するのでゼロ）
    + 全属性についての計算結果の総和を出力
+ StyleGAN２での実装概要 ([metrics/linear_separability.py](https://github.com/NVlabs/stylegan2/blob/bf0fe0baba9fc7039eae0cac575c1778be1ce3e3/metrics/linear_separability.py))
    + attrib_indicesにどの属性分類機を使うか指定するが、デフォルトでは40種類全部使う設定
    + 潜在変数 z を多数生成 $\to$ latents
    + 潜在変数 z をGenerator(Gs)に入力し画像を生成 $\to$ images
    + 属性分類機に与えるための前処理（リサイズ）を行う
    + 画像を属性分類機に与えて、正例・負例である確率を計算 $\to$ predictions
    + 識別結果がはっきりしているサンプルのみを残す（曖昧な確率を出した半分のサンプリを削除）
    + 正例・負例のラベル svm_targets に基づいて z から線形SVM(LinearSVC)を学習 $\to$ svm
    + SVMで　z を識別 $\to$ svm_outputs
    + svm_targets, svm_outputs の値（それぞれ 0/1)に基づき、各サンプルを $2\times2$ のconfusion matrixに分類する $\to p$
    + p のconditional entropyを計算 $\to$ conditional_entropies
    + conditional_entropiesの全属性合計を出力、最後にexpontentialを適用
    + z から生成した w についても同様に計算し、別の指標として出力する
 
# <font color=royalblue>pr50k3:&nbsp;&nbsp;Precision & Recall</font> 
+ FIDなどの手法は1つの数値だけを結果として出力する
+ 目的
    + precision: 生成画像がリアル画像らしいかどうか
    + recall: 生成画像が様々な種類のリアル画像を網羅しているか
+ 指標の提案は下記[A]が先で、改良された[B]がStyleGAN2では使用されている


+ アルゴリズム
    + precison: 生成画像の画像特徴量が、リアル画像の画像特徴量が張る多様体の中に含まれる確率
    + recall: 生成画像 $\leftrightarrow$ リアル画像を逆にしたもの
    + リアル画像の多様体の定義方法
        + 画像特徴量: VGG16の最終層(2048次元)
        + 各画像は「支配領域」を持つ
        + 支配領域は、自分自身に３番目に近い画像までの距離（L2距離）を半径とした球
        + 全画像の支配領域の和集合 = 多様体
+ StyleGAN２での実装概要 ([metrics/precison_recall.py](https://github.com/NVlabs/stylegan2/blob/bf0fe0baba9fc7039eae0cac575c1778be1ce3e3/metrics/precision_recall.py))
    + VGG16モデルをロード（特徴抽出器）
    + リアル画像多数をVGG16モデルに通した結果を取得 $\to$ ref_features
    + Generator(Gs)を用いてランダムな画像を生成し、リアル画像と同様にVGG16モデルに通す $\to$ eval_featrues
    + ManifoldEstimatorで、特徴量間の距離を計測
        + ref_featuresを用いて、リアル画像それぞれの支配領域（半径）を計算
        + eval_featuresの各サンプルについて、リアル画像の支配領域のいずれかに含まれるかを検査
        + precision=含まれたサンプル数 / 全サンプル数
        + recallはリアルと生成画像を入れ替えて計算
 
[参考]
[Assessing Generative Models via Precision and Recall](https://arxiv.org/abs/1806.00035)
[Improved Precision and Recall Metric for Assessing Generative Models](https://arxiv.org/abs/1904.06991)

# <font color=royalblue>おわりに</font>
本稿では、GANで生成された画像の品質評価についてStyleGAN2での実装をベースに説明しました。
StyleGAN2の実装についても別途整理して掲載する予定です。