3.CycleGAN——循环生成对抗网络(一个把马变成斑马的网络)

今天我们学习的模型是CycleGAN,到目前为止我们需要先熟悉部分的模型,对应内部的算法和运行逻辑我并没有进行学习,大致只知道这个模型的部分结构并且这个网络在这个章节中是干什么的。对于本书的编辑作者也是想要我们想了解部分模型,并对模型产生兴趣后面的章节在进行深度的学习并了解模型的搭建。

本篇文章我们看到的是一个把马变成斑马的网络。该网络学习了一匹或多匹马的图像,从而在你输入一张图片的时候,它可以将他们全部变成斑马,图像的其余部分尽可能的不被修改。接下来的部分我们来看一下这个到底是怎么具体实现的。

  • 首先我们建立一个模型 
netG = ResNetGenerator()

 这个模型虽然已经被建立,但它包含的是随机权重。而这个模型已经有着被训练的权重,文件名为‘horse2zebra_0.4.0.pth’,也就是已经被训练过的模型。

  • 加载文件并使用load_state_dict()加载模型
model_path = './dict/horse2zebra_0.4.0.pth'
model_data = torch.load(model_path) # 转化为张量
netG.load_state_dict(model_data)

同样,上节我们也提到到eval模式,就像对resnet101所作的那样。

# 切换模型到评估模式
netG.eval()
  • 预处理操作 
from torchvision import transforms

# 定义预处理操作,包括调整大小和转换为张量
preprocess = transforms.Compose([transforms.Resize(256),
                                 transforms.ToTensor()])
  • 加载和预处理图像 
import torch
from PIL import Image

# 加载和预处理图像
img = Image.open('./pic/horse.jpg')
img_t = preprocess(img)
batch_t = torch.unsqueeze(img_t, dim=0)
  • 模型推理 
# 执行模型推理
batch_out = netG(batch_t)
  • 处理输出,转化为图片并显示 
from torchvision import transforms

out_t = (batch_out.data.squeeze() + 1.0) / 2.0
out_img = transforms.ToPILImage()(out_t)
# out_img.save('./zebra.jpg')    # 对文件进行保存
out_img.show()    # 展示图片

 其中还有对ResNetBlock进行定义的类,具体的实现我目前也不清楚,需要等到后面的章节原书有着相应的讲解,现在我们只需要了解建立模型和使用模型大致需要几个步骤就行了。

  • 相关的代码如下 
# 定义ResNetBlock类,继承自nn.Module
class ResNetBlock(nn.Module):
    def __init__(self, dim):
        """
        初始化ResNetBlock
        :param dim: 卷积层的输入和输出通道数
        """
        super(ResNetBlock, self).__init__()
        self.conv_block = self.build_conv_block(dim)  # 构建卷积块

    def build_conv_block(self, dim):
        """
        构建一个卷积块
        :param dim: 卷积层的输入和输出通道数
        :return: nn.Sequential包含多个卷积层的顺序容器
        """
        conv_block = []

        # 添加反射填充层
        conv_block += [nn.ReflectionPad2d(1)]

        # 添加卷积层、实例归一化层和ReLU激活函数
        conv_block += [nn.Conv2d(dim, dim, kernel_size=3, padding=0, bias=True),
                       nn.InstanceNorm2d(dim),
                       nn.ReLU(True)]

        # 再次添加反射填充层
        conv_block += [nn.ReflectionPad2d(1)]

        # 再次添加卷积层和实例归一化层
        conv_block += [nn.Conv2d(dim, dim, kernel_size=3, padding=0, bias=True),
                       nn.InstanceNorm2d(dim)]

        # 使用nn.Sequential将层组合成一个卷积块
        return nn.Sequential(*conv_block)

    def forward(self, x):
        """
        前向传播函数
        :param x: 输入张量
        :return: 加上输入张量的卷积块输出
        """
        out = x + self.conv_block(x)  # 跳跃连接
        return out

# 定义ResNetGenerator类,继承自nn.Module
class ResNetGenerator(nn.Module):

    def __init__(self, input_nc=3, output_nc=3, ngf=64, n_blocks=9):  # <3>
        """
        初始化ResNetGenerator
        :param input_nc: 输入图像的通道数
        :param output_nc: 输出图像的通道数
        :param ngf: 第一层卷积层的过滤器数量
        :param n_blocks: ResNetBlock的数量
        """
        assert(n_blocks >= 0)
        super(ResNetGenerator, self).__init__()

        self.input_nc = input_nc
        self.output_nc = output_nc
        self.ngf = ngf

        # 构建模型结构
        model = [nn.ReflectionPad2d(3),
                 nn.Conv2d(input_nc, ngf, kernel_size=7, padding=0, bias=True),
                 nn.InstanceNorm2d(ngf),
                 nn.ReLU(True)]

        n_downsampling = 2
        mult = 2**n_downsampling

        # 添加下采样层
        for i in range(n_downsampling):
            mult = 2**i
            model += [nn.Conv2d(ngf * mult, ngf * mult * 2, kernel_size=3, stride=2, padding=1, bias=True),
                      nn.InstanceNorm2d(ngf * mult * 2),
                      nn.ReLU(True)]

        mult = 2**n_downsampling

        # 添加ResNet Block
        for i in range(n_blocks):
            model += [ResNetBlock(ngf * mult)]

        # 添加上采样层
        for i in range(n_downsampling):
            mult = 2**(n_downsampling - i)
            model += [nn.ConvTranspose2d(ngf * mult, int(ngf * mult / 2),
                                         kernel_size=3, stride=2,
                                         padding=1, output_padding=1,
                                         bias=True),
                      nn.InstanceNorm2d(int(ngf * mult / 2)),
                      nn.ReLU(True)]

        model += [nn.ReflectionPad2d(3)]
        model += [nn.Conv2d(ngf, output_nc, kernel_size=7, padding=0)]
        model += [nn.Tanh()]

        self.model = nn.Sequential(*model)

    def forward(self, input): 
        """
        前向传播函数
        :param input: 输入张量
        :return: 输出张量
        """
        return self.model(input)

本文总体代码如下:

import torch
import torch.nn as nn
from PIL import Image
from torchvision import transforms

# 定义ResNetBlock类,继承自nn.Module
class ResNetBlock(nn.Module):
    def __init__(self, dim):
        """
        初始化ResNetBlock
        :param dim: 卷积层的输入和输出通道数
        """
        super(ResNetBlock, self).__init__()
        self.conv_block = self.build_conv_block(dim)  # 构建卷积块

    def build_conv_block(self, dim):
        """
        构建一个卷积块
        :param dim: 卷积层的输入和输出通道数
        :return: nn.Sequential包含多个卷积层的顺序容器
        """
        conv_block = []

        # 添加反射填充层
        conv_block += [nn.ReflectionPad2d(1)]

        # 添加卷积层、实例归一化层和ReLU激活函数
        conv_block += [nn.Conv2d(dim, dim, kernel_size=3, padding=0, bias=True),
                       nn.InstanceNorm2d(dim),
                       nn.ReLU(True)]

        # 再次添加反射填充层
        conv_block += [nn.ReflectionPad2d(1)]

        # 再次添加卷积层和实例归一化层
        conv_block += [nn.Conv2d(dim, dim, kernel_size=3, padding=0, bias=True),
                       nn.InstanceNorm2d(dim)]

        # 使用nn.Sequential将层组合成一个卷积块
        return nn.Sequential(*conv_block)

    def forward(self, x):
        """
        前向传播函数
        :param x: 输入张量
        :return: 加上输入张量的卷积块输出
        """
        out = x + self.conv_block(x)  # 跳跃连接
        return out

# 定义ResNetGenerator类,继承自nn.Module
class ResNetGenerator(nn.Module):

    def __init__(self, input_nc=3, output_nc=3, ngf=64, n_blocks=9):  # <3>
        """
        初始化ResNetGenerator
        :param input_nc: 输入图像的通道数
        :param output_nc: 输出图像的通道数
        :param ngf: 第一层卷积层的过滤器数量
        :param n_blocks: ResNetBlock的数量
        """
        assert(n_blocks >= 0)
        super(ResNetGenerator, self).__init__()

        self.input_nc = input_nc
        self.output_nc = output_nc
        self.ngf = ngf

        # 构建模型结构
        model = [nn.ReflectionPad2d(3),
                 nn.Conv2d(input_nc, ngf, kernel_size=7, padding=0, bias=True),
                 nn.InstanceNorm2d(ngf),
                 nn.ReLU(True)]

        n_downsampling = 2
        mult = 2**n_downsampling

        # 添加下采样层
        for i in range(n_downsampling):
            mult = 2**i
            model += [nn.Conv2d(ngf * mult, ngf * mult * 2, kernel_size=3, stride=2, padding=1, bias=True),
                      nn.InstanceNorm2d(ngf * mult * 2),
                      nn.ReLU(True)]

        mult = 2**n_downsampling

        # 添加ResNet Block
        for i in range(n_blocks):
            model += [ResNetBlock(ngf * mult)]

        # 添加上采样层
        for i in range(n_downsampling):
            mult = 2**(n_downsampling - i)
            model += [nn.ConvTranspose2d(ngf * mult, int(ngf * mult / 2),
                                         kernel_size=3, stride=2,
                                         padding=1, output_padding=1,
                                         bias=True),
                      nn.InstanceNorm2d(int(ngf * mult / 2)),
                      nn.ReLU(True)]

        model += [nn.ReflectionPad2d(3)]
        model += [nn.Conv2d(ngf, output_nc, kernel_size=7, padding=0)]
        model += [nn.Tanh()]

        self.model = nn.Sequential(*model)

    def forward(self, input): 
        """
        前向传播函数
        :param input: 输入张量
        :return: 输出张量
        """
        return self.model(input)

# 加载模型权重
netG = ResNetGenerator()
model_path = './dict/horse2zebra_0.4.0.pth'
model_data = torch.load(model_path)
netG.load_state_dict(model_data)

# 切换模型到评估模式
netG.eval()

# 定义预处理操作,包括调整大小和转换为张量
preprocess = transforms.Compose([transforms.Resize(256),
                                 transforms.ToTensor()])

# 加载和预处理图像
img = Image.open('./pic/horse.jpg')
img_t = preprocess(img)
batch_t = torch.unsqueeze(img_t, dim=0)

# 执行模型推理
batch_out = netG(batch_t)

# 处理输出,转换为图像并显示
out_t = (batch_out.data.squeeze() + 1.0) / 2.0
out_img = transforms.ToPILImage()(out_t)
# out_img.save('./data/pic2/zebra.jpg')
out_img.show()

 

 

 

 

 

### 回答1: GAN(Generative Adversarial Network)是一种深度学习模型,在许多任务中都有广泛应用。在 GAN 中,有一个生成器和一个判别器。生成器尝试生成与真实数据类似的新数据,判别器则尝试区分生成的数据与真实数据。生成器和判别器通过对抗的方式共同训练。 Matlab-GAN 是一种基于 Matlab 的 GAN 实现,可以实现生成图片,视频等任务。在 Matlab-GAN 中,可以使用不同的损失函数和正则化技术,来改善生成的质量和稳定性。 除了 GAN,Pixel2Pixel 和 CycleGAN 也是常用的深度学习模型,在计算机视觉任务中具有重要的应用。Pixel2Pixel 是一种基于卷积神经网络的图像翻译模型,可以将一个图像转换为另一个图像,如将黑白图像转换为彩色图像。CycleGAN 是一种无需成对匹配的图像转换模型,可以用于跨域图像转换,如将的图像转换为斑马的图像。 Matlab-GAN 支持 Pixel2Pixel 和 CycleGAN 的实现,可以帮助更方便地进行图像转换任务。Pixel2Pixel 和 CycleGAN 也可以与 GAN 结合使用,产生更高质量、更可控的生成结果。 总之,Matlab-GAN 是一种实现生成对抗网络的工具,支持不同类型的 GAN 和深度学习模型,可以实现图像、视频等多种任务。Pixel2Pixel 和 CycleGAN 作为深度学习模型中常用的工具,可以帮助更好地完成图像转换任务。 ### 回答2: GAN,即生成对抗网络,是近年来流行的一种机器学习算法模型,它可以通过两个深度神经网络模型(生成器和判别器)来生成具有类似于真实图像的虚拟图像。 在Matlab中,GAN也有自己的实现——matlab-gan。该实现提供了一系列的GAN示例,如最基础的MNIST手写数字图像生成、使用DCGAN和Wasserstein GAN生成图像,甚至还提供了Pix2Pix和CycleGAN,让用户能够在MATLAB环境中成功加载这些GAN应用。 Pix2Pix是基于条件对抗网络(CGAN)的扩展,它可以将给定的输入图像转换为输出图像。例如,它可以将黑白照片转换成彩色照片,或将景象翻译成抽象画作。该示例合成城市街景并将它们转换为艺术风格的图像。 CycleGAN是一种通用的无监督图像到图像转换器,它可以将两个域之间的图像转换成另一个域。例如,它可以将的图像转换成斑马的图像。CycleGAN在图像风格转换、模型综合、目标转换等方面表现出色,是GAN的重要变种。 总体来说,matlab-gan一个适合于GAN初学者的绝佳平台。它不仅提供了简单的GAN实现,还包括两个复杂的GAN变种——Pix2Pix和CycleGAN。这些示例不仅能够教授GAN的基础理论,还能够为研究者提供一个练习环境来测试并扩展这些算法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值