はじめに
Inception score [1]を計算します。このスコアは、GAN (Generative Adversarial Network)が生成した画像の評価値として使われることがあります。 [1]の著者らによるTensorFlow版のコードが[2]にあります。Chainer版が[3]にあります。ここではKerasで試します。Inception score
Inception scoreは、Inceptionモデルで識別しやすい画像であるほど、かつ、識別されるラベルのバリエーションが豊富であるほどスコアが高くなるように設計されたスコアです。 スコアは次のように計算します。\(x_i\)を\(i\)番目の画像データ、\(y\)をラベル、\(i\)番目の画像データをInceptionモデルに入力して得られるラベル\(y\)の確率を\(p(y|x_i)\)とします。スコアを計算するために使用する全ての画像データを\(X\)とすると、周辺確率は、 \[ p(y) = \frac{1}{|X|} \sum_{x_i \in X} p(y|x_i) \] と計算できます。\(p(y|x_i)\)と\(p(y)\)とのKL divergence [4]は \[ D_{\rm KL}(p(y|x_i) || p(y)) = \sum_{y \in Y} p(y|x_i) \log \frac{p(y|x_i)}{p(y)} \] です。これを全ての\(x_i \in X\)について平均して、expをとると、Inception scoreになります。具体的には、 \[ \exp\left(\frac{1}{|X|}\sum_{x_i \in X} D_{\rm KL}(p(y|x_i) || p(y))\right) \] です。 KL divergenceは分布間の差異を測定する尺度です。したがって、\(p(y|x_i)\)が\(y\)に関して凸凹であるほど、そして、\(p(y)\)は平坦であるほど差異が大きくなり、その結果、Inception scoreが大きくなります。凸凹であるとか平坦であるとかは相対的なものなので、図にすると、コード
Inception scoreそのものは関数inception_scoreに示すように簡単に計算できます。学習済みのInceptionモデルは入力サイズが(299,299)で固定なので、入力する画像はリサイズする必要があります。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | # -*- coding: utf-8 -*-
import os, glob
import glob
import numpy as np
from keras.applications.inception_v3 import InceptionV3, preprocess_input
from keras.applications.imagenet_utils import decode_predictions
from keras.preprocessing import image
from keras.datasets import mnist
from PIL import Image as pil_image
model = InceptionV3() # Load a model and its weights
def resize_mnist(x):
x_list = []
for i in range(x.shape[0]):
img = image.array_to_img(x[i, :, :, :].reshape(28, 28, -1))
#img.save("mnist-{0:03d}.png".format(i))
img = img.resize(size=(299, 299), resample=pil_image.LANCZOS)
x_list.append(image.img_to_array(img))
return np.array(x_list)
def resize_do_nothing(x):
return x
def inception_score(x, resizer, batch_size=32):
r = None
n_batch = (x.shape[0]+batch_size-1) // batch_size
for j in range(n_batch):
x_batch = resizer(x[j*batch_size:(j+1)*batch_size, :, :, :])
r_batch = model.predict(preprocess_input(x_batch)) # r has the probabilities for all classes
r = r_batch if r is None else np.concatenate([r, r_batch], axis=0)
p_y = np.mean(r, axis=0) # p(y)
e = r*np.log(r/p_y) # p(y|x)log(P(y|x)/P(y))
e = np.sum(e, axis=1) # KL(x) = Σ_y p(y|x)log(P(y|x)/P(y))
e = np.mean(e, axis=0)
return np.exp(e) # Inception score
def mnist_inception_score(n_train):
(x_train, y_train), (x_val, y_val) = mnist.load_data()
x_train = np.expand_dims(x_train, axis=3) # shape=(60000, 28, 28) --> (60000, 28, 28, 1)
x_train = np.tile(x_train, (1, 1, 1, 3)) # shape=(60000, 28, 28, 1) --> (60000, 28, 28, 3)
return inception_score(x_train[0:n_train, :, :, :], resize_mnist)
def image_inception_score(globfile):
files = glob.glob(globfile)
xs = None
for f in files:
img = image.load_img(f, target_size=(299, 299))
x = image.img_to_array(img) # x.shape=(299, 299, 3)
x = np.expand_dims(x, axis=0) # Add an axis of batch-size. x.shape=(1, 299, 299, 3)
xs = x if xs is None else np.concatenate([xs, x], axis=0)
return inception_score(xs, resize_do_nothing)
print("Inception score (MNIST, 32):", mnist_inception_score(32))
print("Inception score (MNIST, 320):", mnist_inception_score(320))
print("Inception score (Imagenet, n02066245)", image_inception_score("imagenet/*.jpg"))
print("Inception score (Imagenet, 9 categories)", image_inception_score("imagenet2/*.jpg"))
|
結果
MNISTとImagenetの一部の画像でInception scoreを計算したところ、Image set | # of images | Inception score |
---|---|---|
MNIST train | 32 | 1.97646 |
MNIST train | 320 | 2.30575 |
Imagenet (n02066245) | 32 | 1.57115 |
Imagenet (9 classes) | 32 | 8.03765 |
まとめ
十分にテストをしたわけではありませんが、Inception scoreの傾向は分かりました。画像の評価に限定されますが、GANの評価に使えそうです。参考文献
[1] Tim Salimans, Ian Goodfellow, Wojciech Zaremba, Vicki Cheung, Alec Radford and Xi Chen, "Improved Techniques for Training GANs," NIPS2016, pp. 2234-2242, 2016, http://papers.nips.cc/paper/6124-improved-techniques-for-training-gans[2] https://github.com/openai/improved-gan
[3] https://github.com/hvy/chainer-inception-score
[4] https://en.wikipedia.org/wiki/Kullback%E2%80%93Leibler_divergence
0 件のコメント :
コメントを投稿