jcm/models/ncsnv2.py (279 lines of code) (raw):

# coding=utf-8 # Copyright 2020 The Google Research Authors. # # 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. # pylint: skip-file """The NCSNv2 model.""" import flax.linen as nn import functools from .utils import register_model from .layers import ( CondRefineBlock, RefineBlock, ResidualBlock, ncsn_conv3x3, ConditionalResidualBlock, get_act, ) from .normalization import get_normalization import ml_collections CondResidualBlock = ConditionalResidualBlock conv3x3 = ncsn_conv3x3 def get_network(config): if config.data.image_size < 96: return functools.partial(NCSNv2, config=config) elif 96 <= config.data.image_size <= 128: return functools.partial(NCSNv2_128, config=config) elif 128 < config.data.image_size <= 256: return functools.partial(NCSNv2_256, config=config) else: raise NotImplementedError( f"No network suitable for {config.data.image_size}px implemented yet." ) @register_model(name="ncsnv2_64") class NCSNv2(nn.Module): """NCSNv2 model architecture.""" config: ml_collections.ConfigDict @nn.compact def __call__(self, x, labels, train=True): # config parsing config = self.config nf = config.model.nf act = get_act(config) normalizer = get_normalization(config) interpolation = config.model.interpolation if not config.data.centered: h = 2 * x - 1.0 else: h = x h = conv3x3(h, nf, stride=1, bias=True) # ResNet backbone h = ResidualBlock(nf, resample=None, act=act, normalization=normalizer)(h) layer1 = ResidualBlock(nf, resample=None, act=act, normalization=normalizer)(h) h = ResidualBlock(2 * nf, resample="down", act=act, normalization=normalizer)( layer1 ) layer2 = ResidualBlock( 2 * nf, resample=None, act=act, normalization=normalizer )(h) h = ResidualBlock( 2 * nf, resample="down", act=act, normalization=normalizer, dilation=2 )(layer2) layer3 = ResidualBlock( 2 * nf, resample=None, act=act, normalization=normalizer, dilation=2 )(h) h = ResidualBlock( 2 * nf, resample="down", act=act, normalization=normalizer, dilation=4 )(layer3) layer4 = ResidualBlock( 2 * nf, resample=None, act=act, normalization=normalizer, dilation=4 )(h) # U-Net with RefineBlocks ref1 = RefineBlock( layer4.shape[1:3], 2 * nf, act=act, interpolation=interpolation, start=True )([layer4]) ref2 = RefineBlock( layer3.shape[1:3], 2 * nf, interpolation=interpolation, act=act )([layer3, ref1]) ref3 = RefineBlock( layer2.shape[1:3], 2 * nf, interpolation=interpolation, act=act )([layer2, ref2]) ref4 = RefineBlock( layer1.shape[1:3], nf, interpolation=interpolation, act=act, end=True )([layer1, ref3]) h = normalizer()(ref4) h = act(h) h = conv3x3(h, x.shape[-1]) return h @register_model(name="ncsn") class NCSN(nn.Module): """NCSNv1 model architecture.""" config: ml_collections.ConfigDict @nn.compact def __call__(self, x, labels, train=True): # config parsing config = self.config nf = config.model.nf act = get_act(config) normalizer = get_normalization(config, conditional=True) interpolation = config.model.interpolation if not config.data.centered: h = 2 * x - 1.0 else: h = x h = conv3x3(h, nf, stride=1, bias=True) # ResNet backbone h = CondResidualBlock(nf, resample=None, act=act, normalization=normalizer)( h, labels ) layer1 = CondResidualBlock( nf, resample=None, act=act, normalization=normalizer )(h, labels) h = CondResidualBlock( 2 * nf, resample="down", act=act, normalization=normalizer )(layer1, labels) layer2 = CondResidualBlock( 2 * nf, resample=None, act=act, normalization=normalizer )(h, labels) h = CondResidualBlock( 2 * nf, resample="down", act=act, normalization=normalizer, dilation=2 )(layer2, labels) layer3 = CondResidualBlock( 2 * nf, resample=None, act=act, normalization=normalizer, dilation=2 )(h, labels) h = CondResidualBlock( 2 * nf, resample="down", act=act, normalization=normalizer, dilation=4 )(layer3, labels) layer4 = CondResidualBlock( 2 * nf, resample=None, act=act, normalization=normalizer, dilation=4 )(h, labels) # U-Net with RefineBlocks ref1 = CondRefineBlock( layer4.shape[1:3], 2 * nf, act=act, normalizer=normalizer, interpolation=interpolation, start=True, )([layer4], labels) ref2 = CondRefineBlock( layer3.shape[1:3], 2 * nf, normalizer=normalizer, interpolation=interpolation, act=act, )([layer3, ref1], labels) ref3 = CondRefineBlock( layer2.shape[1:3], 2 * nf, normalizer=normalizer, interpolation=interpolation, act=act, )([layer2, ref2], labels) ref4 = CondRefineBlock( layer1.shape[1:3], nf, normalizer=normalizer, interpolation=interpolation, act=act, end=True, )([layer1, ref3], labels) h = normalizer()(ref4, labels) h = act(h) h = conv3x3(h, x.shape[-1]) return h @register_model(name="ncsnv2_128") class NCSNv2_128(nn.Module): # pylint: disable=invalid-name """NCSNv2 model architecture for 128px images.""" config: ml_collections.ConfigDict @nn.compact def __call__(self, x, labels, train=True): # config parsing config = self.config nf = config.model.nf act = get_act(config) normalizer = get_normalization(config) interpolation = config.model.interpolation if not config.data.centered: h = 2 * x - 1.0 else: h = x h = conv3x3(h, nf, stride=1, bias=True) # ResNet backbone h = ResidualBlock(nf, resample=None, act=act, normalization=normalizer)(h) layer1 = ResidualBlock(nf, resample=None, act=act, normalization=normalizer)(h) h = ResidualBlock(2 * nf, resample="down", act=act, normalization=normalizer)( layer1 ) layer2 = ResidualBlock( 2 * nf, resample=None, act=act, normalization=normalizer )(h) h = ResidualBlock(2 * nf, resample="down", act=act, normalization=normalizer)( layer2 ) layer3 = ResidualBlock( 2 * nf, resample=None, act=act, normalization=normalizer )(h) h = ResidualBlock( 4 * nf, resample="down", act=act, normalization=normalizer, dilation=2 )(layer3) layer4 = ResidualBlock( 4 * nf, resample=None, act=act, normalization=normalizer, dilation=2 )(h) h = ResidualBlock( 4 * nf, resample="down", act=act, normalization=normalizer, dilation=4 )(layer4) layer5 = ResidualBlock( 4 * nf, resample=None, act=act, normalization=normalizer, dilation=4 )(h) # U-Net with RefineBlocks ref1 = RefineBlock( layer5.shape[1:3], 4 * nf, interpolation=interpolation, act=act, start=True )([layer5]) ref2 = RefineBlock( layer4.shape[1:3], 2 * nf, interpolation=interpolation, act=act )([layer4, ref1]) ref3 = RefineBlock( layer3.shape[1:3], 2 * nf, interpolation=interpolation, act=act )([layer3, ref2]) ref4 = RefineBlock(layer2.shape[1:3], nf, interpolation=interpolation, act=act)( [layer2, ref3] ) ref5 = RefineBlock( layer1.shape[1:3], nf, interpolation=interpolation, act=act, end=True )([layer1, ref4]) h = normalizer()(ref5) h = act(h) h = conv3x3(h, x.shape[-1]) return h @register_model(name="ncsnv2_256") class NCSNv2_256(nn.Module): # pylint: disable=invalid-name """NCSNv2 model architecture for 256px images.""" config: ml_collections.ConfigDict @nn.compact def __call__(self, x, labels, train=True): # config parsing config = self.config nf = config.model.nf act = get_act(config) normalizer = get_normalization(config) interpolation = config.model.interpolation if not config.data.centered: h = 2 * x - 1.0 else: h = x h = conv3x3(h, nf, stride=1, bias=True) # ResNet backbone h = ResidualBlock(nf, resample=None, act=act, normalization=normalizer)(h) layer1 = ResidualBlock(nf, resample=None, act=act, normalization=normalizer)(h) h = ResidualBlock(2 * nf, resample="down", act=act, normalization=normalizer)( layer1 ) layer2 = ResidualBlock( 2 * nf, resample=None, act=act, normalization=normalizer )(h) h = ResidualBlock(2 * nf, resample="down", act=act, normalization=normalizer)( layer2 ) layer3 = ResidualBlock( 2 * nf, resample=None, act=act, normalization=normalizer )(h) h = ResidualBlock(2 * nf, resample="down", act=act, normalization=normalizer)( layer3 ) layer31 = ResidualBlock( 2 * nf, resample=None, act=act, normalization=normalizer )(h) h = ResidualBlock( 4 * nf, resample="down", act=act, normalization=normalizer, dilation=2 )(layer31) layer4 = ResidualBlock( 4 * nf, resample=None, act=act, normalization=normalizer, dilation=2 )(h) h = ResidualBlock( 4 * nf, resample="down", act=act, normalization=normalizer, dilation=4 )(layer4) layer5 = ResidualBlock( 4 * nf, resample=None, act=act, normalization=normalizer, dilation=4 )(h) # U-Net with RefineBlocks ref1 = RefineBlock( layer5.shape[1:3], 4 * nf, interpolation=interpolation, act=act, start=True )([layer5]) ref2 = RefineBlock( layer4.shape[1:3], 2 * nf, interpolation=interpolation, act=act )([layer4, ref1]) ref31 = RefineBlock( layer31.shape[1:3], 2 * nf, interpolation=interpolation, act=act )([layer31, ref2]) ref3 = RefineBlock( layer3.shape[1:3], 2 * nf, interpolation=interpolation, act=act )([layer3, ref31]) ref4 = RefineBlock(layer2.shape[1:3], nf, interpolation=interpolation, act=act)( [layer2, ref3] ) ref5 = RefineBlock( layer1.shape[1:3], nf, interpolation=interpolation, act=act, end=True )([layer1, ref4]) h = normalizer()(ref5) h = act(h) h = conv3x3(h, x.shape[-1]) return h