| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| """ Tensorflow inception score code |
| Derived from https://github.com/openai/improved-gan |
| Code derived from tensorflow/tensorflow/models/image/imagenet/classify_image.py |
| THIS CODE REQUIRES TENSORFLOW 1.3 or EARLIER to run in PARALLEL BATCH MODE |
| |
| To use this code, run sample.py on your model with --sample_npz, and then |
| pass the experiment name in the --experiment_name. |
| This code also saves pool3 stats to an npz file for FID calculation |
| """ |
| from __future__ import absolute_import |
| from __future__ import division |
| from __future__ import print_function |
|
|
| import os.path |
| import sys |
| import tarfile |
| import math |
| from tqdm import tqdm, trange |
| from argparse import ArgumentParser |
|
|
| import numpy as np |
| from six.moves import urllib |
| import tensorflow as tf |
| import pickle |
| import h5py as h5 |
| import json |
|
|
| MODEL_DIR = "../inception_net" |
| DATA_URL = ( |
| "http://download.tensorflow.org/models/image/imagenet/inception-2015-12-05.tgz" |
| ) |
| softmax = None |
|
|
|
|
| def prepare_parser(): |
| usage = "Parser for TF1.3- Inception Score scripts." |
| parser = ArgumentParser(description=usage) |
| parser.add_argument( |
| "--experiment_name", |
| type=str, |
| default="", |
| help="Which experiment" "s samples.npz file to pull and evaluate", |
| ) |
| parser.add_argument( |
| "--experiment_root", |
| type=str, |
| default="samples", |
| help="Default location where samples are stored (default: %(default)s)", |
| ) |
| parser.add_argument( |
| "--batch_size", |
| type=int, |
| default=500, |
| help="Default overall batchsize (default: %(default)s)", |
| ) |
| parser.add_argument( |
| "--kmeans_subsampled", |
| type=int, |
| default=-1, |
| help="Reduced number of instances to test with (using this number of centroids).", |
| ) |
| parser.add_argument( |
| "--seed", type=int, default=0, help="Seed (default: %(default)s)" |
| ) |
|
|
| |
| parser.add_argument( |
| "--use_ground_truth_data", |
| action="store_true", |
| default=False, |
| help="Use ground truth data to store its reference inception moments", |
| ) |
| parser.add_argument( |
| "--data_root", |
| type=str, |
| default="data", |
| help="Default location where data is stored (default: %(default)s)", |
| ) |
| parser.add_argument( |
| "--which_dataset", |
| type=str, |
| default="imagenet", |
| choices=["imagenet", "imagenet_lt", "coco"], |
| help="Dataset choice.", |
| ) |
| parser.add_argument( |
| "--resolution", |
| type=int, |
| default=64, |
| help="Resolution to train with " "(default: %(default)s)", |
| ) |
| parser.add_argument( |
| "--split", type=str, default="train", help="Data split (default: %(default)s)" |
| ) |
| parser.add_argument( |
| "--strat_name", |
| type=str, |
| default="", |
| choices=["", "few", "low", "many"], |
| help="Stratified split for FID in ImageNet-LT validation (default: %(default)s)", |
| ) |
| return parser |
|
|
|
|
| def run(config): |
| assert ( |
| config["strat_name"] != "" |
| and config["which_dataset"] == "imagenet_lt" |
| and config["split"] == "val" |
| ) or config["strat_name"] == "" |
| |
| |
| |
| def get_inception_score(images, splits=10, normalize=True): |
| assert type(images) == list |
| assert type(images[0]) == np.ndarray |
| assert len(images[0].shape) == 3 |
| |
| |
| inps = [] |
| for img in images: |
| if normalize: |
| img = np.uint8(255 * (img + 1) / 2.0) |
| img = img.astype(np.float32) |
| inps.append(np.expand_dims(img, 0)) |
| bs = config["batch_size"] |
| with tf.Session() as sess: |
| preds, pools = [], [] |
| n_batches = int(math.ceil(float(len(inps)) / float(bs))) |
| for i in trange(n_batches): |
| inp = inps[(i * bs) : min((i + 1) * bs, len(inps))] |
| inp = np.concatenate(inp, 0) |
| pred, pool = sess.run([softmax, pool3], {"ExpandDims:0": inp}) |
| preds.append(pred) |
| pools.append(pool) |
| preds = np.concatenate(preds, 0) |
| scores = [] |
| for i in range(splits): |
| part = preds[ |
| (i * preds.shape[0] // splits) : ( |
| (i + 1) * preds.shape[0] // splits |
| ), |
| :, |
| ] |
| kl = part * (np.log(part) - np.log(np.expand_dims(np.mean(part, 0), 0))) |
| kl = np.mean(np.sum(kl, 1)) |
| scores.append(np.exp(kl)) |
| return np.mean(scores), np.std(scores), np.squeeze(np.concatenate(pools, 0)) |
|
|
| |
| def _init_inception(): |
| global softmax, pool3 |
| if not os.path.exists(MODEL_DIR): |
| os.makedirs(MODEL_DIR) |
| filename = DATA_URL.split("/")[-1] |
| filepath = os.path.join(MODEL_DIR, filename) |
| if not os.path.exists(filepath): |
|
|
| def _progress(count, block_size, total_size): |
| sys.stdout.write( |
| "\r>> Downloading %s %.1f%%" |
| % (filename, float(count * block_size) / float(total_size) * 100.0) |
| ) |
| sys.stdout.flush() |
|
|
| filepath, _ = urllib.request.urlretrieve(DATA_URL, filepath, _progress) |
| print() |
| statinfo = os.stat(filepath) |
| print("Succesfully downloaded", filename, statinfo.st_size, "bytes.") |
| tarfile.open(filepath, "r:gz").extractall(MODEL_DIR) |
| with tf.gfile.FastGFile( |
| os.path.join(MODEL_DIR, "classify_image_graph_def.pb"), "rb" |
| ) as f: |
| graph_def = tf.GraphDef() |
| graph_def.ParseFromString(f.read()) |
| _ = tf.import_graph_def(graph_def, name="") |
| |
| with tf.Session() as sess: |
| pool3 = sess.graph.get_tensor_by_name("pool_3:0") |
| ops = pool3.graph.get_operations() |
| for op_idx, op in enumerate(ops): |
| for o in op.outputs: |
| shape = o.get_shape() |
| shape = [s.value for s in shape] |
| new_shape = [] |
| for j, s in enumerate(shape): |
| if s == 1 and j == 0: |
| new_shape.append(None) |
| else: |
| new_shape.append(s) |
| o.__dict__["_shape_val"] = tf.TensorShape(new_shape) |
| w = sess.graph.get_operation_by_name("softmax/logits/MatMul").inputs[1] |
| logits = tf.matmul(tf.squeeze(pool3, [1, 2]), w) |
| softmax = tf.nn.softmax(logits) |
|
|
| |
| _init_inception() |
|
|
| if config["use_ground_truth_data"]: |
| |
| if config["which_dataset"] in ["imagenet", "imagenet_lt"]: |
| dataset_name_prefix = "ILSVRC" |
| elif config["which_dataset"] == "coco": |
| dataset_name_prefix = "COCO" |
| hdf5_filename = "%s%i%s%s%s_xy.hdf5" % ( |
| dataset_name_prefix, |
| config["resolution"], |
| "longtail" |
| if config["which_dataset"] == "imagenet_lt" and config["split"] == "train" |
| else "", |
| "_val" if config["split"] == "val" else "", |
| "_test" |
| if config["split"] == "val" and config["which_dataset"] == "coco" |
| else "", |
| ) |
| with h5.File(os.path.join(config["data_root"], hdf5_filename), "r") as f: |
| data_imgs = f["imgs"][:] |
| data_labels = f["labels"][:] |
| ims = data_imgs.transpose(0, 2, 3, 1) |
|
|
| else: |
| if config["strat_name"] != "": |
| fname = "%s/%s/samples%s_seed%i_strat_%s.pickle" % ( |
| config["experiment_root"], |
| config["experiment_name"], |
| "_kmeans" + str(config["kmeans_subsampled"]) |
| if config["kmeans_subsampled"] > -1 |
| else "", |
| config["seed"], |
| config["strat_name"], |
| ) |
| else: |
| fname = "%s/%s/samples%s_seed%i.pickle" % ( |
| config["experiment_root"], |
| config["experiment_name"], |
| "_kmeans" + str(config["kmeans_subsampled"]) |
| if config["kmeans_subsampled"] > -1 |
| else "", |
| config["seed"], |
| ) |
| print("loading %s ..." % fname) |
| file_to_read = open(fname, "rb") |
| ims = pickle.load(file_to_read)["x"] |
| print("loading %s ..." % fname) |
| print("number of images saved are ", len(ims)) |
| file_to_read.close() |
| ims = ims.swapaxes(1, 2).swapaxes(2, 3) |
|
|
| import time |
|
|
| t0 = time.time() |
| inc_mean, inc_std, pool_activations = get_inception_score( |
| list(ims), splits=10, normalize=not config["use_ground_truth_data"] |
| ) |
| t1 = time.time() |
| print("Saving pool to numpy file for FID calculations...") |
| mu = np.mean(pool_activations, axis=0) |
| sigma = np.cov(pool_activations, rowvar=False) |
| if config["use_ground_truth_data"]: |
| np.savez( |
| "%s/%s%s_res%i_tf_inception_moments_ground_truth.npz" |
| % ( |
| config["data_root"], |
| config["which_dataset"], |
| "_val" if config["split"] == "val" else "", |
| config["resolution"], |
| ), |
| **{"mu": mu, "sigma": sigma} |
| ) |
| else: |
| np.savez( |
| "%s/%s/TF_pool%s_%s.npz" |
| % ( |
| config["experiment_root"], |
| config["experiment_name"], |
| "_val" if config["split"] == "val" else "", |
| "_strat_" + config["strat_name"] if config["strat_name"] != "" else "", |
| ), |
| **{"mu": mu, "sigma": sigma} |
| ) |
| print( |
| "Inception took %3f seconds, score of %3f +/- %3f." |
| % (t1 - t0, inc_mean, inc_std) |
| ) |
|
|
| |
| if ( |
| config["split"] == "val" |
| and config["which_dataset"] == "imagenet_lt" |
| and config["use_ground_truth_data"] |
| ): |
| samples_per_class = np.load( |
| "BigGAN_PyTorch/imagenet_lt/imagenet_lt_samples_per_class.npy", |
| allow_pickle=True, |
| ) |
| for strat_name in ["_many", "_low", "_few"]: |
| if strat_name == "_many": |
| pool_ = pool_activations[samples_per_class[data_labels] >= 100] |
| elif strat_name == "_low": |
| pool_ = pool_activations[samples_per_class[data_labels] < 100] |
| labels_ = data_labels[samples_per_class[data_labels] < 100] |
| pool_ = pool_[samples_per_class[labels_] > 20] |
| elif strat_name == "_few": |
| pool_ = pool_activations[samples_per_class[data_labels] <= 20] |
| print("Size for strat ", strat_name, " is ", len(pool_)) |
| mu = np.mean(pool_, axis=0) |
| sigma = np.cov(pool_, rowvar=False) |
|
|
| np.savez( |
| "%s/%s%s_res%i_tf_inception_moments%s_ground_truth.npz" |
| % ( |
| config["data_root"], |
| config["which_dataset"], |
| "_val" if config["split"] == "val" else "", |
| config["resolution"], |
| strat_name, |
| ), |
| **{"mu": mu, "sigma": sigma} |
| ) |
|
|
|
|
| def main(): |
| |
| parser = prepare_parser() |
| config = vars(parser.parse_args()) |
| print(config) |
| run(config) |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|