Spaces:
Paused
Paused
| """ | |
| @author: Yanzuo Lu | |
| @author: oliveryanzuolu@gmail.com | |
| """ | |
| import argparse | |
| import copy | |
| import datetime | |
| import logging | |
| import os | |
| import sys | |
| import time | |
| import warnings | |
| import numpy as np | |
| import torch | |
| import torch.nn.functional as F | |
| from accelerate import Accelerator | |
| from accelerate.tracking import TensorBoardTracker, WandBTracker | |
| from accelerate.utils import set_seed | |
| from diffusers import (DDIMInverseScheduler, DDIMScheduler, DDPMScheduler, | |
| EulerDiscreteScheduler, PNDMScheduler) | |
| from einops import rearrange | |
| from PIL import Image | |
| from scipy.linalg import sqrtm | |
| from torch.utils.data import DataLoader | |
| from torchvision.utils import make_grid | |
| from datasets import FidRealDeepFashion, PisTestDeepFashion | |
| from defaults import pose_transfer_C as cfg | |
| from models import UNet, VariationalAutoencoder, build_metric | |
| from utils import AverageMeter | |
| warnings.filterwarnings("ignore") | |
| logger = logging.getLogger() | |
| def build_test_loader(cfg): | |
| test_data = PisTestDeepFashion( | |
| cfg.INPUT.ROOT_DIR, cfg.INPUT.GT.IMG_SIZE, cfg.INPUT.POSE.IMG_SIZE, | |
| cfg.INPUT.COND.IMG_SIZE, cfg.TEST.IMG_SIZE) | |
| test_loader = DataLoader( | |
| test_data, | |
| cfg.TEST.MICRO_BATCH_SIZE, | |
| num_workers=cfg.TEST.NUM_WORKERS, | |
| pin_memory=True | |
| ) | |
| fid_real_data = FidRealDeepFashion(cfg.INPUT.ROOT_DIR, cfg.TEST.IMG_SIZE) | |
| fid_real_loader = DataLoader( | |
| fid_real_data, | |
| cfg.TEST.MICRO_BATCH_SIZE, | |
| num_workers=cfg.TEST.NUM_WORKERS, | |
| pin_memory=True | |
| ) | |
| return test_loader, fid_real_loader, test_data, fid_real_data | |
| def eval(cfg, model, test_loader, fid_real_loader, weight_dtype, save_dir, | |
| test_data, fid_real_data, global_step, accelerator, metric, | |
| noise_scheduler, inverse_noise_scheduler, vae, unet): | |
| logger.info("start sampling...") | |
| model.eval() | |
| unet.eval() | |
| gt_out_gathered = [] | |
| pred_out_gathered = [] | |
| lpips_gathered = [] | |
| psnr_gathered = [] | |
| ssim_gathered = [] | |
| ssim_256_gathered = [] | |
| with torch.no_grad(): | |
| end_time = time.time() | |
| batch_time = AverageMeter() | |
| for i, test_batch in enumerate(test_loader): | |
| gt_imgs = test_batch["img_gt"] | |
| img_size = test_batch["img_tgt"].shape[2:] | |
| bsz = gt_imgs.shape[0] | |
| if cfg.TEST.DDIM_INVERSION_STEPS > 0: | |
| if cfg.TEST.DDIM_INVERSION_DOWN_BLOCK_GUIDANCE: | |
| c, down_block_additional_residuals, up_block_additional_residuals = model({ | |
| "img_cond": test_batch["img_cond_from"], "pose_img": test_batch["pose_img_from"]}) | |
| else: | |
| c, down_block_additional_residuals, up_block_additional_residuals = model({ | |
| "img_cond": test_batch["img_cond_from"], "pose_img": test_batch["pose_img_to"]}) | |
| noisy_latents = inverse_sample( | |
| cfg.TEST.DDIM_INVERSION_STEPS, accelerator, inverse_noise_scheduler, vae, unet, | |
| test_batch["img_src"], c[:bsz] if cfg.TEST.DDIM_INVERSION_UNCONDITIONAL else c[bsz:], | |
| [sample.to(dtype=weight_dtype) for sample in down_block_additional_residuals] if cfg.TEST.DDIM_INVERSION_DOWN_BLOCK_GUIDANCE else None, | |
| {k: v.to(dtype=weight_dtype) for k, v in up_block_additional_residuals.items()} if cfg.TEST.DDIM_INVERSION_UP_BLOCK_GUIDANCE else None) | |
| else: | |
| c, down_block_additional_residuals, up_block_additional_residuals = model({ | |
| "img_cond": test_batch["img_cond_from"], "pose_img": test_batch["pose_img_to"]}) | |
| noisy_latents = torch.randn((bsz, 4, img_size[0]//8, img_size[1]//8)).to(accelerator.device) | |
| if cfg.TEST.DDIM_INVERSION_STEPS > 0 and cfg.TEST.DDIM_INVERSION_DOWN_BLOCK_GUIDANCE: | |
| c, down_block_additional_residuals, up_block_additional_residuals = model({ | |
| "img_cond": test_batch["img_cond_from"], "pose_img": test_batch["pose_img_to"]}) | |
| sampling_imgs = sample( | |
| cfg, weight_dtype, accelerator, noise_scheduler, vae, unet, noisy_latents, | |
| c, down_block_additional_residuals, up_block_additional_residuals) | |
| # log one-batch sampling results for visualization | |
| if i == 0: | |
| src_imgs = test_batch["img_src"] * 0.5 + 0.5 | |
| tgt_imgs = test_batch["img_tgt"] * 0.5 + 0.5 | |
| pose_imgs = F.interpolate(test_batch["pose_img_to"][:, :3, :, :], | |
| tuple(test_batch["img_src"].shape[2:]), | |
| mode="bicubic", antialias=True) | |
| save_img = torch.stack([src_imgs, pose_imgs, tgt_imgs, sampling_imgs]) | |
| save_img = postprocess_image(save_img, nrow=save_img.shape[0]*2) | |
| save_img.save(os.path.join(save_dir, f"inpainting_test_{accelerator.process_index}_{i}.jpg")) | |
| sampling_imgs = F.interpolate(sampling_imgs, tuple(gt_imgs.shape[2:]), mode="bicubic", antialias=True) | |
| sampling_imgs = sampling_imgs.float() * 255.0 | |
| sampling_imgs = sampling_imgs.clamp(0, 255).to(dtype=torch.uint8) # can save all images here!!! | |
| sampling_imgs = sampling_imgs.to(torch.float32) / 255. | |
| pred_out, lpips, psnr, ssim, ssim_256 = metric(gt_imgs, sampling_imgs) | |
| pred_out_gathered.append(accelerator.gather_for_metrics(pred_out).cpu().numpy()) | |
| lpips_gathered.append(accelerator.gather_for_metrics(lpips).cpu().numpy()) | |
| psnr_gathered.append(accelerator.gather_for_metrics(psnr).cpu().numpy()) | |
| ssim_gathered.append(accelerator.gather_for_metrics(ssim).cpu().numpy()) | |
| ssim_256_gathered.append(accelerator.gather_for_metrics(ssim_256).cpu().numpy()) | |
| batch_time.update(time.time() - end_time) | |
| end_time = time.time() | |
| if (i + 1) % cfg.ACCELERATE.LOG_PERIOD == 0 or i == len(test_loader) - 1: | |
| etas = batch_time.avg * (len(test_loader) - 1 - i) | |
| logger.info( | |
| f"Sampling ({i+1}/{len(test_loader)}) " | |
| f"Time {batch_time.val:.4f}({batch_time.avg:.4f}) " | |
| f"Eta {datetime.timedelta(seconds=int(etas))}") | |
| if os.environ.get("WANDB_MODE", None) == "offline": | |
| break | |
| end_time = time.time() | |
| batch_time = AverageMeter() | |
| for i, fid_real_imgs in enumerate(fid_real_loader): | |
| gt_out = metric(fid_real_imgs) | |
| gt_out_gathered.append(accelerator.gather_for_metrics(gt_out).cpu().numpy()) | |
| batch_time.update(time.time() - end_time) | |
| end_time = time.time() | |
| if (i + 1) % cfg.ACCELERATE.LOG_PERIOD == 0 or i == len(fid_real_loader) - 1: | |
| etas = batch_time.avg * (len(fid_real_loader) - 1 - i) | |
| logger.info( | |
| f"FidReal ({i+1}/{len(fid_real_loader)}) " | |
| f"Time {batch_time.val:.4f}({batch_time.avg:.4f}) " | |
| f"Eta {datetime.timedelta(seconds=int(etas))}") | |
| if accelerator.is_main_process: | |
| gt_out_gathered = np.concatenate(gt_out_gathered, axis=0) | |
| pred_out_gathered = np.concatenate(pred_out_gathered, axis=0) | |
| lpips_gathered = np.concatenate(lpips_gathered, axis=0) | |
| psnr_gathered = np.concatenate(psnr_gathered, axis=0) | |
| ssim_gathered = np.concatenate(ssim_gathered, axis=0) | |
| ssim_256_gathered = np.concatenate(ssim_256_gathered, axis=0) | |
| if os.environ.get("WANDB_MODE", None) != "offline": | |
| assert len(gt_out_gathered) == len(fid_real_data) | |
| assert len(pred_out_gathered) == len(lpips_gathered) == len(psnr_gathered) == \ | |
| len(ssim_gathered) == len(ssim_256_gathered) == len(test_data) | |
| mu1 = np.mean(gt_out_gathered, axis=0) | |
| sigma1 = np.cov(gt_out_gathered, rowvar=False) | |
| mu2 = np.mean(pred_out_gathered, axis=0) | |
| sigma2 = np.cov(pred_out_gathered, rowvar=False) | |
| mu1 = np.atleast_1d(mu1) | |
| mu2 = np.atleast_1d(mu2) | |
| sigma1 = np.atleast_2d(sigma1) | |
| sigma2 = np.atleast_2d(sigma2) | |
| diff = mu1 - mu2 | |
| # Product might be almost singular | |
| covmean, _ = sqrtm(sigma1.dot(sigma2), disp=False) | |
| if not np.isfinite(covmean).all(): | |
| msg = ('fid calculation produces singular product; ' | |
| 'adding %s to diagonal of cov estimates') % 1e-6 | |
| logger.info(msg) | |
| offset = np.eye(sigma1.shape[0]) * 1e-6 | |
| covmean = sqrtm((sigma1 + offset).dot(sigma2 + offset)) | |
| # Numerical error might give slight imaginary component | |
| if np.iscomplexobj(covmean): | |
| if not np.allclose(np.diagonal(covmean).imag, 0, atol=1e-3): | |
| m = np.max(np.abs(covmean.imag)) | |
| raise ValueError('Imaginary component {}'.format(m)) | |
| covmean = covmean.real | |
| tr_covmean = np.trace(covmean) | |
| score_fid = diff.dot(diff) + np.trace(sigma1) + np.trace(sigma2) - 2 * tr_covmean | |
| score_lpips = np.mean(lpips_gathered) | |
| score_ssim = np.mean(ssim_gathered) | |
| score_ssim_256 = np.mean(ssim_256_gathered) | |
| score_psnr = np.mean(psnr_gathered) | |
| logger.info("Evaluation Results:") | |
| logger.info(f"FID: {score_fid:.3f}") | |
| logger.info(f"LPIPS: {score_lpips:.4f}") | |
| logger.info(f"SSIM: {score_ssim:.4f}") | |
| logger.info(f"SSIM_256: {score_ssim_256:.4f}") | |
| logger.info(f"PSNR: {score_psnr:.3f}") | |
| accelerator.log({ | |
| "score_fid": score_fid, | |
| "score_lpips": score_lpips, | |
| "score_ssim": score_ssim, | |
| "score_ssim_256": score_ssim_256, | |
| "score_psnr": score_psnr | |
| }, step=global_step) | |
| accelerator.wait_for_everyone() | |
| torch.cuda.empty_cache() | |
| def sample(cfg, weight_dtype, accelerator, noise_scheduler, vae, unet, noisy_latents, | |
| c_new, down_block_additional_residuals, up_block_additional_residuals): | |
| bsz = noisy_latents.shape[0] | |
| noise_scheduler.set_timesteps(cfg.TEST.NUM_INFERENCE_STEPS) | |
| if cfg.TEST.GUIDANCE_TYPE == "uc_full": | |
| down_block_additional_residuals = [torch.cat([torch.zeros_like(sample), sample]).to(dtype=weight_dtype) \ | |
| for sample in down_block_additional_residuals] | |
| up_block_additional_residuals = {k: torch.cat([torch.zeros_like(v), v]).to(dtype=weight_dtype) \ | |
| for k, v in up_block_additional_residuals.items()} | |
| for t in noise_scheduler.timesteps: | |
| inputs = torch.cat([noisy_latents, noisy_latents], dim=0) | |
| inputs = noise_scheduler.scale_model_input(inputs, timestep=t) | |
| with accelerator.autocast(): | |
| noise_pred = unet(sample=inputs, timestep=t, encoder_hidden_states=c_new, | |
| down_block_additional_residuals=copy.deepcopy(down_block_additional_residuals), | |
| up_block_additional_residuals=copy.deepcopy(up_block_additional_residuals)) | |
| noise_pred_uc, noise_pred_full = noise_pred.chunk(2) | |
| noise_pred = noise_pred_uc + cfg.TEST.FULL_GUIDANCE_SCALE * (noise_pred_full - noise_pred_uc) | |
| noisy_latents = noise_scheduler.step(noise_pred, t, noisy_latents)[0] | |
| elif cfg.TEST.GUIDANCE_TYPE == "updown_full": | |
| down_block_additional_residuals = [torch.cat([sample, sample]).to(dtype=weight_dtype) \ | |
| for sample in down_block_additional_residuals] | |
| up_block_additional_residuals = {k: torch.cat([v, v]).to(dtype=weight_dtype) \ | |
| for k, v in up_block_additional_residuals.items()} | |
| for t in noise_scheduler.timesteps: | |
| inputs = torch.cat([noisy_latents, noisy_latents], dim=0) | |
| inputs = noise_scheduler.scale_model_input(inputs, timestep=t) | |
| with accelerator.autocast(): | |
| noise_pred = unet(sample=inputs, timestep=t, encoder_hidden_states=c_new, | |
| down_block_additional_residuals=copy.deepcopy(down_block_additional_residuals), | |
| up_block_additional_residuals=copy.deepcopy(up_block_additional_residuals)) | |
| noise_pred_updown, noise_pred_full = noise_pred.chunk(2) | |
| noise_pred = noise_pred_updown + cfg.TEST.FULL_GUIDANCE_SCALE * (noise_pred_full - noise_pred_updown) | |
| noisy_latents = noise_scheduler.step(noise_pred, t, noisy_latents)[0] | |
| elif cfg.TEST.GUIDANCE_TYPE == "down_full": | |
| down_block_additional_residuals = [torch.cat([sample, sample]).to(dtype=weight_dtype) \ | |
| for sample in down_block_additional_residuals] | |
| up_block_additional_residuals = {k: torch.cat([torch.zeros_like(v), v]).to(dtype=weight_dtype) \ | |
| for k, v in up_block_additional_residuals.items()} | |
| for t in noise_scheduler.timesteps: | |
| inputs = torch.cat([noisy_latents, noisy_latents], dim=0) | |
| inputs = noise_scheduler.scale_model_input(inputs, timestep=t) | |
| with accelerator.autocast(): | |
| noise_pred = unet(sample=inputs, timestep=t, encoder_hidden_states=c_new, | |
| down_block_additional_residuals=copy.deepcopy(down_block_additional_residuals), | |
| up_block_additional_residuals=copy.deepcopy(up_block_additional_residuals)) | |
| noise_pred_down, noise_pred_full = noise_pred.chunk(2) | |
| noise_pred = noise_pred_down + cfg.TEST.FULL_GUIDANCE_SCALE * (noise_pred_full - noise_pred_down) | |
| noisy_latents = noise_scheduler.step(noise_pred, t, noisy_latents)[0] | |
| elif cfg.TEST.GUIDANCE_TYPE == "uc_down_full": | |
| c_new = torch.cat([c_new[:bsz], c_new[:bsz], c_new[bsz:]]) | |
| down_block_additional_residuals = [torch.cat([torch.zeros_like(sample), sample, sample]).to(dtype=weight_dtype) \ | |
| for sample in down_block_additional_residuals] | |
| up_block_additional_residuals = {k: torch.cat([torch.zeros_like(v), torch.zeros_like(v), v]).to(dtype=weight_dtype) \ | |
| for k, v in up_block_additional_residuals.items()} | |
| for t in noise_scheduler.timesteps: | |
| inputs = torch.cat([noisy_latents, noisy_latents, noisy_latents], dim=0) | |
| inputs = noise_scheduler.scale_model_input(inputs, timestep=t) | |
| with accelerator.autocast(): | |
| noise_pred = unet(sample=inputs, timestep=t, encoder_hidden_states=c_new, | |
| down_block_additional_residuals=copy.deepcopy(down_block_additional_residuals), | |
| up_block_additional_residuals=copy.deepcopy(up_block_additional_residuals)) | |
| noise_pred_uc, noise_pred_down, noise_pred_full = noise_pred.chunk(3) | |
| noise_pred = noise_pred_uc + \ | |
| cfg.TEST.DOWN_BLOCK_GUIDANCE_SCALE * (noise_pred_down - noise_pred_uc) + \ | |
| cfg.TEST.FULL_GUIDANCE_SCALE * (noise_pred_full - noise_pred_down) | |
| noisy_latents = noise_scheduler.step(noise_pred, t, noisy_latents)[0] | |
| elif cfg.TEST.GUIDANCE_TYPE == "uc_down_updown_cdown": | |
| c_new = torch.cat([c_new[:bsz], c_new[:bsz], c_new[:bsz], c_new[bsz:]]) | |
| down_block_additional_residuals = [torch.cat([torch.zeros_like(sample), sample, sample, sample]).to(dtype=weight_dtype) \ | |
| for sample in down_block_additional_residuals] | |
| up_block_additional_residuals = {k: torch.cat([torch.zeros_like(v), torch.zeros_like(v), v, torch.zeros_like(v)]).to(dtype=weight_dtype) \ | |
| for k, v in up_block_additional_residuals.items()} | |
| for t in noise_scheduler.timesteps: | |
| inputs = torch.cat([noisy_latents, noisy_latents, noisy_latents, noisy_latents], dim=0) | |
| inputs = noise_scheduler.scale_model_input(inputs, timestep=t) | |
| with accelerator.autocast(): | |
| noise_pred = unet(sample=inputs, timestep=t, encoder_hidden_states=c_new, | |
| down_block_additional_residuals=copy.deepcopy(down_block_additional_residuals), | |
| up_block_additional_residuals=copy.deepcopy(up_block_additional_residuals)) | |
| noise_pred_uc, noise_pred_down, noise_pred_updown, noise_pred_cdown = noise_pred.chunk(4) | |
| noise_pred = noise_pred_uc + \ | |
| cfg.TEST.DOWN_BLOCK_GUIDANCE_SCALE * (noise_pred_down - noise_pred_uc) + \ | |
| cfg.TEST.ALL_BLOCK_GUIDANCE_SCALE * (noise_pred_updown - noise_pred_down) + \ | |
| cfg.TEST.GUIDANCE_SCALE * (noise_pred_cdown - noise_pred_down) | |
| noisy_latents = noise_scheduler.step(noise_pred, t, noisy_latents)[0] | |
| elif cfg.TEST.GUIDANCE_TYPE == "uc_down_updown_full": | |
| c_new = torch.cat([c_new[:bsz], c_new[:bsz], c_new[:bsz], c_new[bsz:]]) | |
| down_block_additional_residuals = [torch.cat([torch.zeros_like(sample), sample, sample, sample]).to(dtype=weight_dtype) \ | |
| for sample in down_block_additional_residuals] | |
| up_block_additional_residuals = {k: torch.cat([torch.zeros_like(v), torch.zeros_like(v), v, v]).to(dtype=weight_dtype) \ | |
| for k, v in up_block_additional_residuals.items()} | |
| for t in noise_scheduler.timesteps: | |
| inputs = torch.cat([noisy_latents, noisy_latents, noisy_latents, noisy_latents], dim=0) | |
| inputs = noise_scheduler.scale_model_input(inputs, timestep=t) | |
| with accelerator.autocast(): | |
| noise_pred = unet(sample=inputs, timestep=t, encoder_hidden_states=c_new, | |
| down_block_additional_residuals=copy.deepcopy(down_block_additional_residuals), | |
| up_block_additional_residuals=copy.deepcopy(up_block_additional_residuals)) | |
| noise_pred_uc, noise_pred_down, noise_pred_updown, noise_pred_full = noise_pred.chunk(4) | |
| noise_pred = noise_pred_uc + \ | |
| cfg.TEST.DOWN_BLOCK_GUIDANCE_SCALE * (noise_pred_down - noise_pred_uc) + \ | |
| cfg.TEST.ALL_BLOCK_GUIDANCE_SCALE * (noise_pred_updown - noise_pred_down) + \ | |
| cfg.TEST.FULL_GUIDANCE_SCALE * (noise_pred_full - noise_pred_updown) | |
| noisy_latents = noise_scheduler.step(noise_pred, t, noisy_latents)[0] | |
| with accelerator.autocast(): | |
| sampling_imgs = vae.decode(noisy_latents) * 0.5 + 0.5 # denormalize | |
| sampling_imgs = sampling_imgs.clamp(0, 1) | |
| return sampling_imgs | |
| def inverse_sample(num_inference_steps, accelerator, inverse_noise_scheduler, vae, unet, img_src, | |
| c_new, down_block_additional_residuals=None, up_block_additional_residuals=None): | |
| inverse_noise_scheduler.set_timesteps(num_inference_steps) | |
| with accelerator.autocast(): | |
| noisy_latents = vae.encode(img_src) | |
| for t in inverse_noise_scheduler.timesteps: | |
| inputs = noisy_latents | |
| with accelerator.autocast(): | |
| noise_pred = unet(sample=inputs, timestep=t, encoder_hidden_states=c_new, | |
| down_block_additional_residuals=copy.deepcopy(down_block_additional_residuals) if down_block_additional_residuals else None, | |
| up_block_additional_residuals=copy.deepcopy(up_block_additional_residuals) if up_block_additional_residuals else None) | |
| noisy_latents = inverse_noise_scheduler.step(noise_pred, t, noisy_latents)[0] | |
| return noisy_latents | |
| def postprocess_image(tensor, nrow): | |
| tensor = tensor * 255. | |
| tensor = torch.clamp(tensor, min=0., max=255.) | |
| tensor = rearrange(tensor, 'n b c h w -> b n c h w') | |
| tensor = rearrange(tensor, 'b n c h w -> (b n) c h w') | |
| tensor = make_grid(tensor, nrow=nrow) | |
| img = tensor.cpu().numpy().transpose(1, 2, 0).astype(np.uint8) | |
| return Image.fromarray(img) | |
| def main(cfg): | |
| project_dir = os.path.join("outputs", cfg.ACCELERATE.PROJECT_NAME) | |
| run_dir = os.path.join(project_dir, cfg.ACCELERATE.RUN_NAME) | |
| os.makedirs(run_dir, exist_ok=True) | |
| accelerator = Accelerator( | |
| log_with = ["wandb", "tensorboard"], | |
| project_dir = project_dir, | |
| mixed_precision = cfg.ACCELERATE.MIXED_PRECISION | |
| ) | |
| torch.backends.cuda.matmul.allow_tf32 = cfg.ACCELERATE.ALLOW_TF32 | |
| set_seed(cfg.ACCELERATE.SEED) | |
| if accelerator.is_main_process: | |
| accelerator.trackers = [] | |
| accelerator.trackers.append(WandBTracker( | |
| cfg.ACCELERATE.PROJECT_NAME, name=cfg.ACCELERATE.RUN_NAME, config=cfg, dir=project_dir)) | |
| accelerator.trackers.append(TensorBoardTracker(cfg.ACCELERATE.RUN_NAME, project_dir)) | |
| with open(os.path.join(run_dir, "config.yaml"), "w") as f: | |
| f.write(cfg.dump()) | |
| accelerator.wait_for_everyone() | |
| fmt = "[%(asctime)s %(filename)s:%(lineno)s] %(message)s" | |
| datefmt = "%Y-%m-%d %H:%M:%S" | |
| logging.basicConfig( | |
| level = logging.INFO, | |
| format = fmt, | |
| datefmt = datefmt, | |
| filename = f"{run_dir}/log_rank{accelerator.process_index}.txt", | |
| filemode = "a" | |
| ) | |
| if accelerator.is_main_process: | |
| console_handler = logging.StreamHandler(sys.stdout) | |
| console_handler.setLevel(logging.INFO) | |
| console_handler.setFormatter(logging.Formatter(fmt, datefmt)) | |
| logger.addHandler(console_handler) | |
| logger.info(f"running with config:\n{str(cfg)}") | |
| logger.info("preparing datasets...") | |
| test_loader, fid_real_loader, test_data, fid_real_data = build_test_loader(cfg) | |
| logger.info("preparing model...") | |
| weight_dtype = torch.float32 | |
| if accelerator.mixed_precision == "fp16": | |
| weight_dtype = torch.float16 | |
| elif accelerator.mixed_precision == "bf16": | |
| weight_dtype = torch.bfloat16 | |
| # not trained, move to 16-bit to save memory | |
| vae = VariationalAutoencoder( | |
| pretrained_path=cfg.MODEL.FIRST_STAGE_CONFIG.PRETRAINED_PATH | |
| ).to(accelerator.device, dtype=weight_dtype) | |
| if cfg.MODEL.SCHEDULER_CONFIG.NAME == "euler": | |
| noise_scheduler = EulerDiscreteScheduler.from_pretrained(cfg.MODEL.SCHEDULER_CONFIG.PRETRAINED_PATH) | |
| elif cfg.MODEL.SCHEDULER_CONFIG.NAME == "pndm": | |
| noise_scheduler = PNDMScheduler.from_pretrained(cfg.MODEL.SCHEDULER_CONFIG.PRETRAINED_PATH) | |
| elif cfg.MODEL.SCHEDULER_CONFIG.NAME == "ddim": | |
| noise_scheduler = DDIMScheduler.from_pretrained(cfg.MODEL.SCHEDULER_CONFIG.PRETRAINED_PATH) | |
| elif cfg.MODEL.SCHEDULER_CONFIG.NAME == "ddpm": | |
| noise_scheduler = DDPMScheduler.from_pretrained(cfg.MODEL.SCHEDULER_CONFIG.PRETRAINED_PATH) | |
| inverse_noise_scheduler = DDIMInverseScheduler( | |
| num_train_timesteps=noise_scheduler.num_train_timesteps, | |
| beta_start=noise_scheduler.beta_start, | |
| beta_end=noise_scheduler.beta_end, | |
| beta_schedule=noise_scheduler.beta_schedule, | |
| trained_betas=noise_scheduler.trained_betas, | |
| clip_sample=noise_scheduler.clip_sample, | |
| set_alpha_to_one=noise_scheduler.set_alpha_to_one, | |
| steps_offset=noise_scheduler.steps_offset, | |
| prediction_type=noise_scheduler.prediction_type, | |
| timestep_spacing=noise_scheduler.timestep_spacing | |
| ) | |
| from pose_transfer_train import build_model | |
| model = build_model(cfg) | |
| unet = UNet(cfg) | |
| metric = build_metric().to(accelerator.device) | |
| logger.info(model.load_state_dict(torch.load( | |
| os.path.join(cfg.MODEL.PRETRAINED_PATH, "pytorch_model.bin"), map_location="cpu" | |
| ), strict=False)) | |
| logger.info(unet.load_state_dict(torch.load( | |
| os.path.join(cfg.MODEL.PRETRAINED_PATH, "pytorch_model_1.bin"), map_location="cpu" | |
| ), strict=False)) | |
| logger.info("preparing accelerator...") | |
| model, unet, test_loader, fid_real_loader = accelerator.prepare(model, unet, test_loader, fid_real_loader) | |
| save_dir = os.path.join(run_dir, "log_images") | |
| os.makedirs(save_dir, exist_ok=True) | |
| eval( | |
| cfg=cfg, | |
| model=model, | |
| test_loader=test_loader, | |
| fid_real_loader=fid_real_loader, | |
| weight_dtype=weight_dtype, | |
| save_dir=save_dir, | |
| test_data=test_data, | |
| fid_real_data=fid_real_data, | |
| global_step=None, | |
| accelerator=accelerator, | |
| metric=metric, | |
| noise_scheduler=noise_scheduler, | |
| inverse_noise_scheduler=inverse_noise_scheduler, | |
| vae=vae, | |
| unet=unet | |
| ) | |
| accelerator.end_training() | |
| if __name__ == "__main__": | |
| parser = argparse.ArgumentParser(description="Pose Transfer Testing") | |
| parser.add_argument("--config_file", type=str, default="", help="path to config file") | |
| parser.add_argument("opts", default=None, nargs=argparse.REMAINDER, help= | |
| "modify config options using the command-line") | |
| args = parser.parse_args() | |
| if args.config_file: | |
| cfg.merge_from_file(args.config_file) | |
| cfg.merge_from_list(args.opts) | |
| cfg.freeze() | |
| main(cfg) |