resnet.py 6.1 KB
Newer Older
L
LielinJiang 已提交
1 2 3 4 5 6 7 8 9 10
import paddle
import paddle.nn as nn
import functools

from ...modules.norm import build_norm_layer

from .builder import GENERATORS


@GENERATORS.register()
L
fix nan  
LielinJiang 已提交
11
class ResnetGenerator(nn.Layer):
L
LielinJiang 已提交
12 13 14 15
    """Resnet-based generator that consists of Resnet blocks between a few downsampling/upsampling operations.

    code and idea from Justin Johnson's neural style transfer project(https://github.com/jcjohnson/fast-neural-style)
    """
L
fix nan  
LielinJiang 已提交
16 17 18 19 20 21 22 23
    def __init__(self,
                 input_nc,
                 output_nc,
                 ngf=64,
                 norm_type='instance',
                 use_dropout=False,
                 n_blocks=6,
                 padding_type='reflect'):
L
LielinJiang 已提交
24 25 26 27 28 29 30 31 32 33 34
        """Construct a Resnet-based generator

        Args:
            input_nc (int)      -- the number of channels in input images
            output_nc (int)     -- the number of channels in output images
            ngf (int)           -- the number of filters in the last conv layer
            norm_layer          -- normalization layer
            use_dropout (bool)  -- if use dropout layers
            n_blocks (int)      -- the number of ResNet blocks
            padding_type (str)  -- the name of padding layer in conv layers: reflect | replicate | zero
        """
L
fix nan  
LielinJiang 已提交
35
        assert (n_blocks >= 0)
L
LielinJiang 已提交
36 37 38 39 40 41 42 43
        super(ResnetGenerator, self).__init__()

        norm_layer = build_norm_layer(norm_type)
        if type(norm_layer) == functools.partial:
            use_bias = norm_layer.func == nn.InstanceNorm
        else:
            use_bias = norm_layer == nn.InstanceNorm

L
fix nan  
LielinJiang 已提交
44 45 46 47 48 49 50 51 52 53
        model = [
            nn.ReflectionPad2d([3, 3, 3, 3]),
            nn.Conv2d(input_nc,
                      ngf,
                      kernel_size=7,
                      padding=0,
                      bias_attr=use_bias),
            norm_layer(ngf),
            nn.ReLU()
        ]
L
LielinJiang 已提交
54 55 56

        n_downsampling = 2
        for i in range(n_downsampling):  # add downsampling layers
L
fix nan  
LielinJiang 已提交
57
            mult = 2**i
L
LielinJiang 已提交
58
            model += [
L
fix nan  
LielinJiang 已提交
59 60 61 62 63 64 65 66 67 68 69 70
                nn.Conv2d(ngf * mult,
                          ngf * mult * 2,
                          kernel_size=3,
                          stride=2,
                          padding=1,
                          bias_attr=use_bias),
                norm_layer(ngf * mult * 2),
                nn.ReLU()
            ]

        mult = 2**n_downsampling
        for i in range(n_blocks):  # add ResNet blocks
L
LielinJiang 已提交
71

L
fix nan  
LielinJiang 已提交
72 73 74 75 76 77 78
            model += [
                ResnetBlock(ngf * mult,
                            padding_type=padding_type,
                            norm_layer=norm_layer,
                            use_dropout=use_dropout,
                            use_bias=use_bias)
            ]
L
LielinJiang 已提交
79 80

        for i in range(n_downsampling):  # add upsampling layers
L
fix nan  
LielinJiang 已提交
81
            mult = 2**(n_downsampling - i)
L
LielinJiang 已提交
82
            model += [
L
fix nan  
LielinJiang 已提交
83 84 85 86 87 88 89 90 91 92 93
                nn.ConvTranspose2d(ngf * mult,
                                   int(ngf * mult / 2),
                                   kernel_size=3,
                                   stride=2,
                                   padding=1,
                                   output_padding=1,
                                   bias_attr=use_bias),
                norm_layer(int(ngf * mult / 2)),
                nn.ReLU()
            ]
        model += [nn.ReflectionPad2d([3, 3, 3, 3])]
L
LielinJiang 已提交
94 95
        model += [nn.Conv2d(ngf, output_nc, kernel_size=7, padding=0)]
        model += [nn.Tanh()]
L
LielinJiang 已提交
96 97 98 99 100 101 102 103

        self.model = nn.Sequential(*model)

    def forward(self, x):
        """Standard forward"""
        return self.model(x)


L
fix nan  
LielinJiang 已提交
104
class ResnetBlock(nn.Layer):
L
LielinJiang 已提交
105 106 107 108 109 110 111 112 113 114
    """Define a Resnet block"""
    def __init__(self, dim, padding_type, norm_layer, use_dropout, use_bias):
        """Initialize the Resnet block

        A resnet block is a conv block with skip connections
        We construct a conv block with build_conv_block function,
        and implement skip connections in <forward> function.
        Original Resnet paper: https://arxiv.org/pdf/1512.03385.pdf
        """
        super(ResnetBlock, self).__init__()
L
fix nan  
LielinJiang 已提交
115 116
        self.conv_block = self.build_conv_block(dim, padding_type, norm_layer,
                                                use_dropout, use_bias)
L
LielinJiang 已提交
117

L
fix nan  
LielinJiang 已提交
118 119
    def build_conv_block(self, dim, padding_type, norm_layer, use_dropout,
                         use_bias):
L
LielinJiang 已提交
120 121 122 123 124 125 126 127 128 129 130 131 132 133
        """Construct a convolutional block.

        Parameters:
            dim (int)           -- the number of channels in the conv layer.
            padding_type (str)  -- the name of padding layer: reflect | replicate | zero
            norm_layer          -- normalization layer
            use_dropout (bool)  -- if use dropout layers.
            use_bias (bool)     -- if the conv layer uses bias or not

        Returns a conv block (with a conv layer, a normalization layer, and a non-linearity layer (ReLU))
        """
        conv_block = []
        p = 0
        if padding_type == 'reflect':
L
fix nan  
LielinJiang 已提交
134
            conv_block += [nn.ReflectionPad2d([1, 1, 1, 1])]
L
LielinJiang 已提交
135
        elif padding_type == 'replicate':
L
fix nan  
LielinJiang 已提交
136
            conv_block += [nn.ReplicationPad2d([1, 1, 1, 1])]
L
LielinJiang 已提交
137 138 139
        elif padding_type == 'zero':
            p = 1
        else:
L
fix nan  
LielinJiang 已提交
140 141 142 143 144 145 146 147
            raise NotImplementedError('padding [%s] is not implemented' %
                                      padding_type)

        conv_block += [
            nn.Conv2d(dim, dim, kernel_size=3, padding=p, bias_attr=use_bias),
            norm_layer(dim),
            nn.ReLU()
        ]
L
LielinJiang 已提交
148
        if use_dropout:
L
fix nan  
LielinJiang 已提交
149 150
            conv_block += [nn.Dropout(0.5)]

L
LielinJiang 已提交
151 152
        p = 0
        if padding_type == 'reflect':
L
fix nan  
LielinJiang 已提交
153
            conv_block += [nn.ReflectionPad2d([1, 1, 1, 1])]
L
LielinJiang 已提交
154
        elif padding_type == 'replicate':
L
fix nan  
LielinJiang 已提交
155
            conv_block += [nn.ReplicationPad2d([1, 1, 1, 1])]
L
LielinJiang 已提交
156 157 158
        elif padding_type == 'zero':
            p = 1
        else:
L
fix nan  
LielinJiang 已提交
159 160 161 162 163 164
            raise NotImplementedError('padding [%s] is not implemented' %
                                      padding_type)
        conv_block += [
            nn.Conv2d(dim, dim, kernel_size=3, padding=p, bias_attr=use_bias),
            norm_layer(dim)
        ]
L
LielinJiang 已提交
165 166 167 168 169 170 171

        return nn.Sequential(*conv_block)

    def forward(self, x):
        """Forward function (with skip connections)"""
        out = x + self.conv_block(x)  # add skip connections
        return out