JGAN/models/pix2pix/pix2pix.py

203 lines
7.3 KiB
Python

import jittor as jt
from jittor import init
from jittor import nn
import jittor.transform as transform
import argparse
import os
import numpy as np
import math
import itertools
import time
import datetime
import sys
import cv2
import time
from models import *
from datasets import *
import warnings
warnings.filterwarnings("ignore")
jt.flags.use_cuda = 1
parser = argparse.ArgumentParser()
parser.add_argument("--epoch", type=int, default=0, help="epoch to start training from")
parser.add_argument("--n_epochs", type=int, default=200, help="number of epochs of training")
parser.add_argument("--dataset_name", type=str, default="facades", help="name of the dataset")
parser.add_argument("--batch_size", type=int, default=1, help="size of the batches")
parser.add_argument("--lr", type=float, default=0.0002, help="adam: learning rate")
parser.add_argument("--b1", type=float, default=0.5, help="adam: decay of first order momentum of gradient")
parser.add_argument("--b2", type=float, default=0.999, help="adam: decay of first order momentum of gradient")
parser.add_argument("--decay_epoch", type=int, default=100, help="epoch from which to start lr decay")
parser.add_argument("--n_cpu", type=int, default=8, help="number of cpu threads to use during batch generation")
parser.add_argument("--img_height", type=int, default=256, help="size of image height")
parser.add_argument("--img_width", type=int, default=256, help="size of image width")
parser.add_argument("--channels", type=int, default=3, help="number of image channels")
parser.add_argument(
"--sample_interval", type=int, default=500, help="interval between sampling of images from generators"
)
parser.add_argument("--checkpoint_interval", type=int, default=1, help="interval between model checkpoints")
opt = parser.parse_args()
print(opt)
def save_image(img, path, nrow=10):
N,C,W,H = img.shape
if (N%nrow!=0):
print("save_image error: N%nrow!=0")
return
img=img.transpose((1,0,2,3))
ncol=int(N/nrow)
img2=img.reshape([img.shape[0],-1,H])
img=img2[:,:W*ncol,:]
for i in range(1,int(img2.shape[1]/W/ncol)):
img=np.concatenate([img,img2[:,W*ncol*i:W*ncol*(i+1),:]],axis=2)
min_=img.min()
max_=img.max()
img=(img-min_)/(max_-min_)*255
img=img.transpose((1,2,0))
if C==3:
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
cv2.imwrite(path,img)
os.makedirs("images/%s" % opt.dataset_name, exist_ok=True)
os.makedirs("saved_models/%s" % opt.dataset_name, exist_ok=True)
# Loss functions
criterion_GAN = nn.MSELoss()
criterion_pixelwise = nn.L1Loss()
# Loss weight of L1 pixel-wise loss between translated image and real image
lambda_pixel = 100
# Calculate output of image discriminator (PatchGAN)
patch = (1, opt.img_height // 2 ** 4, opt.img_width // 2 ** 4)
# Initialize generator and discriminator
generator = GeneratorUNet()
discriminator = Discriminator()
if opt.epoch != 0:
# Load pretrained models
generator.load("saved_models/%s/generator_last.pkl" % (opt.dataset_name))
discriminator.load("saved_models/%s/discriminator_last.pkl" % (opt.dataset_name))
# Optimizers
optimizer_G = jt.optim.Adam(generator.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2))
optimizer_D = jt.optim.Adam(discriminator.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2))
# Configure dataloaders
transforms_ = [
transform.Resize(size=(opt.img_height, opt.img_width), mode=Image.BICUBIC),
transform.ImageNormalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5]),
]
dataloader = ImageDataset("../../data/%s" % opt.dataset_name, transforms_=transforms_).set_attrs(
batch_size=opt.batch_size,
shuffle=True,
num_workers=opt.n_cpu,
)
val_dataloader = ImageDataset("../../data/%s" % opt.dataset_name, transforms_=transforms_, mode="val").set_attrs(
batch_size=10,
shuffle=True,
num_workers=1,
)
def sample_images(batches_done):
"""Saves a generated sample from the validation set"""
real_B, real_A = next(iter(val_dataloader))
fake_B = generator(real_A)
img_sample = np.concatenate([real_A.data, fake_B.data, real_B.data], -2)
save_image(img_sample, "images/%s/%s.png" % (opt.dataset_name, batches_done), nrow=5)
warmup_times = -1
run_times = 3000
total_time = 0.
cnt = 0
# ----------
# Training
# ----------
prev_time = time.time()
for epoch in range(opt.epoch, opt.n_epochs):
for i, (real_B, real_A) in enumerate(dataloader):
# Adversarial ground truths
valid = jt.ones([real_A.shape[0], 1]).stop_grad()
fake = jt.zeros([real_A.shape[0], 1]).stop_grad()
# ------------------
# Train Generators
# ------------------
# GAN loss
fake_B = generator(real_A)
pred_fake = discriminator(fake_B, real_A)
loss_GAN = criterion_GAN(pred_fake, valid)
# Pixel-wise loss
loss_pixel = criterion_pixelwise(fake_B, real_B)
# Total loss
loss_G = loss_GAN + lambda_pixel * loss_pixel
optimizer_G.step(loss_G)
# ---------------------
# Train Discriminator
# ---------------------
# Real loss
pred_real = discriminator(real_B, real_A)
loss_real = criterion_GAN(pred_real, valid)
# Fake loss
pred_fake = discriminator(fake_B.detach(), real_A)
loss_fake = criterion_GAN(pred_fake, fake)
# Total loss
loss_D = 0.5 * (loss_real + loss_fake)
optimizer_D.step(loss_D)
if warmup_times==-1:
# --------------
# Log Progress
# --------------
# Determine approximate time left
batches_done = epoch * len(dataloader) + i
batches_left = opt.n_epochs * len(dataloader) - batches_done
time_left = datetime.timedelta(seconds=batches_left * (time.time() - prev_time))
prev_time = time.time()
# Print log
jt.sync_all()
if batches_done % 5 == 0:
sys.stdout.write(
"\r[Epoch %d/%d] [Batch %d/%d] [D loss: %f] [G loss: %f, pixel: %f, adv: %f] ETA: %s"
% (
epoch,
opt.n_epochs,
i,
len(dataloader),
loss_D.numpy()[0],
loss_G.numpy()[0],
loss_pixel.numpy()[0],
loss_GAN.numpy()[0],
time_left,
)
)
# If at sample interval save image
if batches_done % opt.sample_interval == 0:
sample_images(batches_done)
else:
jt.sync_all()
cnt += 1
print(cnt)
if cnt == warmup_times:
jt.sync_all(True)
sta = time.time()
if cnt > warmup_times + run_times:
jt.sync_all(True)
total_time = time.time() - sta
print(f"run {run_times} iters cost {total_time} seconds, and avg {total_time / run_times} one iter.")
exit(0)
if opt.checkpoint_interval != -1 and epoch % opt.checkpoint_interval == 0:
# Save model checkpoints
generator.save(os.path.join(f"saved_models/{opt.dataset_name}/generator_last.pkl"))
discriminator.save(os.path.join(f"saved_models/{opt.dataset_name}/discriminator_last.pkl"))