[论文笔记]On the Effects and Weight Normalization in GAN

本文探索了参数标准化(Weight Normalization)这一技术在GAN中的应用。BN在mini-batch的层级上计算均值和方差,容易引入噪声,并不适用于GAN这种生成模型,而WN对参数进行重写,引入噪声更少。

我觉得本文的亮点有二:

1. 提出T-ReLU并配合Affine Tranformation使在引入WN后网络的表达能力维持不变

朴素的参数标准化层有如下的形式:
$$y=\frac{{w}^{T}x}{\|w\|}$$
文中称这样形式的层为“strict weight-normalized layer”。若将线性层换为这样的层,网络的表达能力会下降,因而需要添加如下的affine transformation:

$$y=\frac{{w}^{T}x}{\|w\|} \gamma + \beta$$

用于恢复网络的表达能力。

将上述变换带入ReLU,简化后可以得到如下T-ReLu:
$$TReLU_\alpha (x) = ReLU(x-\alpha) + \alpha$$

文章的一个重要结论是,在网络的最后一层加入affine transformation层之后,堆叠的“线性层+ReLU”与“strict weight-normalized layer + T-ReLU”表达能力相同(在附录中给出证明)。

下面L表示线性层,R表示ReLU,TR表示TReLU,A表示affine transformation,S表示上述的strict weight-normalized layer。

证明的大致思路是,在ReLU与线性层之间加入affine transformation层,由于线性层的存在,affine transformation带来的效果会被吸收(相当于多个线性层叠在一起还是线性层),网络表达能力不变。而”L+R+A”的结构可以等价于”S+TR+A”。如此递归下去,即可得到结论。个人认为相当于把线性层中的bias转嫁成了TReLU中的threshold(即$\alpha$)。

2. 提出对生成图形的评估指标

生成式模型的生成效果常常难以评价。DcGAN给出的结果也是生成图片的对比。本文中提出一个评价生成效果的指标,且与人的主观评价一致。

评价的具体指标是生成图片与测试集图片的欧氏距离,评价的对象是生成器是Generator。有如下形式:

$$\frac{1}{m} \sum_{i=1}^{m} min_z {\|G(z)-x^{(i)}\|}^2$$

其中的$min$指使用梯度下降方法等使生成图片的效果最好。但事实上这样做开销很高。

PyTorch实现

作者将他们的实现代码公布在了GitHub上。

下面是利用PyTorch对T-ReLU的实现:

class TPReLU(Module):

    def __init__(self, num_parameters=1, init=0.25):
        self.num_parameters = num_parameters
        super(TPReLU, self).__init__()
        self.weight = Parameter(torch.Tensor(num_parameters).fill_(init))
        self.bias = Parameter(torch.zeros(num_parameters))

    def forward(self, input):
        bias_resize = self.bias.view(1, self.num_parameters, *((1,) * (input.dim() - 2))).expand_as(input)
        return F.prelu(input - bias_resize, self.weight.clamp(0, 1)) + bias_resize


对 Weigh-normalized layer 的实现:

class WeightNormalizedLinear(Module):

    def __init__(self, in_features, out_features, scale=True, bias=True, init_factor=1, init_scale=1):
        super(WeightNormalizedLinear, self).__init__()
        self.in_features = in_features
        self.out_features = out_features
        self.weight = Parameter(torch.Tensor(out_features, in_features))
        if bias:
            self.bias = Parameter(torch.zeros(1, out_features))
        else:
            self.register_parameter('bias', None)
        if scale:
            self.scale = Parameter(torch.Tensor(1, out_features).fill_(init_scale))
        else:
            self.register_parameter('scale', None)
        self.reset_parameters(init_factor)

    def reset_parameters(self, factor):
        stdv = 1. * factor / math.sqrt(self.weight.size(1))
        self.weight.data.uniform_(-stdv, stdv)
        if self.bias is not None:
            self.bias.data.uniform_(-stdv, stdv)

    def weight_norm(self):
        return self.weight.pow(2).sum(1).add(1e-6).sqrt()

    def norm_scale_bias(self, input):
        output = input.div(self.weight_norm().transpose(0, 1).expand_as(input))
        if self.scale is not None:
            output = output.mul(self.scale.expand_as(input))
        if self.bias is not None:
            output = output.add(self.bias.expand_as(input))
        return output

    def forward(self, input):
        return self.norm_scale_bias(F.linear(input, self.weight))

观察上面的forward函数可以发现,TReLU添加bias这一习得参数,而weight-normalized layer中则对传入的weight进行了标准化。

论文链接:On the Effects and Weight Normalization in GAN

[论文笔记]Accurate, Large Minibatch SGD: Training ImageNet in One Hour [论文笔记]Large-Scale Evolution of Image Classifiers
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×