2121import numpy as np
2222import torch
2323import torch .nn as nn
24- import torch .nn .functional as F
2524
2625from ..configuration_utils import ConfigMixin
2726from ..modeling_utils import ModelMixin
2827from .attention import AttentionBlock
2928from .embeddings import GaussianFourierProjection , get_timestep_embedding
30- from .resnet import Downsample , ResnetBlock2D , Upsample , downsample_2d , upfirdn2d , upsample_2d
29+ from .resnet import Downsample2D , FirDownsample2D , FirUpsample2D , ResnetBlock2D , Upsample2D
3130
3231
3332def _setup_kernel (k ):
@@ -40,96 +39,6 @@ def _setup_kernel(k):
4039 return k
4140
4241
43- def _upsample_conv_2d (x , w , k = None , factor = 2 , gain = 1 ):
44- """Fused `upsample_2d()` followed by `Conv2d()`.
45-
46- Args:
47- Padding is performed only once at the beginning, not between the operations. The fused op is considerably more
48- efficient than performing the same calculation using standard TensorFlow ops. It supports gradients of arbitrary
49- order.
50- x: Input tensor of the shape `[N, C, H, W]` or `[N, H, W,
51- C]`.
52- w: Weight tensor of the shape `[filterH, filterW, inChannels,
53- outChannels]`. Grouped convolution can be performed by `inChannels = x.shape[0] // numGroups`.
54- k: FIR filter of the shape `[firH, firW]` or `[firN]`
55- (separable). The default is `[1] * factor`, which corresponds to nearest-neighbor upsampling.
56- factor: Integer upsampling factor (default: 2). gain: Scaling factor for signal magnitude (default: 1.0).
57-
58- Returns:
59- Tensor of the shape `[N, C, H * factor, W * factor]` or `[N, H * factor, W * factor, C]`, and same datatype as
60- `x`.
61- """
62-
63- assert isinstance (factor , int ) and factor >= 1
64-
65- # Check weight shape.
66- assert len (w .shape ) == 4
67- convH = w .shape [2 ]
68- convW = w .shape [3 ]
69- inC = w .shape [1 ]
70-
71- assert convW == convH
72-
73- # Setup filter kernel.
74- if k is None :
75- k = [1 ] * factor
76- k = _setup_kernel (k ) * (gain * (factor ** 2 ))
77- p = (k .shape [0 ] - factor ) - (convW - 1 )
78-
79- stride = (factor , factor )
80-
81- # Determine data dimensions.
82- stride = [1 , 1 , factor , factor ]
83- output_shape = ((x .shape [2 ] - 1 ) * factor + convH , (x .shape [3 ] - 1 ) * factor + convW )
84- output_padding = (
85- output_shape [0 ] - (x .shape [2 ] - 1 ) * stride [0 ] - convH ,
86- output_shape [1 ] - (x .shape [3 ] - 1 ) * stride [1 ] - convW ,
87- )
88- assert output_padding [0 ] >= 0 and output_padding [1 ] >= 0
89- num_groups = x .shape [1 ] // inC
90-
91- # Transpose weights.
92- w = torch .reshape (w , (num_groups , - 1 , inC , convH , convW ))
93- w = w [..., ::- 1 , ::- 1 ].permute (0 , 2 , 1 , 3 , 4 )
94- w = torch .reshape (w , (num_groups * inC , - 1 , convH , convW ))
95-
96- x = F .conv_transpose2d (x , w , stride = stride , output_padding = output_padding , padding = 0 )
97-
98- return upfirdn2d (x , torch .tensor (k , device = x .device ), pad = ((p + 1 ) // 2 + factor - 1 , p // 2 + 1 ))
99-
100-
101- def _conv_downsample_2d (x , w , k = None , factor = 2 , gain = 1 ):
102- """Fused `Conv2d()` followed by `downsample_2d()`.
103-
104- Args:
105- Padding is performed only once at the beginning, not between the operations. The fused op is considerably more
106- efficient than performing the same calculation using standard TensorFlow ops. It supports gradients of arbitrary
107- order.
108- x: Input tensor of the shape `[N, C, H, W]` or `[N, H, W,
109- C]`.
110- w: Weight tensor of the shape `[filterH, filterW, inChannels,
111- outChannels]`. Grouped convolution can be performed by `inChannels = x.shape[0] // numGroups`.
112- k: FIR filter of the shape `[firH, firW]` or `[firN]`
113- (separable). The default is `[1] * factor`, which corresponds to average pooling.
114- factor: Integer downsampling factor (default: 2). gain: Scaling factor for signal magnitude (default: 1.0).
115-
116- Returns:
117- Tensor of the shape `[N, C, H // factor, W // factor]` or `[N, H // factor, W // factor, C]`, and same datatype
118- as `x`.
119- """
120-
121- assert isinstance (factor , int ) and factor >= 1
122- _outC , _inC , convH , convW = w .shape
123- assert convW == convH
124- if k is None :
125- k = [1 ] * factor
126- k = _setup_kernel (k ) * gain
127- p = (k .shape [0 ] - factor ) + (convW - 1 )
128- s = [factor , factor ]
129- x = upfirdn2d (x , torch .tensor (k , device = x .device ), pad = ((p + 1 ) // 2 , p // 2 ))
130- return F .conv2d (x , w , stride = s , padding = 0 )
131-
132-
13342def _variance_scaling (scale = 1.0 , in_axis = 1 , out_axis = 0 , dtype = torch .float32 , device = "cpu" ):
13443 """Ported from JAX."""
13544 scale = 1e-10 if scale == 0 else scale
@@ -183,46 +92,6 @@ def forward(self, x, y):
18392 raise ValueError (f"Method { self .method } not recognized." )
18493
18594
186- class FirUpsample (nn .Module ):
187- def __init__ (self , channels = None , out_channels = None , use_conv = False , fir_kernel = (1 , 3 , 3 , 1 )):
188- super ().__init__ ()
189- out_channels = out_channels if out_channels else channels
190- if use_conv :
191- self .Conv2d_0 = Conv2d (channels , out_channels , kernel_size = 3 , stride = 1 , padding = 1 )
192- self .use_conv = use_conv
193- self .fir_kernel = fir_kernel
194- self .out_channels = out_channels
195-
196- def forward (self , x ):
197- if self .use_conv :
198- h = _upsample_conv_2d (x , self .Conv2d_0 .weight , k = self .fir_kernel )
199- h = h + self .Conv2d_0 .bias .reshape (1 , - 1 , 1 , 1 )
200- else :
201- h = upsample_2d (x , self .fir_kernel , factor = 2 )
202-
203- return h
204-
205-
206- class FirDownsample (nn .Module ):
207- def __init__ (self , channels = None , out_channels = None , use_conv = False , fir_kernel = (1 , 3 , 3 , 1 )):
208- super ().__init__ ()
209- out_channels = out_channels if out_channels else channels
210- if use_conv :
211- self .Conv2d_0 = self .Conv2d_0 = Conv2d (channels , out_channels , kernel_size = 3 , stride = 1 , padding = 1 )
212- self .fir_kernel = fir_kernel
213- self .use_conv = use_conv
214- self .out_channels = out_channels
215-
216- def forward (self , x ):
217- if self .use_conv :
218- x = _conv_downsample_2d (x , self .Conv2d_0 .weight , k = self .fir_kernel )
219- x = x + self .Conv2d_0 .bias .reshape (1 , - 1 , 1 , 1 )
220- else :
221- x = downsample_2d (x , self .fir_kernel , factor = 2 )
222-
223- return x
224-
225-
22695class NCSNpp (ModelMixin , ConfigMixin ):
22796 """NCSN++ model"""
22897
@@ -313,19 +182,19 @@ def __init__(
313182 AttnBlock = functools .partial (AttentionBlock , overwrite_linear = True , rescale_output_factor = math .sqrt (2.0 ))
314183
315184 if self .fir :
316- Up_sample = functools .partial (FirUpsample , fir_kernel = fir_kernel , use_conv = resamp_with_conv )
185+ Up_sample = functools .partial (FirUpsample2D , fir_kernel = fir_kernel , use_conv = resamp_with_conv )
317186 else :
318- Up_sample = functools .partial (Upsample , name = "Conv2d_0" )
187+ Up_sample = functools .partial (Upsample2D , name = "Conv2d_0" )
319188
320189 if progressive == "output_skip" :
321190 self .pyramid_upsample = Up_sample (channels = None , use_conv = False )
322191 elif progressive == "residual" :
323192 pyramid_upsample = functools .partial (Up_sample , use_conv = True )
324193
325194 if self .fir :
326- Down_sample = functools .partial (FirDownsample , fir_kernel = fir_kernel , use_conv = resamp_with_conv )
195+ Down_sample = functools .partial (FirDownsample2D , fir_kernel = fir_kernel , use_conv = resamp_with_conv )
327196 else :
328- Down_sample = functools .partial (Downsample , padding = 0 , name = "Conv2d_0" )
197+ Down_sample = functools .partial (Downsample2D , padding = 0 , name = "Conv2d_0" )
329198
330199 if progressive_input == "input_skip" :
331200 self .pyramid_downsample = Down_sample (channels = None , use_conv = False )
0 commit comments