paddle U-GAT-IT论文复现(心得):代码实现

用paddle框架复现论文

对于代码实现,通常来说首先就是要看懂别人写的代码,然后明白某段代码大概表述的意思,然后再根据框架依次实现。首先,我们来先看看pytorch的代码有哪些部分,然后再用paddle进行实现。

pytorch代码组成

原作者的pytorch代码
点击链接即可看到项目下有两个文件夹(assest,dataset),5个py文件,1个md文件,1个授权文件。显然有用的文件就是5个py文件,我们再分别点击这5个py文件,可以大致看出dataset.py是处理数据集的代码,networks.py是网络结构的代码,UGATIT.py是训练模型和测试模型的代码,main.py是启动文件,包括一些必要参数,utils.py是一些处理函数。通过大致浏览,就可以知道论文的核心代码是networks.py和UGATIT.py,故我们在进行复现论文过程中,这两个文件是关键。接下来,我们对各个文件进行详细实现。

networks.py实现

我个人认为,网络结构是论文的重中之重,故将其放到第一个进行实现。
由于这是基于GAN的网络结构,故有一个生成器网络,一个判别器网络,从代码中也可以看出,代码里分别有两个类,一个是ResnetGenerator,一个是Discriminator。

生成器网络

对于这生成器网络的实现,我们可以采用继承paddle.fluid.dygraph.Layer来创建类,即

class ResnetBlock(fluid.dygraph.Layer):
	def __init__(self, input_nc, output_nc, ngf=64, n_blocks=6, img_size=256, light=False):
		assert(n_blocks >= 0)
		...
	def forward(self, input):
		...

显然,这跟pytorch的nn.Module的结构一致,包括一个网络结构和前向传播的计算,然后我们再来看下网络结构,它是由很多块组成的,第一个块是由镜像填充,2维卷积,对图像的HW(像素)进行归一化,relu激活函数四个部分组成,而paddle.fluid.dygraph中只有Conv2D和InstanceNorm类,故镜像填充和relu激活函数需要自己定义类,这里给出镜像填充的定义,relu同理

class ReflectionPad2d(fluid.dygraph.Layer):
    def __init__(self, padding):
        super(ReflectionPad2d, self).__init__()
        self.padding = padding

    def forward(self, input):
        result = fluid.layers.pad2d(input,paddings=self.padding, mode="reflect")
        return result

故,第一个块写成

DownBlock = []
DownBlock += [ReflectionPad2d(padding=[3,3,3,3]),
              Conv2D(num_channels=input_nc, num_filters=ngf, filter_size=7, stride=1, padding=0, bias_attr=False),
              InstanceNorm(ngf),
              Relu()]

接下来两个块是同样的写法,只是其中参数需要修改下。往后看,涉及到残差块,而对于残差块,pytorch也给出了代码,故只需依瓢画葫芦即可写出,再然后就是两个全连接层和一个卷积层,再就是参数beta,gamma的块,这部分代码与pytorch基本一致,不需要修改。然后,到了论文的关键点,一个adILN残差块,与前面残差块不同的是,这里不再使用InstanceNorm进行归一化,而是使用一个定义的adILN进行归一化,这里需要注意一点,pytorch直接用Parameter函数创建一个参数变量,然后对参数变量进行填充,在paddle里使用create_parameter函数,并且在函数的配置参数上对其进行填充,即

self.rho = self.create_parameter([1, num_features, 1, 1],dtype='float32',default_initializer=fluid.initializer.Constant(0.9))

这里直接使用self.create_parameter即可,因为类别中有这个函数属性,也可以用fluid.layers.create_parameter函数。还有就是前向计算时,需要注意mean函数为fluid.layers.reduce_mean,var写成
fluid.layers.reduce_mean(fluid.layers.square(x - x_mean)),有时为了避免出错,需要将a-b写成fluid.layers.elementwise_sub(a,b).expand函数变成fluid.layers.expand,unsqueeze变成fluid.layers.unsqueeze函数。关于函数的用法,可以参考官网的API文档。后面还有个ILN归一化块,更前面adILN块基本一致。
最后,有个UpBlock2 块,这个块跟前面块的区别在于一个Upsample函数,同样也是定义一个类,利用fluid.layefrs.resize_nearest函数进行上采样

class Upsample(fluid.dygraph.Layer):
    def __init__(self, scale_factor):
        super(Upsample, self).__init__()
        self.scale = scal
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值