-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathfid.py
92 lines (81 loc) · 4.23 KB
/
fid.py
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# -*- coding: utf-8 -*-
'''
From https://github.com/tsc2017/Frechet-Inception-Distance
Code derived from https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/gan/python/eval/python/classifier_metrics_impl.py
Usage:
Call get_fid(images1, images2)
Args:
images1, images2: Numpy arrays with values ranging from 0 to 255 and shape in the form [N, 3, HEIGHT, WIDTH] where N, HEIGHT and WIDTH can be arbitrary.
dtype of the images is recommended to be np.uint8 to save CPU memory.
Returns:
Frechet Inception Distance between the two image distributions.
'''
from data_loader import DataLoader
import tensorflow as tf
import os, sys
import functools
import numpy as np
import time
from tensorflow.python.ops import array_ops
from tensorflow.python.ops import functional_ops
tfgan = tf.contrib.gan
session = tf.InteractiveSession()
# A smaller BATCH_SIZE reduces GPU memory usage, but at the cost of a slight slowdown
BATCH_SIZE = 64
# Run images through Inception.
inception_images = tf.placeholder(tf.float32, [BATCH_SIZE, 3, None, None])
activations1 = tf.placeholder(tf.float32, [None, None], name = 'activations1')
activations2 = tf.placeholder(tf.float32, [None, None], name = 'activations2')
fcd = tfgan.eval.frechet_classifier_distance_from_activations(activations1, activations2)
def inception_activations(images = inception_images, num_splits = 1):
images = tf.transpose(images, [0, 2, 3, 1])
size = 299
images = tf.image.resize_bilinear(images, [size, size])
generated_images_list = array_ops.split(images, num_or_size_splits = num_splits)
activations = functional_ops.map_fn(
fn = functools.partial(tfgan.eval.run_inception, output_tensor = 'pool_3:0'),
elems = array_ops.stack(generated_images_list),
parallel_iterations = 1,
back_prop = False,
swap_memory = True,
name = 'RunClassifier')
activations = array_ops.concat(array_ops.unstack(activations), 0)
return activations
activations =inception_activations()
def get_inception_activations(inps):
n_batches = inps.shape[0]//BATCH_SIZE
act = np.zeros([n_batches * BATCH_SIZE, 2048], dtype = np.float32)
for i in range(n_batches):
inp = inps[i * BATCH_SIZE:(i + 1) * BATCH_SIZE] / 255. * 2 - 1
act[i * BATCH_SIZE:(i + 1) * BATCH_SIZE] = activations.eval(feed_dict = {inception_images: inp})
return act
def activations2distance(act1, act2):
return fcd.eval(feed_dict = {activations1: act1, activations2: act2})
def get_fid(images1, images2):
assert(type(images1) == np.ndarray)
assert(len(images1.shape) == 4)
assert(images1.shape[1] == 3)
assert(np.min(images1[0]) >= 0 and np.max(images1[0]) > 10), 'Image values should be in the range [0, 255]'
assert(type(images2) == np.ndarray)
assert(len(images2.shape) == 4)
assert(images2.shape[1] == 3)
assert(np.min(images2[0]) >= 0 and np.max(images2[0]) > 10), 'Image values should be in the range [0, 255]'
assert(images1.shape == images2.shape), 'The two numpy arrays must have the same shape'
print('Calculating FID with %i images from each distribution' % (images1.shape[0]))
start_time = time.time()
act1 = get_inception_activations(images1)
act2 = get_inception_activations(images2)
fid = activations2distance(act1, act2)
print('FID calculation time: %f s' % (time.time() - start_time))
return fid
if __name__ == '__main__':
dl = DataLoader(dataset_name='fer2013',img_res=(48,48,1),normalize=False)
_ , batch_images_0 = dl.load_data(domain=0, batch_size=100, is_testing=True,convertRGB=True)
_ , _batch_images_0 = dl.load_data(domain=0, batch_size=100, is_testing=True,convertRGB=True)
_ , batch_images_1 = dl.load_data(domain=1, batch_size=100, is_testing=True,convertRGB=True)
batch_images_0 = np.transpose(batch_images_0, (0,3,1,2) )
batch_images_1 = np.transpose(batch_images_1, (0,3,1,2) )
_batch_images_0 = np.transpose(_batch_images_0, (0,3,1,2) )
print(">> fid [sample size=100, label=0]:",get_fid(batch_images_0, _batch_images_0)) #93.23781
print(">> fid [sample size=100, label=0 - ideal]:",get_fid(batch_images_0, batch_images_0)) #-7.3896445e-13
print(">> fid [sample size=100, label=0/1]:",get_fid(batch_images_0, batch_images_1)) #118.91554