nlayers.py 6.0 KB
Newer Older
Q
qingqing01 已提交
1
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve.
L
lijianshe02 已提交
2 3 4 5 6 7 8 9 10 11 12 13 14
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

L
lzzyzlbb 已提交
15 16 17 18
# code was heavily based on https://github.com/wtjiang98/PSGAN
# MIT License 
# Copyright (c) 2020 Wentao Jiang

L
lijianshe02 已提交
19
import paddle
L
LielinJiang 已提交
20 21
import functools
import numpy as np
L
fix nan  
LielinJiang 已提交
22
import paddle.nn as nn
L
lijianshe02 已提交
23 24
import paddle.nn.functional as F

L
lijianshe02 已提交
25
from ...modules.nn import Spectralnorm
L
LielinJiang 已提交
26 27 28 29 30 31
from ...modules.norm import build_norm_layer

from .builder import DISCRIMINATORS


@DISCRIMINATORS.register()
32
class NLayerDiscriminator(nn.Layer):
L
LielinJiang 已提交
33
    """Defines a PatchGAN discriminator"""
34
    def __init__(self, input_nc, ndf=64, n_layers=3, norm_type='instance', use_sigmoid=False):
L
LielinJiang 已提交
35 36
        """Construct a PatchGAN discriminator

L
lijianshe02 已提交
37
        Parameters:
L
LielinJiang 已提交
38 39 40
            input_nc (int)  -- the number of channels in input images
            ndf (int)       -- the number of filters in the last conv layer
            n_layers (int)  -- the number of conv layers in the discriminator
41
            norm_type (str)      -- normalization layer type
42
            use_sigmoid (bool)   -- whether use sigmoid at last
L
LielinJiang 已提交
43 44 45
        """
        super(NLayerDiscriminator, self).__init__()
        norm_layer = build_norm_layer(norm_type)
L
lijianshe02 已提交
46 47 48
        if type(
                norm_layer
        ) == functools.partial:  # no need to use bias as BatchNorm2d has affine parameters
L
LielinJiang 已提交
49
            use_bias = norm_layer.func == nn.InstanceNorm2D
L
LielinJiang 已提交
50
        else:
L
LielinJiang 已提交
51
            use_bias = norm_layer == nn.InstanceNorm2D
L
fix nan  
LielinJiang 已提交
52

L
LielinJiang 已提交
53 54
        kw = 4
        padw = 1
55 56 57 58

        if norm_type == 'spectral':
            sequence = [
                Spectralnorm(
L
LielinJiang 已提交
59
                    nn.Conv2D(input_nc,
L
lijianshe02 已提交
60 61 62 63
                              ndf,
                              kernel_size=kw,
                              stride=2,
                              padding=padw)),
64 65 66 67
                nn.LeakyReLU(0.01)
            ]
        else:
            sequence = [
L
LielinJiang 已提交
68
                nn.Conv2D(input_nc,
L
lijianshe02 已提交
69 70 71 72 73
                          ndf,
                          kernel_size=kw,
                          stride=2,
                          padding=padw,
                          bias_attr=use_bias),
74 75
                nn.LeakyReLU(0.2)
            ]
L
LielinJiang 已提交
76 77
        nf_mult = 1
        nf_mult_prev = 1
L
lijianshe02 已提交
78
        for n in range(1, n_layers):  # gradually increase the number of filters
L
LielinJiang 已提交
79
            nf_mult_prev = nf_mult
L
fix nan  
LielinJiang 已提交
80
            nf_mult = min(2**n, 8)
81 82 83
            if norm_type == 'spectral':
                sequence += [
                    Spectralnorm(
L
LielinJiang 已提交
84
                        nn.Conv2D(ndf * nf_mult_prev,
L
lijianshe02 已提交
85 86 87 88
                                  ndf * nf_mult,
                                  kernel_size=kw,
                                  stride=2,
                                  padding=padw)),
89 90 91 92
                    nn.LeakyReLU(0.01)
                ]
            else:
                sequence += [
L
LielinJiang 已提交
93
                    nn.Conv2D(ndf * nf_mult_prev,
L
lijianshe02 已提交
94 95 96 97 98
                              ndf * nf_mult,
                              kernel_size=kw,
                              stride=2,
                              padding=padw,
                              bias_attr=use_bias),
99 100 101 102 103 104 105
                    norm_layer(ndf * nf_mult),
                    nn.LeakyReLU(0.2)
                ]

        nf_mult_prev = nf_mult
        nf_mult = min(2**n_layers, 8)
        if norm_type == 'spectral':
L
LielinJiang 已提交
106
            sequence += [
L
lijianshe02 已提交
107
                Spectralnorm(
L
LielinJiang 已提交
108
                    nn.Conv2D(ndf * nf_mult_prev,
L
lijianshe02 已提交
109 110 111 112
                              ndf * nf_mult,
                              kernel_size=kw,
                              stride=1,
                              padding=padw)),
L
lijianshe02 已提交
113
                nn.LeakyReLU(0.01)
L
LielinJiang 已提交
114
            ]
115 116
        else:
            sequence += [
L
LielinJiang 已提交
117
                nn.Conv2D(ndf * nf_mult_prev,
L
lijianshe02 已提交
118 119 120 121 122
                          ndf * nf_mult,
                          kernel_size=kw,
                          stride=1,
                          padding=padw,
                          bias_attr=use_bias),
123 124 125
                norm_layer(ndf * nf_mult),
                nn.LeakyReLU(0.2)
            ]
L
LielinJiang 已提交
126

127 128 129
        if norm_type == 'spectral':
            sequence += [
                Spectralnorm(
L
LielinJiang 已提交
130
                    nn.Conv2D(ndf * nf_mult,
L
lijianshe02 已提交
131 132 133 134 135
                              1,
                              kernel_size=kw,
                              stride=1,
                              padding=padw,
                              bias_attr=False))
136 137 138
            ]  # output 1 channel prediction map
        else:
            sequence += [
L
LielinJiang 已提交
139
                nn.Conv2D(ndf * nf_mult,
L
lijianshe02 已提交
140 141 142
                          1,
                          kernel_size=kw,
                          stride=1,
L
LielinJiang 已提交
143
                          padding=padw)
144 145
            ]  # output 1 channel prediction map

L
LielinJiang 已提交
146
        self.model = nn.Sequential(*sequence)
147
        self.final_act = F.sigmoid if use_sigmoid else (lambda x:x)
L
LielinJiang 已提交
148 149 150

    def forward(self, input):
        """Standard forward."""
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
        return self.final_act(self.model(input))


@DISCRIMINATORS.register()
class NLayerDiscriminatorWithClassification(NLayerDiscriminator):
    def __init__(self, input_nc, n_class=10, **kwargs):
        input_nc = input_nc + n_class
        super(NLayerDiscriminatorWithClassification, self).__init__(input_nc, **kwargs)

        self.n_class = n_class
    
    def forward(self, x, class_id):
        if self.n_class > 0:
            class_id = (class_id % self.n_class).detach()
            class_id = F.one_hot(class_id, self.n_class).astype('float32')
            class_id = class_id.reshape([x.shape[0], -1, 1, 1])
            class_id = class_id.tile([1,1,*x.shape[2:]])
            x = paddle.concat([x, class_id], 1)
        
        return super(NLayerDiscriminatorWithClassification, self).forward(x)