学会CycleGAN进行风格迁移,实现自定义滤镜

output_channels: Output channels

norm_type: Type of normalization. Either ‘batchnorm’ or ‘instancenorm’.

Returns:

Generator model

“”"

down_stack = [

downsample(64, 4, norm_type, apply_norm=False), # (bs, 128, 128, 64)

downsample(128, 4, norm_type), # (bs, 64, 64, 128)

downsample(256, 4, norm_type), # (bs, 32, 32, 256)

downsample(512, 4, norm_type), # (bs, 16, 16, 512)

downsample(512, 4, norm_type), # (bs, 8, 8, 512)

downsample(512, 4, norm_type), # (bs, 4, 4, 512)

downsample(512, 4, norm_type), # (bs, 2, 2, 512)

downsample(512, 4, norm_type), # (bs, 1, 1, 512)

]

up_stack = [

upsample(512, 4, norm_type, apply_dropout=True), # (bs, 2, 2, 1024)

upsample(512, 4, norm_type, apply_dropout=True), # (bs, 4, 4, 1024)

upsample(512, 4, norm_type, apply_dropout=True), # (bs, 8, 8, 1024)

upsample(512, 4, norm_type), # (bs, 16, 16, 1024)

upsample(256, 4, norm_type), # (bs, 32, 32, 512)

upsample(128, 4, norm_type), # (bs, 64, 64, 256)

upsample(64, 4, norm_type), # (bs, 128, 128, 128)

]

initializer = tf.random_normal_initializer(0., 0.02)

last = tf.keras.layers.Conv2DTranspose(

output_channels, 4, strides=2,

padding=‘same’, kernel_initializer=initializer,

activation=‘tanh’) # (bs, 256, 256, 3)

concat = tf.keras.layers.Concatenate()

inputs = tf.keras.layers.Input(shape=[None, None, 3])

x = inputs

Downsampling through the model

skips = []

for down in down_stack:

x = down(x)

skips.append(x)

skips = reversed(skips[:-1])

Upsampling and establishing the skip connections

for up, skip in zip(up_stack, skips):

x = up(x)

x = concat([x, skip])

x = last(x)

return tf.keras.Model(inputs=inputs, outputs=x)

def discriminator(norm_type=‘batchnorm’, target=True):

“”"

Args:

norm_type: Type of normalization. Either ‘batchnorm’ or ‘instancenorm’.

target: Bool, indicating whether target image is an input or not.

Returns:

Discriminator model

“”"

initializer = tf.random_normal_initializer(0., 0.02)

inp = tf.keras.layers.Input(shape=[None, None, 3], name=‘input_image’)

x = inp

if target:

tar = tf.keras.layers.Input(shape=[None, None, 3], name=‘target_image’)

x = tf.keras.layers.concatenate([inp, tar]) # (bs, 256, 256, channels*2)

down1 = downsample(64, 4, norm_type, False)(x) # (bs, 128, 128, 64)

down2 = downsample(128, 4, norm_type)(down1) # (bs, 64, 64, 128)

down3 = downsample(256, 4, norm_type)(down2) # (bs, 32, 32, 256)

zero_pad1 = tf.keras.layers.ZeroPadding2D()(down3) # (bs, 34, 34, 256)

conv = tf.keras.layers.Conv2D(

512, 4, strides=1, kernel_initializer=initializer,

use_bias=False)(zero_pad1) # (bs, 31, 31, 512)

if norm_type.lower() == ‘batchnorm’:

norm1 = tf.keras.layers.BatchNormalization()(conv)

elif norm_type.lower() == ‘instancenorm’:

norm1 = InstanceNormalization()(conv)

leaky_relu = tf.keras.layers.LeakyReLU()(norm1)

zero_pad2 = tf.keras.layers.ZeroPadding2D()(leaky_relu) # (bs, 33, 33, 512)

last = tf.keras.layers.Conv2D(

1, 4, strides=1,

kernel_initializer=initializer)(zero_pad2) # (bs, 30, 30, 1)

if target:

return tf.keras.Model(inputs=[inp, tar], outputs=last)

else:

return tf.keras.Model(inputs=inp, outputs=last)

损失函数

LAMBDA = 10

loss_obj = tf.keras.losses.BinaryCrossentropy(from_logits=True)

def discriminator_loss(real, generated):

real_loss = loss_obj(tf.ones_like(real), real)

generated_loss = loss_obj(tf.zeros_like(generated), generated)

total_disc_loss = real_loss + generated_loss

return total_disc_loss * 0.5

def generator_loss(generated):

return loss_obj(tf.ones_like(generated), generated)

def calc_cycle_loss(real_image, cycled_image):

loss1 = tf.reduce_mean(tf.abs(real_image - cycled_image))

return LAMBDA * loss1

def identity_loss(real_image, same_image):

loss = tf.reduce_mean(tf.abs(real_image - same_image))

return LAMBDA * 0.5 * loss

训练结果可视化函数

def generate_images(model, test_input):

prediction = model(test_input)

plt.figure(figsize=(12, 12))

display_list = [test_input[0], prediction[0]]

title = [‘Input Image’, ‘Predicted Image’]

for i in range(2):

plt.subplot(1, 2, i+1)

plt.title(title[i])

getting the pixel values between [0, 1] to plot it.

plt.imshow(display_list[i] * 0.5 + 0.5)

plt.axis(‘off’)

plt.show()

plt.savefig(‘results/{}.png’.format(time.time()))

训练步骤

首先实例化模型:

generator_g = unet_generator(OUTPUT_CHANNELS, norm_type=‘instancenorm’)

generator_f = unet_generator(OUTPUT_CHANNELS, norm_type=‘instancenorm’)

discriminator_x = discriminator(norm_type=‘instancenorm’, target=False)

discriminator_y = discriminator(norm_type=‘instancenorm’, target=False)

实例化优化器:

generator_g_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.5)

generator_f_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.5)

discriminator_x_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.5)

discriminator_y_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.5)

checkpoint_path = “./checkpoints/vangogh2photo_train”

使用 tf.GradientTape 自定义训练过程:

@tf.function

def train_step(real_x, real_y):

persistent is set to True because the tape is used more than

once to calculate the gradients.

with tf.GradientTape(persistent=True) as tape:

Generator G translates X -> Y

Generator F translates Y -> X.

fake_y = generator_g(real_x, training=True)

cycled_x = generator_f(fake_y, training=True)

fake_x = generator_f(real_y, training=True)

cycled_y = generator_g(fake_x, training=True)

same_x and same_y are used for identity loss.

same_x = generator_f(real_x, training=True)

same_y = generator_g(real_y, training=True)

disc_real_x = discriminator_x(real_x, training=True)

disc_real_y = discriminator_y(real_y, training=True)

disc_fake_x = discriminator_x(fake_x, training=True)

disc_fake_y = discriminator_y(fake_y, training=True)

calculate the loss

gen_g_loss = generator_loss(disc_fake_y)

gen_f_loss = generator_loss(disc_fake_x)

total_cycle_loss = calc_cycle_loss(real_x, cycled_x) + calc_cycle_loss(real_y, cycled_y)

Total generator loss = adversarial loss + cycle loss

total_gen_g_loss = gen_g_loss + total_cycle_loss + identity_loss(real_y, same_y)

total_gen_f_loss = gen_f_loss + total_cycle_loss + identity_loss(real_x, same_x)

disc_x_loss = discriminator_loss(disc_real_x, disc_fake_x)

disc_y_loss = discriminator_loss(disc_real_y, disc_fake_y)

Calculate the gradients for generator and discriminator

generator_g_gradients = tape.gradient(total_gen_g_loss,

generator_g.trainable_variables)

generator_f_gradients = tape.gradient(total_gen_f_loss,

generator_f.trainable_variables)

discriminator_x_gradients = tape.gradient(disc_x_loss,

discriminator_x.trainable_variables)

discriminator_y_gradients = tape.gradient(disc_y_loss,

最后

Python崛起并且风靡,因为优点多、应用领域广、被大牛们认可。学习 Python 门槛很低,但它的晋级路线很多,通过它你能进入机器学习、数据挖掘、大数据,CS等更加高级的领域。Python可以做网络应用,可以做科学计算,数据分析,可以做网络爬虫,可以做机器学习、自然语言处理、可以写游戏、可以做桌面应用…Python可以做的很多,你需要学好基础,再选择明确的方向。这里给大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!

👉Python所有方向的学习路线👈

Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。

👉Python必备开发工具👈

工欲善其事必先利其器。学习Python常用的开发软件都在这里了,给大家节省了很多时间。

👉Python全套学习视频👈

我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了。

👉实战案例👈

学python就与学数学一样,是不能只看书不做题的,直接看步骤和答案会让人误以为自己全都掌握了,但是碰到生题的时候还是会一筹莫展。

因此在学习python的过程中一定要记得多动手写代码,教程只需要看一两遍即可。

👉大厂面试真题👈

我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Python爬虫全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注:python)
img

面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Python爬虫全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注:python)
[外链图片转存中…(img-2Ach0U4N-1710905465902)]

  • 17
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: CycleGAN是一种无监督的图像风格转换工具,可以将一个领域的图像转换成另一个领域的图像,例如将马的图片转换成斑马的图片,或将日本画转换成现实照片等。 为了训练CycleGAN,需要先准备两个数据集,例如A和B,分别代表两种不同的领域。接着,需要编写一个Python脚本进行训练。以下是一份基本的CycleGAN训练代码: ``` import torch import torch.nn as nn import torch.optim as optim import torchvision import torchvision.transforms as transforms from torch.utils.data import DataLoader from torchvision.datasets import ImageFolder from cyclegan import Generator, Discriminator, cycle_loss # Set device (CPU/GPU) device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") # Define hyperparameters lr = 0.0002 epochs = 200 batch_size = 1 # Define dataset transform = transforms.Compose([transforms.Resize(256), transforms.RandomCrop(256), transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]) dataset_A = ImageFolder(root="./datasets/horses/trainA", transform=transform) dataset_B = ImageFolder(root="./datasets/zebras/trainB", transform=transform) dataloader_A = DataLoader(dataset_A, batch_size=batch_size, shuffle=True) dataloader_B = DataLoader(dataset_B, batch_size=batch_size, shuffle=True) # Initialize generators and discriminators G_AtoB = Generator(3, 3).to(device) G_BtoA = Generator(3, 3).to(device) D_A = Discriminator(3).to(device) D_B = Discriminator(3).to(device) # Define loss function and optimizers MSE_Loss = nn.MSELoss() L1_Loss = nn.L1Loss() G_optimizer = optim.Adam(list(G_AtoB.parameters()) + list(G_BtoA.parameters()), lr=lr, betas=(0.5, 0.999)) D_optimizer = optim.Adam(list(D_A.parameters()) + list(D_B.parameters()), lr=lr, betas=(0.5, 0.999)) # Begin training for epoch in range(epochs): for i, (real_A, real_B) in enumerate(zip(dataloader_A, dataloader_B)): # Move tensors to device real_A = real_A[0].to(device) real_B = real_B[0].to(device) # Train generators G_AtoB.zero_grad() G_BtoA.zero_grad() fake_B = G_AtoB(real_A) cycle_A = G_BtoA(fake_B) fake_A = G_BtoA(real_B) cycle_B = G_AtoB(fake_A) D_fake_A = D_A(fake_A) D_fake_B = D_B(fake_B) G_loss = cycle_loss(MSE_Loss, L1_Loss, G_AtoB, G_BtoA, D_A, D_B, real_A, real_B, fake_A, fake_B, cycle_A, cycle_B) G_loss.backward() G_optimizer.step() # Train discriminators D_A.zero_grad() D_B.zero_grad() D_real_A = D_A(real_A) D_real_B = D_B(real_B) D_fake_A = D_A(fake_A.detach()) D_fake_B = D_B(fake_B.detach()) D_A_loss = (MSE_Loss(D_real_A, torch.ones_like(D_real_A)) + MSE_Loss(D_fake_A, torch.zeros_like(D_fake_A))) / 2 D_B_loss = (MSE_Loss(D_real_B, torch.ones_like(D_real_B)) + MSE_Loss(D_fake_B, torch.zeros_like(D_fake_B))) / 2 D_A_loss.backward() D_B_loss.backward() D_optimizer.step() print("Epoch [{}/{}]: G_loss {:.4f} D_A_loss {:.4f} D_B_loss {:.4f}".format(epoch + 1, epochs, G_loss.item(), D_A_loss.item(), D_B_loss.item())) # Save models torch.save(G_AtoB.state_dict(), "./saved_models/G_AtoB.pth") torch.save(G_BtoA.state_dict(), "./saved_models/G_BtoA.pth") ``` 上述代码中,`cyclegan.py`是自定义CycleGAN类文件,其中包含了`Generator`、`Discriminator`和`cycle_loss`等API。在进一步理解CycleGAN的原理后,可以通过修改训练超参数、调整模型架构或增加其他数据增强方式等方法,改进模型性能和训练效率。 ### 回答2: CycleGAN是一种GAN模型,可以用于图像风格迁移。在使用CycleGAN进行风格迁移训练之前,需要准备两组数据,一组是原始的图像数据,另一组是目标风格的图像数据。这两组数据应该包含相同的主题或对象,并且分别属于两种不同的风格。 接下来,需要编写CycleGAN的训练代码。在训练代码中,需要定义GAN的网络结构和优化器,并设置超参数。例如,CycleGAN需要定义两个生成器和两个判别器,每个生成器接受一组数据并生成一组与目标风格相匹配的数据,每个判别器用于判断生成的数据是否与目标风格相匹配。 训练代码中的超参数包括批量大小、学习率、迭代次数等。这些参数需要根据具体的应用场景进行调整。例如,在迭代次数方面,通常需要进行多轮迭代才能得到较好的结果。在每轮迭代中,需要计算生成器和判别器的损失,并根据损失更新网络中的参数。 当训练完成后,需要将测试图像输入模型并生成新的图像。这些新的图像应该具有与目标风格相似的外观和特征。同时,需要对生成的图像进行评估和调整,进一步提高模型的性能和效果。 总之,使用CycleGAN进行风格迁移的训练代码需要在GAN的网络结构、超参数和训练过程中进行合理的调整和设置,以实现较好的结果。 ### 回答3: CycleGAN是一种用于图像风格迁移的神经网络模型,可将一种领域的图像转换为另一种领域的图像,例如将马的图像转换为斑马的图像或将日落的图像转换为日出的图像。 要使用CycleGAN进行风格迁移训练,首先需要准备两个数据集,分别代表两个领域的图像。然后,需要编写代码来定义模型的结构和训练过程。 在模型定义方面,CycleGAN包括两个生成器网络和两个判别器网络。生成器将一个领域的图像转换为另一个领域的图像,判别器则负责区分生成图像与真实图像的差异。 在训练过程中,会通过交替优化生成器和判别器的损失来训练模型。生成器的损失包括重建损失和对抗损失,而判别器的损失包括真实图像与生成图像之间的损失。 最后,一旦模型训练完成,就可以使用它将任意领域的图像转换为目标领域的图像。 总之,使用CycleGAN进行风格迁移需要编写复杂的代码来定义模型和训练过程,但它是一种非常强大和灵活的工具,可以让我们轻松地将图像从一种领域转换为另一种领域。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值