← back to Handbag Authentication

handbag_data/github_datasets/iGAN/train_dcgan/train_predict_z.py

187 lines

from __future__ import print_function
import sys

sys.path.append('..')
import os
import json
import numpy as np
from tqdm import tqdm
import theano
import theano.tensor as T
from lib import utils
from lib import updates
from lib import costs
from lib.theano_utils import floatX, sharedX
from load import load_imgs
from lib import image_save
import train_dcgan_utils
import train_dcgan_config
from lib import AlexNet
import lasagne
import argparse
from time import time
import cv2

# set arguments and parameters
parser = argparse.ArgumentParser('Train a predictive network (x->z) to invert the generative network')
parser.add_argument('--model_name', dest='model_name', help='model name', default='shoes_64', type=str)
parser.add_argument('--ext', dest='ext', help='experiment name=model_name+ext', default='', type=str)
parser.add_argument('--data_file', dest='data_file', help='the file that stores the hdf5 data', type=str, default=None)
parser.add_argument('--cache_dir', dest='cache_dir', help='cache directory that stores models, samples and webpages', type=str, default=None)
parser.add_argument('--batch_size', dest='batch_size', help='the number of examples in each batch', type=int, default=128)

parser.add_argument('--save_freq', dest='save_freq', help='save a model every save_freq epochs', type=int, default=1)
parser.add_argument('--lr', dest='lr', help='learning rate', type=float, default=0.0002)
parser.add_argument('--weight_decay', dest='weight_decay', help='l2 weight decay', type=float, default=1e-5)
parser.add_argument('--b1', dest='b1', help='momentum term of adam', type=float, default=0.5)
parser.add_argument('--layer', dest='layer', help='the AlexNet layer used for feature loss', type=str, default='conv4')
parser.add_argument('--alpha', dest='alpha', help='the weight for feature loss. Loss=pixel_loss + alpha * feature_loss', type=float, default=0.002)
args = parser.parse_args()


if not args.data_file:
    args.data_file = '../datasets/%s.hdf5' % args.model_name

npx, n_layers, n_f, nc, nz, niter, niter_decay = getattr(train_dcgan_config, args.model_name)()
expr_name = args.model_name + args.ext

if not args.cache_dir:
    args.cache_dir = './cache/%s/' % expr_name

for arg in vars(args):
    print('[%s] =' % arg, getattr(args, arg))

# create directories
rec_dir = os.path.join(args.cache_dir, 'rec')
model_dir = os.path.join(args.cache_dir, 'models')
log_dir = os.path.join(args.cache_dir, 'log')
web_dir = os.path.join(args.cache_dir, 'web_rec')
html = image_save.ImageSave(web_dir, expr_name, append=True)
utils.mkdirs([rec_dir, model_dir, log_dir, web_dir])

# load data
tr_data, te_data, tr_stream, te_stream, ntrain, ntest \
    = load_imgs(ntrain=None, ntest=None, batch_size=args.batch_size, data_file=args.data_file)
te_handle = te_data.open()
ntest = int(np.floor(ntest / float(args.batch_size)) * args.batch_size)
# st()
test_x, = te_data.get_data(te_handle, slice(0, ntest))

test_x = train_dcgan_utils.transform(test_x, nc=nc)
predict_params = train_dcgan_utils.init_predict_params(nz=nz, n_f=n_f, n_layers=n_layers, nc=nc)
# load modelG
gen_params = train_dcgan_utils.init_gen_params(nz=nz, n_f=n_f, n_layers=n_layers, nc=nc)
train_dcgan_utils.load_model(gen_params, os.path.join(model_dir, 'gen_params'))
gen_batchnorm = train_dcgan_utils.load_batchnorm(os.path.join(model_dir, 'gen_batchnorm'))

# define the model
t = time()
x = T.tensor4()
z = train_dcgan_utils.predict(x, predict_params, n_layers=n_layers)
gx = train_dcgan_utils.gen_test(z, gen_params, gen_batchnorm, n_layers=n_layers, n_f=n_f)

# define pixel loss
pixel_loss = costs.L2Loss(gx, x)

# define feature loss
x_t = AlexNet.transform_im(x, npx=npx, nc=nc)
x_net = AlexNet.build_model(x_t, layer=args.layer, shape=(None, 3, npx, npx))
AlexNet.load_model(x_net, layer=args.layer)
x_f = lasagne.layers.get_output(x_net[args.layer], deterministic=True)
gx_t = AlexNet.transform_im(gx, npx=npx, nc=nc)
gx_net = AlexNet.build_model(gx_t, layer=args.layer, shape=(None, 3, npx, npx))
AlexNet.load_model(gx_net, layer=args.layer)
gx_f = lasagne.layers.get_output(gx_net[args.layer], deterministic=True)
ftr_loss = costs.L2Loss(gx_f, x_f)

# add two losses together
cost = pixel_loss + ftr_loss * sharedX(args.alpha)
output = [cost, z]
lrt = sharedX(args.lr)
b1t = sharedX(args.b1)
p_updater = updates.Adam(lr=lrt, b1=b1t, regularizer=updates.Regularizer(l2=args.weight_decay))
p_updates = p_updater(predict_params, cost)

print('COMPILING')
t = time()
_train_p = theano.function([x], cost, updates=p_updates)
_train_p_cost = theano.function([x], [cost, gx])
_predict_z = theano.function([x], z)
_gen = theano.function([z], gx)
print('%.2f seconds to compile theano functions' % (time() - t))


def rec_test(test_data, n_epochs=0, batch_size=128, output_dir=None):

    print('computing reconstruction loss on test images')
    rec_imgs = []
    imgs = []
    costs = []
    ntest = len(test_data)

    for n in tqdm(range(ntest / batch_size)):
        imb = test_data[n * batch_size:(n + 1) * batch_size, ...]
        # imb = train_dcgan_utils.transform(xmb, nc=3)
        [cost, gx] = _train_p_cost(imb)
        costs.append(cost)
        ntest = ntest + 1
        if n == 0:
            utils.print_numpy(imb)
            utils.print_numpy(gx)
            imgs.append(train_dcgan_utils.inverse_transform(imb, npx=npx, nc=nc))
            rec_imgs.append(train_dcgan_utils.inverse_transform(gx, npx=npx, nc=nc))

    if output_dir is not None:
        # st()
        save_samples = np.hstack(np.concatenate(imgs, axis=0))
        save_recs = np.hstack(np.concatenate(rec_imgs, axis=0))
        save_comp = np.vstack([save_samples, save_recs])
        mean_cost = np.mean(costs)

        txt = 'epoch = %3.3d, cost = %3.3f' % (n_epochs, mean_cost)

        width = save_comp.shape[1]
        save_f = (save_comp * 255).astype(np.uint8)
        html.save_image([save_f], [''], header=txt, width=width, cvt=True)
        html.save()
        save_cvt = cv2.cvtColor(save_f, cv2.COLOR_RGB2BGR)
        cv2.imwrite(os.path.join(rec_dir, 'rec_epoch_%5.5d.png' % n_epochs), save_cvt)

    return mean_cost


f_log = open('%s/training_predict_log.ndjson' % log_dir, 'wb')
log_fields = ['n_epochs', 'n_updates', 'n_examples', 'n_seconds', 'test_cost']

n_epochs = 0
n_updates = 0
n_examples = 0
t = time()

for epoch in range(niter + niter_decay):
    n = 0
    total_n = int(ntrain / args.batch_size)
    for xmb, in tr_stream.get_epoch_iterator():
        imb = train_dcgan_utils.transform(xmb, nc=nc)
        n += 1
        train_cost = _train_p(imb)
        print('epoch = %3.3d, n = %3.3d/%3.3d, train_cost = %4.4f' % (epoch, n, total_n, train_cost)),
        n_updates += 1
        n_examples += len(xmb)

    n_epochs += 1

    if n_epochs % args.save_freq == 0:
        train_dcgan_utils.save_model(predict_params, '%s/predict_params%3.3d' % (model_dir, n_epochs))
    train_dcgan_utils.save_model(predict_params, os.path.join(model_dir, 'predict_params'))  # save the latest one

    test_cost = rec_test(test_data=test_x, n_epochs=n_epochs, batch_size=args.batch_size, output_dir=rec_dir)
    log = [n_epochs, n_updates, n_examples, time() - t, float(test_cost)]

    print('%.0f %.4f' % (epoch, test_cost))
    f_log.write(json.dumps(dict(zip(log_fields, log))) + '\n')
    f_log.flush()

    if n_epochs > niter:
        lrt.set_value(floatX(lrt.get_value() - args.lr / niter_decay))