CoolFace
Apppublic

meng2003/music2dance

sourceHugging Faceupdated 3y agoView on Hugging Face
0likes
flowplusplus.py300 linesDownload Raw Back to flowplusplus
1import math2import torch3import torch.nn as nn4import torch.nn.functional as F5import numpy as np6 7from models.flowplusplus.act_norm import ActNorm, BatchNorm8from models.flowplusplus.inv_conv import InvConv, InvertibleConv1x19from models.flowplusplus.nn import GatedConv10from models.flowplusplus.coupling import Coupling11from models.util import channelwise, checkerboard, Flip, safe_log, squeeze, unsqueeze12 13from models.moglow.modules import GaussianDiag, StudentT14 15class FlowPlusPlus(nn.Module):16    """Flow++ Model17 18    Based on the paper:19    "Flow++: Improving Flow-Based Generative Models20        with Variational Dequantization and Architecture Design"21    by Jonathan Ho, Xi Chen, Aravind Srinivas, Yan Duan, Pieter Abbeel22    (https://openreview.net/forum?id=Hyg74h05tX).23 24    Args:25        scales (tuple or list): Number of each type of coupling layer in each26            scale. Each scale is a 2-tuple of the form27            (num_channelwise, num_checkerboard).28        in_channels (int): Number of channels in the input.29        mid_channels (int): Number of channels in the intermediate layers.30        num_blocks (int): Number of residual blocks in the s and t network of31            `Coupling` layers.32        num_dequant_blocks (int): Number of blocks in the dequantization flows.33    """34    def __init__(self,35                 scales=((0, 4), (2, 3)),36                 in_shape=(3, 32, 32),37                 cond_dim=0,38                 mid_channels=96,39                 num_blocks=10,40                 num_components=32,41                 use_attn=True,42                 use_logmix=True,43                 use_transformer_nn=False,44                 use_pos_emb=False,45                 use_rel_pos_emb=False,46                 num_heads=10,47                 drop_prob=0.2,48                 norm_layer=None,49                 cond_concat_dims=True,50                 cond_seq_len=1,51                 flow_dist="normal",52                 flow_dist_param=50,53                 bn_momentum=0.1):54        super(FlowPlusPlus, self).__init__()55        # Register bounds to pre-process images, not learnable56        self.register_buffer('bounds', torch.tensor([0.9], dtype=torch.float32))57        self.flows = _FlowStep(scales=scales,58                               in_shape=in_shape,59                               cond_dim=cond_dim,60                               mid_channels=mid_channels,61                               num_blocks=num_blocks,62                               num_components=num_components,63                               use_attn=use_attn,64                               use_logmix=use_logmix,65                               use_transformer_nn=use_transformer_nn,66                               use_pos_emb=use_pos_emb,67                               use_rel_pos_emb=use_rel_pos_emb,68                               num_heads=num_heads,69                               drop_prob=drop_prob,70                               norm_layer=norm_layer,71                               cond_concat_dims=cond_concat_dims,72                               cond_seq_len=cond_seq_len,73                               bn_momentum=bn_momentum)74        if flow_dist == "normal":75            self.distribution = GaussianDiag()76        elif flow_dist == "studentT":77            in_channels, in_height, in_width = in_shape78            self.distribution = StudentT(flow_dist_param, in_channels)79 80    def forward(self, x, cond, reverse=False):81        if cond is not None:82            cond = cond.permute(0,2,1).unsqueeze(3)83            84        if not reverse:        85            if x is not None:86                x = x.permute(0,2,1).unsqueeze(3)87        else:88            c, h, w = self.flows.z_dim()89            # x = 1.0*torch.randn((cond.size(0), c, h, w), dtype=torch.float32).type_as(cond)90            eps_std=1.091            # x = self.distribution.sample((cond.size(0), c, h, w), eps_std, device=cond.device).type_as(cond)92            assert w==193            x = self.distribution.sample((cond.size(0), c, h), eps_std, device=cond.device).type_as(cond)94            x = x.unsqueeze(-1)95            # import pdb;pdb.set_trace()96 97        sldj = torch.zeros(x.size(0), device=x.device)98        x, sldj = self.flows(x, cond, sldj, reverse)99        100        if reverse:101            if x is not None:102                x = x.squeeze(3).permute(0,2,1)103 104        return x, sldj105 106    def loss_generative(self, z, sldj):107        """Negative log-likelihood loss assuming isotropic gaussian with unit norm.108 109        Args:110            k (int or float): Number of discrete values in each input dimension.111                E.g., `k` is 256 for natural images.112 113        See Also:114            Equation (3) in the RealNVP paper: https://arxiv.org/abs/1605.08803115        """116        # print(z)117        # prior_ll = -0.5 * (z ** 2 + np.log(2 * np.pi))118        # prior_ll = prior_ll.flatten(1).sum(-1)# \119        prior_ll = self.distribution.logp(z)120        prior_ll = prior_ll.flatten(1).sum(-1)# \121        # import pdb;pdb.set_trace()122#            - np.log(k) * np.prod(z.size()[1:])123        ll = prior_ll + sldj124        # print(sldj.mean())125        # import pdb;pdb.set_trace()126        nll = -ll.mean()/float(np.log(2.) * z.size(2) * z.size(3))127        # nll = -ll.mean()/float(np.log(2.))128 129        return nll130        131class _FlowStep(nn.Module):132    """Recursive builder for a Flow++ model.133 134    Each `_FlowStep` corresponds to a single scale in Flow++.135    The constructor is recursively called to build a full model.136 137    Args:138        scales (tuple): Number of each type of coupling layer in each scale.139            Each scale is a 2-tuple of the form (num_channelwise, num_checkerboard).140        in_channels (int): Number of channels in the input.141        mid_channels (int): Number of channels in the intermediate layers.142        num_blocks (int): Number of residual blocks in the s and t network of143            `Coupling` layers.144        num_components (int): Number of components in the mixture.145        use_attn (bool): Use attention in the coupling layers.146        drop_prob (float): Dropout probability.147    """148    def __init__(self, scales, in_shape, cond_dim, mid_channels, num_blocks, num_components, use_attn, use_logmix, use_transformer_nn, use_pos_emb, use_rel_pos_emb, num_heads, drop_prob, norm_layer, bn_momentum, cond_concat_dims, cond_seq_len):149        super(_FlowStep, self).__init__()150        in_channels, in_height, in_width = in_shape151        num_channelwise, num_checkerboard = scales[0]152        #import pdb;pdb.set_trace()153        channels = []154        for i in range(num_channelwise):155            new_channels = in_channels// 2156            out_channels = in_channels-new_channels157            # print(norm_layer)158            if norm_layer == "batchnorm":159                channels += [BatchNorm(in_channels, bn_momentum)]160            elif norm_layer == "actnorm":161                channels += [ActNorm(in_channels)]162            if cond_concat_dims:163                c_in_channels = new_channels + cond_dim164                seq_length = in_height165            else:166                c_in_channels = new_channels167                seq_length = in_height + cond_seq_len168            channels += [InvertibleConv1x1(in_channels)]169            channels += [Coupling(in_channels=c_in_channels,170                                  cond_dim=cond_dim,171                                  out_channels=out_channels,172                                  mid_channels=mid_channels,173                                  num_blocks=num_blocks,174                                  num_components=num_components,175                                  use_attn=use_attn,176                                  use_logmix=use_logmix,177                                  use_transformer_nn=use_transformer_nn,178                                  use_pos_emb=use_pos_emb,179                                  use_rel_pos_emb=use_rel_pos_emb,180                                  num_heads=num_heads,181                                  seq_length=seq_length,182                                  output_length=in_height,183                                  concat_dims=cond_concat_dims,184                                  drop_prob=drop_prob)]#,185                         #Flip()] Flip currently does not work with odd number of channels. But is it needed when we have channel mixing with 1x1convs? 186 187        checkers = []188        if cond_concat_dims:189            c_in_channels = new_channels + cond_dim190            seq_length = in_height191        else:192            c_in_channels = new_channels193            seq_length = in_height + cond_seq_len194        for i in range(num_checkerboard):195            if norm_layer == "batchnorm":196                checkers += [BatchNorm(in_channels, bn_momentum)]197            elif norm_layer == "actnorm":198                checkers += [ActNorm(in_channels)]199            checkers += [InvertibleConv1x1(in_channels)]200            checkers += [Coupling(in_channels=c_in_channels,201                                  out_channels=in_channels,202                                  mid_channels=mid_channels,203                                  num_blocks=num_blocks,204                                  num_components=num_components,205                                  use_attn=use_attn,206                                  use_logmix=use_logmix,207                                  use_transformer_nn=use_transformer_nn,208                                  use_pos_emb=use_pos_emb,209                                  use_rel_pos_emb=use_rel_pos_emb,210                                  num_heads=num_heads,211                                  seq_length=seq_length,212                                  output_length=in_height,213                                  concat_dims=cond_concat_dims,214                                  drop_prob=drop_prob)]#,215                         #Flip()]216        self.channels = nn.ModuleList(channels) if channels else None217        self.checkers = nn.ModuleList(checkers) if checkers else None218 219        if len(scales) <= 1:220            self.next = None221        else:222            next_shape = (in_channels, in_height // 2, in_width)223            self.next = _FlowStep(scales=scales[1:],224                                  in_shape=next_shape,225                                  cond_dim=2*cond_dim,226                                  mid_channels=mid_channels,227                                  num_blocks=num_blocks,228                                  num_components=num_components,229                                  use_attn=use_attn,230                                  use_logmix=use_logmix,231                                  use_transformer_nn=use_transformer_nn,232                                  use_pos_emb=use_pos_emb,233                                  use_rel_pos_emb=use_rel_pos_emb,234                                  num_heads=num_heads,235                                  norm_layer = norm_layer,236                                  bn_momentum = bn_momentum,237                                  cond_concat_dims = cond_concat_dims,238                                  cond_seq_len = cond_seq_len,239                                  drop_prob=drop_prob)240                                  241        self.z_shape = (in_channels, in_height, in_width)242        243    def z_dim(self):244        return self.z_shape245 246    def forward(self, x, cond, sldj, reverse=False):247            248        if reverse:249            #import pdb;pdb.set_trace()250            if self.next is not None:251                x = squeeze(x)252                cond = squeeze(cond)253                x, x_split = x.chunk(2, dim=1)254                x, sldj = self.next(x, cond, sldj, reverse)255                x = torch.cat((x, x_split), dim=1)256                x = unsqueeze(x)257                cond = unsqueeze(cond)258 259            if self.checkers:260                x = checkerboard(x)261                for flow in reversed(self.checkers):262                    x, sldj = flow(x, cond, sldj, reverse)263                x = checkerboard(x, reverse=True)264 265            if self.channels:266                x = channelwise(x)267                for flow in reversed(self.channels):268                    x, sldj = flow(x, cond, sldj, reverse)269                x = channelwise(x, reverse=True)270        else:271            # import pdb;pdb.set_trace()272            if self.channels:273                x = channelwise(x)274                for flow in self.channels:275                    # import pdb;pdb.set_trace()276                    x, sldj = flow(x, cond, sldj, reverse)277                    # print(type(flow).__name__)278                    # print(x[0].std())279                x = channelwise(x, reverse=True)280 281            if self.checkers:282                x = checkerboard(x)283                for flow in self.checkers:284                    x, sldj = flow(x, cond, sldj, reverse)285                x = checkerboard(x, reverse=True)286 287            if self.next is not None:288                # import pdb;pdb.set_trace()289                # here we apply the flow steps but only to dimensions sampled at a lower scale. Hmm feels a bit weird290                x = squeeze(x)291                cond = squeeze(cond)292                x, x_split = x.chunk(2, dim=1)293                x, sldj = self.next(x, cond, sldj, reverse)294                x = torch.cat((x, x_split), dim=1)295                x = unsqueeze(x)296 297        # print(x.std())298        return x, sldj299        300