您的位置:首页 > 房产 > 家装 > 东莞网站搭建找哪里_天津的网页设计公司_合肥seo服务商_百度推广代理

东莞网站搭建找哪里_天津的网页设计公司_合肥seo服务商_百度推广代理

2024/12/23 15:17:36 来源:https://blog.csdn.net/m0_51359915/article/details/142148046  浏览:    关键词:东莞网站搭建找哪里_天津的网页设计公司_合肥seo服务商_百度推广代理
东莞网站搭建找哪里_天津的网页设计公司_合肥seo服务商_百度推广代理

  🍨 本文为:[🔗365天深度学习训练营] 中的学习记录博客
 🍖 原作者:[K同学啊 | 接辅导、项目定制]

一、 基础配置

  • 语言环境:Python3.8
  • 编译器选择:Pycharm
  • 深度学习环境:
    • torch==1.12.1+cu113
    • torchvision==0.13.1+cu113

二、 相关代码

1. 文件结构

  • CycleGAN 
    • data
      •  monet2photo
        • testA
        • testB
        • trainA
        • trainB
    • datasets.py  
    • models.py
    • cyclegan.py(主文件)
    • utils.py
    • images(放运行结果)
    • saved_models(放模型)

2. 代码细节

datasets.py

import glob
import random
import osfrom torch.utils.data import Dataset
from PIL import Image
import torchvision.transforms as transformsdef to_rgb(image):rgb_image = Image.new("RGB", image.size)rgb_image.paste(image)return rgb_imageclass ImageDataset(Dataset):def __init__(self, root, transforms_=None, unaligned=False, mode="train"):self.transform = transforms.Compose(transforms_)self.unaligned = unalignedself.files_A = sorted(glob.glob(os.path.join(root, "%sA" % mode) + "/*.*"))self.files_B = sorted(glob.glob(os.path.join(root, "%sB" % mode) + "/*.*"))def __getitem__(self, index):image_A = Image.open(self.files_A[index % len(self.files_A)])if self.unaligned:image_B = Image.open(self.files_B[random.randint(0, len(self.files_B) - 1)])else:image_B = Image.open(self.files_B[index % len(self.files_B)])# Convert grayscale images to rgbif image_A.mode != "RGB":image_A = to_rgb(image_A)if image_B.mode != "RGB":image_B = to_rgb(image_B)item_A = self.transform(image_A)item_B = self.transform(image_B)return {"A": item_A, "B": item_B}def __len__(self):return max(len(self.files_A), len(self.files_B))

models.py

import torch.nn as nn
import torch.nn.functional as F
import torchdef weights_init_normal(m):classname = m.__class__.__name__if classname.find("Conv") != -1:torch.nn.init.normal_(m.weight.data, 0.0, 0.02)if hasattr(m, "bias") and m.bias is not None:torch.nn.init.constant_(m.bias.data, 0.0)elif classname.find("BatchNorm2d") != -1:torch.nn.init.normal_(m.weight.data, 1.0, 0.02)torch.nn.init.constant_(m.bias.data, 0.0)##############################
#           RESNET
##############################class ResidualBlock(nn.Module):def __init__(self, in_features):super(ResidualBlock, self).__init__()self.block = nn.Sequential(nn.ReflectionPad2d(1),nn.Conv2d(in_features, in_features, 3),nn.InstanceNorm2d(in_features),nn.ReLU(inplace=True),nn.ReflectionPad2d(1),nn.Conv2d(in_features, in_features, 3),nn.InstanceNorm2d(in_features),)def forward(self, x):return x + self.block(x)class GeneratorResNet(nn.Module):def __init__(self, input_shape, num_residual_blocks):super(GeneratorResNet, self).__init__()channels = input_shape[0]# Initial convolution blockout_features = 64model = [nn.ReflectionPad2d(channels),nn.Conv2d(channels, out_features, 7),nn.InstanceNorm2d(out_features),nn.ReLU(inplace=True),]in_features = out_features# Downsamplingfor _ in range(2):out_features *= 2model += [nn.Conv2d(in_features, out_features, 3, stride=2, padding=1),nn.InstanceNorm2d(out_features),nn.ReLU(inplace=True),]in_features = out_features# Residual blocksfor _ in range(num_residual_blocks):model += [ResidualBlock(out_features)]# Upsamplingfor _ in range(2):out_features //= 2model += [nn.Upsample(scale_factor=2),nn.Conv2d(in_features, out_features, 3, stride=1, padding=1),nn.InstanceNorm2d(out_features),nn.ReLU(inplace=True),]in_features = out_features# Output layermodel += [nn.ReflectionPad2d(channels), nn.Conv2d(out_features, channels, 7), nn.Tanh()]self.model = nn.Sequential(*model)def forward(self, x):return self.model(x)##############################
#        Discriminator
##############################class Discriminator(nn.Module):def __init__(self, input_shape):super(Discriminator, self).__init__()channels, height, width = input_shape# Calculate output shape of image discriminator (PatchGAN)self.output_shape = (1, height // 2 ** 4, width // 2 ** 4)def discriminator_block(in_filters, out_filters, normalize=True):"""Returns downsampling layers of each discriminator block"""layers = [nn.Conv2d(in_filters, out_filters, 4, stride=2, padding=1)]if normalize:layers.append(nn.InstanceNorm2d(out_filters))layers.append(nn.LeakyReLU(0.2, inplace=True))return layersself.model = nn.Sequential(*discriminator_block(channels, 64, normalize=False),*discriminator_block(64, 128),*discriminator_block(128, 256),*discriminator_block(256, 512),nn.ZeroPad2d((1, 0, 1, 0)),nn.Conv2d(512, 1, 4, padding=1))def forward(self, img):return self.model(img)

utils.py

import random
import time
import datetime
import sysfrom torch.autograd import Variable
import torch
import numpy as npfrom torchvision.utils import save_imageclass ReplayBuffer:def __init__(self, max_size=50):assert max_size > 0, "Empty buffer or trying to create a black hole. Be careful."self.max_size = max_sizeself.data = []def push_and_pop(self, data):to_return = []for element in data.data:element = torch.unsqueeze(element, 0)if len(self.data) < self.max_size:self.data.append(element)to_return.append(element)else:if random.uniform(0, 1) > 0.5:i = random.randint(0, self.max_size - 1)to_return.append(self.data[i].clone())self.data[i] = elementelse:to_return.append(element)return Variable(torch.cat(to_return))class LambdaLR:def __init__(self, n_epochs, offset, decay_start_epoch):assert (n_epochs - decay_start_epoch) > 0, "Decay must start before the training session ends!"self.n_epochs = n_epochsself.offset = offsetself.decay_start_epoch = decay_start_epochdef step(self, epoch):return 1.0 - max(0, epoch + self.offset - self.decay_start_epoch) / (self.n_epochs - self.decay_start_epoch)

cyclegan.py

import argparse
import itertools
from torchvision.utils import save_image, make_grid
from torch.utils.data import DataLoader
from models import *
from datasets import *
from utils import *
import torchimport warnings
warnings.filterwarnings('ignore')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=4, help="number of epochs of training")
parser.add_argument("--dataset_name", type=str, default="monet2photo", 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=2, help="epoch from which to start lr decay")
parser.add_argument("--n_cpu", type=int, default=4, 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=100, help="interval between saving generator outputs")
parser.add_argument("--checkpoint_interval", type=int, default=1, help="interval between saving model checkpoints")
parser.add_argument("--n_residual_blocks", type=int, default=9, help="number of residual blocks in generator")
parser.add_argument("--lambda_cyc", type=float, default=10.0, help="cycle loss weight")
parser.add_argument("--lambda_id", type=float, default=5.0, help="identity loss weight")
opt = parser.parse_args()
print(opt)# Create sample and checkpoint directories
os.makedirs("images/%s" % opt.dataset_name, exist_ok=True)
os.makedirs("saved_models/%s" % opt.dataset_name, exist_ok=True)# Losses
criterion_GAN = torch.nn.MSELoss()
criterion_cycle = torch.nn.L1Loss()
criterion_identity = torch.nn.L1Loss()cuda = torch.cuda.is_available()input_shape = (opt.channels, opt.img_height, opt.img_width)# 初始化生成器鉴别器
G_AB = GeneratorResNet(input_shape, opt.n_residual_blocks)
G_BA = GeneratorResNet(input_shape, opt.n_residual_blocks)
D_A = Discriminator(input_shape)
D_B = Discriminator(input_shape)if cuda:G_AB = G_AB.cuda()G_BA = G_BA.cuda()D_A = D_A.cuda()D_B = D_B.cuda()criterion_GAN.cuda()criterion_cycle.cuda()criterion_identity.cuda()if opt.epoch != 0:# 加载预训练模型G_AB.load_state_dict(torch.load("saved_models/%s/G_AB_%d.pth" % (opt.dataset_name, opt.epoch)))G_BA.load_state_dict(torch.load("saved_models/%s/G_BA_%d.pth" % (opt.dataset_name, opt.epoch)))D_A.load_state_dict(torch.load("saved_models/%s/D_A_%d.pth" % (opt.dataset_name, opt.epoch)))D_B.load_state_dict(torch.load("saved_models/%s/D_B_%d.pth" % (opt.dataset_name, opt.epoch)))
else:# 初始化权重G_AB.apply(weights_init_normal)G_BA.apply(weights_init_normal)D_A.apply(weights_init_normal)D_B.apply(weights_init_normal)# Optimizers
optimizer_G = torch.optim.Adam(itertools.chain(G_AB.parameters(), G_BA.parameters()), lr=opt.lr, betas=(opt.b1, opt.b2)
)
optimizer_D_A = torch.optim.Adam(D_A.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2))
optimizer_D_B = torch.optim.Adam(D_B.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2))# Learning rate update schedulers
lr_scheduler_G = torch.optim.lr_scheduler.LambdaLR(optimizer_G, lr_lambda=LambdaLR(opt.n_epochs, opt.epoch, opt.decay_epoch).step
)
lr_scheduler_D_A = torch.optim.lr_scheduler.LambdaLR(optimizer_D_A, lr_lambda=LambdaLR(opt.n_epochs, opt.epoch, opt.decay_epoch).step
)
lr_scheduler_D_B = torch.optim.lr_scheduler.LambdaLR(optimizer_D_B, lr_lambda=LambdaLR(opt.n_epochs, opt.epoch, opt.decay_epoch).step
)Tensor = torch.cuda.FloatTensor if cuda else torch.Tensor# Buffers of previously generated samples
fake_A_buffer = ReplayBuffer()
fake_B_buffer = ReplayBuffer()# Image transformations
transforms_ = [transforms.Resize(int(opt.img_height * 1.12), Image.BICUBIC),transforms.RandomCrop((opt.img_height, opt.img_width)),transforms.RandomHorizontalFlip(),transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),
]# Training data loader
dataloader = DataLoader(ImageDataset("./data/%s/" % opt.dataset_name, transforms_=transforms_, unaligned=True),batch_size=opt.batch_size,shuffle=True,num_workers=opt.n_cpu,
)
# Test data loader
val_dataloader = DataLoader(ImageDataset("./data/%s/" % opt.dataset_name, transforms_=transforms_, unaligned=True, mode="test"),batch_size=5,shuffle=True,num_workers=1,
)def sample_images(batches_done):"""Saves a generated sample from the test set"""imgs = next(iter(val_dataloader))G_AB.eval()G_BA.eval()real_A = Variable(imgs["A"].type(Tensor))fake_B = G_AB(real_A)real_B = Variable(imgs["B"].type(Tensor))fake_A = G_BA(real_B)# Arange images along x-axisreal_A = make_grid(real_A, nrow=5, normalize=True)real_B = make_grid(real_B, nrow=5, normalize=True)fake_A = make_grid(fake_A, nrow=5, normalize=True)fake_B = make_grid(fake_B, nrow=5, normalize=True)# Arange images along y-axisimage_grid = torch.cat((real_A, fake_B, real_B, fake_A), 1)save_image(image_grid, "images/%s/%s.png" % (opt.dataset_name, batches_done), normalize=False)# ----------
#  Training
# ----------if __name__ == '__main__':prev_time = time.time()for epoch in range(opt.epoch, opt.n_epochs):for i, batch in enumerate(dataloader):# Set model inputreal_A = Variable(batch["A"].type(Tensor))real_B = Variable(batch["B"].type(Tensor))# Adversarial ground truthsvalid = Variable(Tensor(np.ones((real_A.size(0), *D_A.output_shape))), requires_grad=False)fake  = Variable(Tensor(np.zeros((real_A.size(0), *D_A.output_shape))), requires_grad=False)# ------------------#  Train Generators# ------------------G_AB.train()G_BA.train()optimizer_G.zero_grad()# Identity lossloss_id_A = criterion_identity(G_BA(real_A), real_A)loss_id_B = criterion_identity(G_AB(real_B), real_B)loss_identity = (loss_id_A + loss_id_B) / 2# GAN lossfake_B = G_AB(real_A)loss_GAN_AB = criterion_GAN(D_B(fake_B), valid)fake_A = G_BA(real_B)loss_GAN_BA = criterion_GAN(D_A(fake_A), valid)loss_GAN = (loss_GAN_AB + loss_GAN_BA) / 2# Cycle lossrecov_A = G_BA(fake_B)loss_cycle_A = criterion_cycle(recov_A, real_A)recov_B = G_AB(fake_A)loss_cycle_B = criterion_cycle(recov_B, real_B)loss_cycle = (loss_cycle_A + loss_cycle_B) / 2# Total lossloss_G = loss_GAN + opt.lambda_cyc * loss_cycle + opt.lambda_id * loss_identityloss_G.backward()optimizer_G.step()# -----------------------#  Train Discriminator A# -----------------------optimizer_D_A.zero_grad()# Real lossloss_real = criterion_GAN(D_A(real_A), valid)# Fake loss (on batch of previously generated samples)fake_A_ = fake_A_buffer.push_and_pop(fake_A)loss_fake = criterion_GAN(D_A(fake_A_.detach()), fake)# Total lossloss_D_A = (loss_real + loss_fake) / 2loss_D_A.backward()optimizer_D_A.step()# -----------------------#  Train Discriminator B# -----------------------optimizer_D_B.zero_grad()# Real lossloss_real = criterion_GAN(D_B(real_B), valid)# Fake loss (on batch of previously generated samples)fake_B_ = fake_B_buffer.push_and_pop(fake_B)loss_fake = criterion_GAN(D_B(fake_B_.detach()), fake)# Total lossloss_D_B = (loss_real + loss_fake) / 2loss_D_B.backward()optimizer_D_B.step()loss_D = (loss_D_A + loss_D_B) / 2# --------------#  Log Progress# --------------# Determine approximate time leftbatches_done = epoch * len(dataloader) + ibatches_left = opt.n_epochs * len(dataloader) - batches_donetime_left = datetime.timedelta(seconds=batches_left * (time.time() - prev_time))prev_time = time.time()# Print logsys.stdout.write("\r[Epoch %d/%d] [Batch %d/%d] [D loss: %f] [G loss: %f, adv: %f, cycle: %f, identity: %f] ETA: %s"% (epoch,opt.n_epochs,i,len(dataloader),loss_D.item(),loss_G.item(),loss_GAN.item(),loss_cycle.item(),loss_identity.item(),time_left,))# If at sample interval save imageif batches_done % opt.sample_interval == 0:sample_images(batches_done)# Update learning rateslr_scheduler_G.step()lr_scheduler_D_A.step()lr_scheduler_D_B.step()if opt.checkpoint_interval != -1 and epoch % opt.checkpoint_interval == 0:# Save model checkpointstorch.save(G_AB.state_dict(), "saved_models/%s/G_AB_%d.pth" % (opt.dataset_name, epoch))torch.save(G_BA.state_dict(), "saved_models/%s/G_BA_%d.pth" % (opt.dataset_name, epoch))torch.save(D_A.state_dict(), "saved_models/%s/D_A_%d.pth" % (opt.dataset_name, epoch))torch.save(D_B.state_dict(), "saved_models/%s/D_B_%d.pth" % (opt.dataset_name, epoch))

PS:该工程项目运行需根据自己的电脑配置或者服务器配置设置cyclegan.py中对应参数,如:

n_epochs(200→4)、decay_epoch(100→2)、n_cpu(8→4)

部分训练结果:

3. 总结

        CycleGAN的一个重要应用领域是Domain Adaptation,可以把一张普通的风景照变化成梵高化作,CycleGAN 由左右两个 GAN 网络组成 G(AB) 负责把 A 类物体 (斑马) 转换成 B 类物体 (正常的马). G(BA) 负责把 B 类物体 (正常的马) 还原成 A 类物体 (斑马),如下图所示。

三、理论基础

1. CycleGAN的原理结构

        CycleGAN(循环生成对抗网络)是一种生成对抗网络(GAN),它能够在没有成对训练样本的情况下,将一个域(比如照片中的马)转换成另一个域(比如照片中的斑马)。CycleGAN 主要由两部分组成:两个生成器和一个判别器。生成器的作用是在两个域之间进行转换,而判别器则用于判断输入的图像是真实的还是由生成器生成的。

1.1. 生成器(Generator)
CycleGAN 包含两个生成器,一个用于将图像从域A转换到域B,另一个则用于将图像从域B转换回域A。每个生成器都是一个神经网络,通常采用卷积神经网络(CNN)的结构。生成器的目标是学习如何将输入图像转换成目标域中的图像,同时欺骗判别器,使其认为生成的图像是真实的。

1.2. 判别器(Discriminator)
与生成器相对应,CycleGAN 也有两个判别器,一个用于判断图像是否属于域A,另一个用于判断图像是否属于域B。判别器同样通常采用卷积神经网络结构,其目标是能够准确地区分真实图像和由生成器生成的图像。

1.3. 循环一致性损失(Cycle Consistency Loss)
为了确保在没有成对训练样本的情况下,生成器能够学习到有效的映射,CycleGAN 引入了循环一致性损失。这个损失函数确保当图像从域A转换到域B,然后再转换回域A时,得到的图像与原始图像尽可能相似。同样地,从域B转换到域A,再转换回域B也应该保持循环一致性。

1.4. 对抗损失(Adversarial Loss)
对抗损失是GAN的核心,它确保生成器能够生成足以欺骗判别器的图像。对于CycleGAN,每个生成器都需要最小化对抗损失,使其生成的图像能够在相应的判别器上获得高分。

1.5. identity损失(Identity Loss)
除了上述两种损失函数,CycleGAN 还引入了identity损失,以确保当输入图像已经属于目标域时,生成器能够返回原始图像。这有助于保持生成器在训练过程中的稳定性,并防止过度拟合。

1.6.训练过程:
在训练过程中,CycleGAN 通过不断调整生成器和判别器的参数来最小化上述损失函数。生成器尝试生成越来越能欺骗判别器的图像,而判别器则尝试越来越准确地识别真实图像和生成图像。通过这种对抗过程,生成器最终能够学习到如何在两个域之间进行有效的转换。

1.7.应用:
CycleGAN 在计算机视觉领域有广泛的应用,如风格迁移、季节变换、照片增强等,它为那些没有成对训练数据的图像转换任务提供了一种有效的解决方案。

2.CycleGAN和传统GAN的对比

        CycleGAN与普通GAN相比,有几个特殊之处,这些特性使得CycleGAN适合于图像到图像的转换任务,尤其是在没有成对训练数据的情况下:

2.1.无配对数据要求:
普通GAN通常需要成对的训练数据,即每个输入图像都有一个对应的输出图像。而CycleGAN不需要这样的成对数据,它可以学习一个域(比如照片)到另一个域(比如画作)的转换,即使没有直接的成对映射。
2.2.循环一致性损失:
CycleGAN引入了循环一致性损失(Cycle Consistency Loss),这是其核心的创新之一。这个损失函数确保当图像从源域转换到目标域,然后再转换回源域时,能够尽可能地恢复到原始图像。这样的循环保证了即使在没有成对数据的情况下,转换过程也是合理的。
2.3.两个生成器和两个判别器:
CycleGAN包含两个生成器,每个生成器负责一个方向的转换(从域A到域B和从域B到域A)。同时,也有两个判别器,分别用于判断图像是否属于域A或域B。这种结构使得CycleGAN能够同时学习两个域之间的映射。
2.4.对抗性损失和身份损失:
除了循环一致性损失,CycleGAN还结合了对抗性损失和身份损失。对抗性损失确保生成器能够生成足以欺骗判别器的图像,而身份损失确保当输入图像已经属于目标域时,生成器能够返回原始图像,这有助于保持生成器的稳定性。
2.5.多样化的应用场景:
由于不需要成对数据,CycleGAN可以应用于多种不同的图像到图像的转换任务,如风格迁移、季节变换、艺术作品风格化等,而这些任务在普通GAN中很难实现。
2.6.更强的泛化能力:
由于循环一致性损失的设计,CycleGAN在训练过程中学习到了更加泛化的特征表示,这使得它在面对未见过的数据时,也能表现出较好的转换效果。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com