CoolFace
Apppublic

hololens/stable-diffusion-webui-depthmap-script

sourceHugging Faceupdated 2y agoView on Hugging Face
1likes
networks.py502 linesDownload Raw Back to inpaint
1import torch
2import torch.nn as nn
3import numpy as np
4import matplotlib.pyplot as plt
5import torch.nn.functional as F
6
7
8class BaseNetwork(nn.Module):
9    def __init__(self):
10        super(BaseNetwork, self).__init__()
11
12    def init_weights(self, init_type='normal', gain=0.02):
13        '''
14        initialize network's weights
15        init_type: normal | xavier | kaiming | orthogonal
16        https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix/blob/9451e70673400885567d08a9e97ade2524c700d0/models/networks.py#L39
17        '''
18
19        def init_func(m):
20            classname = m.__class__.__name__
21            if hasattr(m, 'weight') and (classname.find('Conv') != -1 or classname.find('Linear') != -1):
22                if init_type == 'normal':
23                    nn.init.normal_(m.weight.data, 0.0, gain)
24                elif init_type == 'xavier':
25                    nn.init.xavier_normal_(m.weight.data, gain=gain)
26                elif init_type == 'kaiming':
27                    nn.init.kaiming_normal_(m.weight.data, a=0, mode='fan_in')
28                elif init_type == 'orthogonal':
29                    nn.init.orthogonal_(m.weight.data, gain=gain)
30
31                if hasattr(m, 'bias') and m.bias is not None:
32                    nn.init.constant_(m.bias.data, 0.0)
33
34            elif classname.find('BatchNorm2d') != -1:
35                nn.init.normal_(m.weight.data, 1.0, gain)
36                nn.init.constant_(m.bias.data, 0.0)
37
38        self.apply(init_func)
39
40def weights_init(init_type='gaussian'):
41    def init_fun(m):
42        classname = m.__class__.__name__
43        if (classname.find('Conv') == 0 or classname.find(
44                'Linear') == 0) and hasattr(m, 'weight'):
45            if init_type == 'gaussian':
46                nn.init.normal_(m.weight, 0.0, 0.02)
47            elif init_type == 'xavier':
48                nn.init.xavier_normal_(m.weight, gain=math.sqrt(2))
49            elif init_type == 'kaiming':
50                nn.init.kaiming_normal_(m.weight, a=0, mode='fan_in')
51            elif init_type == 'orthogonal':
52                nn.init.orthogonal_(m.weight, gain=math.sqrt(2))
53            elif init_type == 'default':
54                pass
55            else:
56                assert 0, "Unsupported initialization: {}".format(init_type)
57            if hasattr(m, 'bias') and m.bias is not None:
58                nn.init.constant_(m.bias, 0.0)
59
60    return init_fun
61
62class PartialConv(nn.Module):
63    def __init__(self, in_channels, out_channels, kernel_size, stride=1,
64                 padding=0, dilation=1, groups=1, bias=True):
65        super().__init__()
66        self.input_conv = nn.Conv2d(in_channels, out_channels, kernel_size,
67                                    stride, padding, dilation, groups, bias)
68        self.mask_conv = nn.Conv2d(in_channels, out_channels, kernel_size,
69                                   stride, padding, dilation, groups, False)
70        self.input_conv.apply(weights_init('kaiming'))
71        self.slide_winsize = in_channels * kernel_size * kernel_size
72
73        torch.nn.init.constant_(self.mask_conv.weight, 1.0)
74
75        # mask is not updated
76        for param in self.mask_conv.parameters():
77            param.requires_grad = False
78
79    def forward(self, input, mask):
80        # http://masc.cs.gmu.edu/wiki/partialconv
81        # C(X) = W^T * X + b, C(0) = b, D(M) = 1 * M + 0 = sum(M)
82        # W^T* (M .* X) / sum(M) + b = [C(M .* X) โ€“ C(0)] / D(M) + C(0)
83        output = self.input_conv(input * mask)
84        if self.input_conv.bias is not None:
85            output_bias = self.input_conv.bias.view(1, -1, 1, 1).expand_as(
86                output)
87        else:
88            output_bias = torch.zeros_like(output)
89
90        with torch.no_grad():
91            output_mask = self.mask_conv(mask)
92
93        no_update_holes = output_mask == 0
94
95        mask_sum = output_mask.masked_fill_(no_update_holes, 1.0)
96
97        output_pre = ((output - output_bias) * self.slide_winsize) / mask_sum + output_bias
98        output = output_pre.masked_fill_(no_update_holes, 0.0)
99
100        new_mask = torch.ones_like(output)
101        new_mask = new_mask.masked_fill_(no_update_holes, 0.0)
102
103        return output, new_mask
104
105
106class PCBActiv(nn.Module):
107    def __init__(self, in_ch, out_ch, bn=True, sample='none-3', activ='relu',
108                 conv_bias=False):
109        super().__init__()
110        if sample == 'down-5':
111            self.conv = PartialConv(in_ch, out_ch, 5, 2, 2, bias=conv_bias)
112        elif sample == 'down-7':
113            self.conv = PartialConv(in_ch, out_ch, 7, 2, 3, bias=conv_bias)
114        elif sample == 'down-3':
115            self.conv = PartialConv(in_ch, out_ch, 3, 2, 1, bias=conv_bias)
116        else:
117            self.conv = PartialConv(in_ch, out_ch, 3, 1, 1, bias=conv_bias)
118
119        if bn:
120            self.bn = nn.BatchNorm2d(out_ch)
121        if activ == 'relu':
122            self.activation = nn.ReLU()
123        elif activ == 'leaky':
124            self.activation = nn.LeakyReLU(negative_slope=0.2)
125
126    def forward(self, input, input_mask):
127        h, h_mask = self.conv(input, input_mask)
128        if hasattr(self, 'bn'):
129            h = self.bn(h)
130        if hasattr(self, 'activation'):
131            h = self.activation(h)
132        return h, h_mask
133
134class Inpaint_Depth_Net(nn.Module):
135    def __init__(self, layer_size=7, upsampling_mode='nearest'):
136        super().__init__()
137        in_channels = 4
138        out_channels = 1
139        self.freeze_enc_bn = False
140        self.upsampling_mode = upsampling_mode
141        self.layer_size = layer_size
142        self.enc_1 = PCBActiv(in_channels, 64, bn=False, sample='down-7', conv_bias=True)
143        self.enc_2 = PCBActiv(64, 128, sample='down-5', conv_bias=True)
144        self.enc_3 = PCBActiv(128, 256, sample='down-5')
145        self.enc_4 = PCBActiv(256, 512, sample='down-3')
146        for i in range(4, self.layer_size):
147            name = 'enc_{:d}'.format(i + 1)
148            setattr(self, name, PCBActiv(512, 512, sample='down-3'))
149
150        for i in range(4, self.layer_size):
151            name = 'dec_{:d}'.format(i + 1)
152            setattr(self, name, PCBActiv(512 + 512, 512, activ='leaky'))
153        self.dec_4 = PCBActiv(512 + 256, 256, activ='leaky')
154        self.dec_3 = PCBActiv(256 + 128, 128, activ='leaky')
155        self.dec_2 = PCBActiv(128 + 64, 64, activ='leaky')
156        self.dec_1 = PCBActiv(64 + in_channels, out_channels,
157                              bn=False, activ=None, conv_bias=True)
158    def add_border(self, input, mask_flag, PCONV=True):
159        with torch.no_grad():
160            h = input.shape[-2]
161            w = input.shape[-1]
162            require_len_unit = 2 ** self.layer_size
163            residual_h = int(np.ceil(h / float(require_len_unit)) * require_len_unit - h) # + 2*require_len_unit
164            residual_w = int(np.ceil(w / float(require_len_unit)) * require_len_unit - w) # + 2*require_len_unit
165            enlarge_input = torch.zeros((input.shape[0], input.shape[1], h + residual_h, w + residual_w)).to(input.device)
166            if mask_flag:
167                if PCONV is False:
168                    enlarge_input += 1.0
169                enlarge_input = enlarge_input.clamp(0.0, 1.0)
170            else:
171                enlarge_input[:, 2, ...] = 0.0
172            anchor_h = residual_h//2
173            anchor_w = residual_w//2
174            enlarge_input[..., anchor_h:anchor_h+h, anchor_w:anchor_w+w] = input
175
176        return enlarge_input, [anchor_h, anchor_h+h, anchor_w, anchor_w+w]
177
178    def forward_3P(self, mask, context, depth, edge, unit_length=128, cuda=None):
179        with torch.no_grad():
180            input = torch.cat((depth, edge, context, mask), dim=1)
181            n, c, h, w = input.shape
182            residual_h = int(np.ceil(h / float(unit_length)) * unit_length - h)
183            residual_w = int(np.ceil(w / float(unit_length)) * unit_length - w)
184            anchor_h = residual_h//2
185            anchor_w = residual_w//2
186            enlarge_input = torch.zeros((n, c, h + residual_h, w + residual_w)).to(cuda)
187            enlarge_input[..., anchor_h:anchor_h+h, anchor_w:anchor_w+w] = input
188            # enlarge_input[:, 3] = 1. - enlarge_input[:, 3]
189            depth_output = self.forward(enlarge_input)
190            depth_output = depth_output[..., anchor_h:anchor_h+h, anchor_w:anchor_w+w]
191            # import pdb; pdb.set_trace()
192
193        return depth_output
194
195    def forward(self, input_feat, refine_border=False, sample=False, PCONV=True):
196        input = input_feat
197        input_mask = (input_feat[:, -2:-1] + input_feat[:, -1:]).clamp(0, 1).repeat(1, input.shape[1], 1, 1)
198
199        vis_input = input.cpu().data.numpy()
200        vis_input_mask = input_mask.cpu().data.numpy()
201        H, W = input.shape[-2:]
202        if refine_border is True:
203            input, anchor = self.add_border(input, mask_flag=False)
204            input_mask, anchor = self.add_border(input_mask, mask_flag=True, PCONV=PCONV)
205        h_dict = {}  # for the output of enc_N
206        h_mask_dict = {}  # for the output of enc_N
207        h_dict['h_0'], h_mask_dict['h_0'] = input, input_mask
208
209        h_key_prev = 'h_0'
210        for i in range(1, self.layer_size + 1):
211            l_key = 'enc_{:d}'.format(i)
212            h_key = 'h_{:d}'.format(i)
213            h_dict[h_key], h_mask_dict[h_key] = getattr(self, l_key)(
214                h_dict[h_key_prev], h_mask_dict[h_key_prev])
215            h_key_prev = h_key
216
217        h_key = 'h_{:d}'.format(self.layer_size)
218        h, h_mask = h_dict[h_key], h_mask_dict[h_key]
219
220        for i in range(self.layer_size, 0, -1):
221            enc_h_key = 'h_{:d}'.format(i - 1)
222            dec_l_key = 'dec_{:d}'.format(i)
223
224            h = F.interpolate(h, scale_factor=2, mode=self.upsampling_mode)
225            h_mask = F.interpolate(h_mask, scale_factor=2, mode='nearest')
226
227            h = torch.cat([h, h_dict[enc_h_key]], dim=1)
228            h_mask = torch.cat([h_mask, h_mask_dict[enc_h_key]], dim=1)
229            h, h_mask = getattr(self, dec_l_key)(h, h_mask)
230        output = h
231        if refine_border is True:
232            h_mask = h_mask[..., anchor[0]:anchor[1], anchor[2]:anchor[3]]
233            output = output[..., anchor[0]:anchor[1], anchor[2]:anchor[3]]
234
235        return output
236
237class Inpaint_Edge_Net(BaseNetwork):
238    def __init__(self, residual_blocks=8, init_weights=True):
239        super(Inpaint_Edge_Net, self).__init__()
240        in_channels = 7
241        out_channels = 1
242        self.encoder = []
243        # 0
244        self.encoder_0 = nn.Sequential(
245                            nn.ReflectionPad2d(3),
246                            spectral_norm(nn.Conv2d(in_channels=in_channels, out_channels=64, kernel_size=7, padding=0), True),
247                            nn.InstanceNorm2d(64, track_running_stats=False),
248                            nn.ReLU(True))
249        # 1
250        self.encoder_1 = nn.Sequential(
251                            spectral_norm(nn.Conv2d(in_channels=64, out_channels=128, kernel_size=4, stride=2, padding=1), True),
252                            nn.InstanceNorm2d(128, track_running_stats=False),
253                            nn.ReLU(True))
254        # 2
255        self.encoder_2 = nn.Sequential(
256                            spectral_norm(nn.Conv2d(in_channels=128, out_channels=256, kernel_size=4, stride=2, padding=1), True),
257                            nn.InstanceNorm2d(256, track_running_stats=False),
258                            nn.ReLU(True))
259        # 3
260        blocks = []
261        for _ in range(residual_blocks):
262            block = ResnetBlock(256, 2)
263            blocks.append(block)
264
265        self.middle = nn.Sequential(*blocks)
266        # + 3
267        self.decoder_0 = nn.Sequential(
268                            spectral_norm(nn.ConvTranspose2d(in_channels=256+256, out_channels=128, kernel_size=4, stride=2, padding=1), True),
269                            nn.InstanceNorm2d(128, track_running_stats=False),
270                            nn.ReLU(True))
271        # + 2
272        self.decoder_1 = nn.Sequential(
273                            spectral_norm(nn.ConvTranspose2d(in_channels=128+128, out_channels=64, kernel_size=4, stride=2, padding=1), True),
274                            nn.InstanceNorm2d(64, track_running_stats=False),
275                            nn.ReLU(True))
276        # + 1
277        self.decoder_2 = nn.Sequential(
278                            nn.ReflectionPad2d(3),
279                            nn.Conv2d(in_channels=64+64, out_channels=out_channels, kernel_size=7, padding=0),
280                            )
281
282        if init_weights:
283            self.init_weights()
284
285    def add_border(self, input, channel_pad_1=None):
286        h = input.shape[-2]
287        w = input.shape[-1]
288        require_len_unit = 16
289        residual_h = int(np.ceil(h / float(require_len_unit)) * require_len_unit - h) # + 2*require_len_unit
290        residual_w = int(np.ceil(w / float(require_len_unit)) * require_len_unit - w) # + 2*require_len_unit
291        enlarge_input = torch.zeros((input.shape[0], input.shape[1], h + residual_h, w + residual_w)).to(input.device)
292        if channel_pad_1 is not None:
293            for channel in channel_pad_1:
294                enlarge_input[:, channel] = 1
295        anchor_h = residual_h//2
296        anchor_w = residual_w//2
297        enlarge_input[..., anchor_h:anchor_h+h, anchor_w:anchor_w+w] = input
298
299        return enlarge_input, [anchor_h, anchor_h+h, anchor_w, anchor_w+w]
300
301    def forward_3P(self, mask, context, rgb, disp, edge, unit_length=128, cuda=None):
302        with torch.no_grad():
303            input = torch.cat((rgb, disp/disp.max(), edge, context, mask), dim=1)
304            n, c, h, w = input.shape
305            residual_h = int(np.ceil(h / float(unit_length)) * unit_length - h)
306            residual_w = int(np.ceil(w / float(unit_length)) * unit_length - w)
307            anchor_h = residual_h//2
308            anchor_w = residual_w//2
309            enlarge_input = torch.zeros((n, c, h + residual_h, w + residual_w)).to(cuda)
310            enlarge_input[..., anchor_h:anchor_h+h, anchor_w:anchor_w+w] = input
311            edge_output = self.forward(enlarge_input)
312            edge_output = edge_output[..., anchor_h:anchor_h+h, anchor_w:anchor_w+w]
313
314        return edge_output
315
316    def forward(self, x, refine_border=False):
317        if refine_border:
318            x, anchor = self.add_border(x, [5])
319        x1 = self.encoder_0(x)
320        x2 = self.encoder_1(x1)
321        x3 = self.encoder_2(x2)
322        x4 = self.middle(x3)
323        x5 = self.decoder_0(torch.cat((x4, x3), dim=1))
324        x6 = self.decoder_1(torch.cat((x5, x2), dim=1))
325        x7 = self.decoder_2(torch.cat((x6, x1), dim=1))
326        x = torch.sigmoid(x7)
327        if refine_border:
328            x = x[..., anchor[0]:anchor[1], anchor[2]:anchor[3]]
329
330        return x
331
332class Inpaint_Color_Net(nn.Module):
333    def __init__(self, layer_size=7, upsampling_mode='nearest', add_hole_mask=False, add_two_layer=False, add_border=False):
334        super().__init__()
335        self.freeze_enc_bn = False
336        self.upsampling_mode = upsampling_mode
337        self.layer_size = layer_size
338        in_channels = 6
339        self.enc_1 = PCBActiv(in_channels, 64, bn=False, sample='down-7')
340        self.enc_2 = PCBActiv(64, 128, sample='down-5')
341        self.enc_3 = PCBActiv(128, 256, sample='down-5')
342        self.enc_4 = PCBActiv(256, 512, sample='down-3')
343        self.enc_5 = PCBActiv(512, 512, sample='down-3')
344        self.enc_6 = PCBActiv(512, 512, sample='down-3')
345        self.enc_7 = PCBActiv(512, 512, sample='down-3')
346
347        self.dec_7 = PCBActiv(512+512, 512, activ='leaky')
348        self.dec_6 = PCBActiv(512+512, 512, activ='leaky')
349
350        self.dec_5A = PCBActiv(512 + 512, 512, activ='leaky')
351        self.dec_4A = PCBActiv(512 + 256, 256, activ='leaky')
352        self.dec_3A = PCBActiv(256 + 128, 128, activ='leaky')
353        self.dec_2A = PCBActiv(128 + 64, 64, activ='leaky')
354        self.dec_1A = PCBActiv(64 + in_channels, 3, bn=False, activ=None, conv_bias=True)
355        '''
356        self.dec_5B = PCBActiv(512 + 512, 512, activ='leaky')
357        self.dec_4B = PCBActiv(512 + 256, 256, activ='leaky')
358        self.dec_3B = PCBActiv(256 + 128, 128, activ='leaky')
359        self.dec_2B = PCBActiv(128 + 64, 64, activ='leaky')
360        self.dec_1B = PCBActiv(64 + 4, 1, bn=False, activ=None, conv_bias=True)
361        '''
362    def cat(self, A, B):
363        return torch.cat((A, B), dim=1)
364
365    def upsample(self, feat, mask):
366        feat = F.interpolate(feat, scale_factor=2, mode=self.upsampling_mode)
367        mask = F.interpolate(mask, scale_factor=2, mode='nearest')
368
369        return feat, mask
370
371    def forward_3P(self, mask, context, rgb, edge, unit_length=128, cuda=None):
372        with torch.no_grad():
373            input = torch.cat((rgb, edge, context, mask), dim=1)
374            n, c, h, w = input.shape
375            residual_h = int(np.ceil(h / float(unit_length)) * unit_length - h) # + 128
376            residual_w = int(np.ceil(w / float(unit_length)) * unit_length - w) # + 256
377            anchor_h = residual_h//2
378            anchor_w = residual_w//2
379            enlarge_input = torch.zeros((n, c, h + residual_h, w + residual_w)).to(cuda)
380            enlarge_input[..., anchor_h:anchor_h+h, anchor_w:anchor_w+w] = input
381            # enlarge_input[:, 3] = 1. - enlarge_input[:, 3]
382            enlarge_input = enlarge_input.to(cuda)
383            rgb_output = self.forward(enlarge_input)
384            rgb_output = rgb_output[..., anchor_h:anchor_h+h, anchor_w:anchor_w+w]
385
386        return rgb_output
387
388    def forward(self, input, add_border=False):
389        input_mask = (input[:, -2:-1] + input[:, -1:]).clamp(0, 1)
390        H, W = input.shape[-2:]
391        f_0, h_0 = input, input_mask.repeat((1,input.shape[1],1,1))
392        f_1, h_1 = self.enc_1(f_0, h_0)
393        f_2, h_2 = self.enc_2(f_1, h_1)
394        f_3, h_3 = self.enc_3(f_2, h_2)
395        f_4, h_4 = self.enc_4(f_3, h_3)
396        f_5, h_5 = self.enc_5(f_4, h_4)
397        f_6, h_6 = self.enc_6(f_5, h_5)
398        f_7, h_7 = self.enc_7(f_6, h_6)
399
400        o_7, k_7 = self.upsample(f_7, h_7)
401        o_6, k_6 = self.dec_7(self.cat(o_7, f_6), self.cat(k_7, h_6))
402        o_6, k_6 = self.upsample(o_6, k_6)
403        o_5, k_5 = self.dec_6(self.cat(o_6, f_5), self.cat(k_6, h_5))
404        o_5, k_5 = self.upsample(o_5, k_5)
405        o_5A, k_5A = o_5, k_5
406        o_5B, k_5B = o_5, k_5
407        ###############
408        o_4A, k_4A = self.dec_5A(self.cat(o_5A, f_4), self.cat(k_5A, h_4))
409        o_4A, k_4A = self.upsample(o_4A, k_4A)
410        o_3A, k_3A = self.dec_4A(self.cat(o_4A, f_3), self.cat(k_4A, h_3))
411        o_3A, k_3A = self.upsample(o_3A, k_3A)
412        o_2A, k_2A = self.dec_3A(self.cat(o_3A, f_2), self.cat(k_3A, h_2))
413        o_2A, k_2A = self.upsample(o_2A, k_2A)
414        o_1A, k_1A = self.dec_2A(self.cat(o_2A, f_1), self.cat(k_2A, h_1))
415        o_1A, k_1A = self.upsample(o_1A, k_1A)
416        o_0A, k_0A = self.dec_1A(self.cat(o_1A, f_0), self.cat(k_1A, h_0))
417
418        return torch.sigmoid(o_0A)
419
420    def train(self, mode=True):
421        """
422        Override the default train() to freeze the BN parameters
423        """
424        super().train(mode)
425        if self.freeze_enc_bn:
426            for name, module in self.named_modules():
427                if isinstance(module, nn.BatchNorm2d) and 'enc' in name:
428                    module.eval()
429
430class Discriminator(BaseNetwork):
431    def __init__(self, use_sigmoid=True, use_spectral_norm=True, init_weights=True, in_channels=None):
432        super(Discriminator, self).__init__()
433        self.use_sigmoid = use_sigmoid
434        self.conv1 = self.features = nn.Sequential(
435            spectral_norm(nn.Conv2d(in_channels=in_channels, out_channels=64, kernel_size=4, stride=2, padding=1, bias=not use_spectral_norm), use_spectral_norm),
436            nn.LeakyReLU(0.2, inplace=True),
437        )
438
439        self.conv2 = nn.Sequential(
440            spectral_norm(nn.Conv2d(in_channels=64, out_channels=128, kernel_size=4, stride=2, padding=1, bias=not use_spectral_norm), use_spectral_norm),
441            nn.LeakyReLU(0.2, inplace=True),
442        )
443
444        self.conv3 = nn.Sequential(
445            spectral_norm(nn.Conv2d(in_channels=128, out_channels=256, kernel_size=4, stride=2, padding=1, bias=not use_spectral_norm), use_spectral_norm),
446            nn.LeakyReLU(0.2, inplace=True),
447        )
448
449        self.conv4 = nn.Sequential(
450            spectral_norm(nn.Conv2d(in_channels=256, out_channels=512, kernel_size=4, stride=1, padding=1, bias=not use_spectral_norm), use_spectral_norm),
451            nn.LeakyReLU(0.2, inplace=True),
452        )
453
454        self.conv5 = nn.Sequential(
455            spectral_norm(nn.Conv2d(in_channels=512, out_channels=1, kernel_size=4, stride=1, padding=1, bias=not use_spectral_norm), use_spectral_norm),
456        )
457
458        if init_weights:
459            self.init_weights()
460
461    def forward(self, x):
462        conv1 = self.conv1(x)
463        conv2 = self.conv2(conv1)
464        conv3 = self.conv3(conv2)
465        conv4 = self.conv4(conv3)
466        conv5 = self.conv5(conv4)
467
468        outputs = conv5
469        if self.use_sigmoid:
470            outputs = torch.sigmoid(conv5)
471
472        return outputs, [conv1, conv2, conv3, conv4, conv5]
473
474class ResnetBlock(nn.Module):
475    def __init__(self, dim, dilation=1):
476        super(ResnetBlock, self).__init__()
477        self.conv_block = nn.Sequential(
478            nn.ReflectionPad2d(dilation),
479            spectral_norm(nn.Conv2d(in_channels=dim, out_channels=dim, kernel_size=3, padding=0, dilation=dilation, bias=not True), True),
480            nn.InstanceNorm2d(dim, track_running_stats=False),
481            nn.LeakyReLU(negative_slope=0.2),
482
483            nn.ReflectionPad2d(1),
484            spectral_norm(nn.Conv2d(in_channels=dim, out_channels=dim, kernel_size=3, padding=0, dilation=1, bias=not True), True),
485            nn.InstanceNorm2d(dim, track_running_stats=False),
486        )
487
488    def forward(self, x):
489        out = x + self.conv_block(x)
490
491        # Remove ReLU at the end of the residual block
492        # http://torch.ch/blog/2016/02/04/resnets.html
493
494        return out
495
496
497def spectral_norm(module, mode=True):
498    if mode:
499        return nn.utils.spectral_norm(module)
500
501    return module
502