CoolFace
Modelpublic

wusize/Harmon-0_5B

sourceHugging Faceupdated 1y agoView on Hugging Face
2likes15downloads
diffloss.py250 linesDownload Raw Back to root
1import torch2import torch.nn as nn3from torch.utils.checkpoint import checkpoint4import math5 6from .misc import create_diffusion7 8 9class DiffLoss(nn.Module):10    """Diffusion Loss"""11    def __init__(self, target_channels, z_channels, depth, width, num_sampling_steps, grad_checkpointing=False):12        super(DiffLoss, self).__init__()13        self.in_channels = target_channels14        self.net = SimpleMLPAdaLN(15            in_channels=target_channels,16            model_channels=width,17            out_channels=target_channels * 2,  # for vlb loss18            z_channels=z_channels,19            num_res_blocks=depth,20            grad_checkpointing=grad_checkpointing21        )22 23        self.train_diffusion = create_diffusion(timestep_respacing="", noise_schedule="cosine")24        self.gen_diffusion = create_diffusion(timestep_respacing=num_sampling_steps, noise_schedule="cosine")25 26    def forward(self, target, z, mask=None):27        t = torch.randint(0, self.train_diffusion.num_timesteps, (target.shape[0],), device=target.device)28        model_kwargs = dict(c=z)29        loss_dict = self.train_diffusion.training_losses(self.net, target, t, model_kwargs)30        loss = loss_dict["loss"]31        if mask is not None:32            loss = (loss * mask).sum() / mask.sum()33        return loss.mean()34 35    def sample(self, z, temperature=1.0, cfg=1.0):36        # diffusion loss sampling37        if not cfg == 1.0:38            noise = torch.randn(z.shape[0] // 2, self.in_channels).cuda()39            noise = torch.cat([noise, noise], dim=0)40            model_kwargs = dict(c=z, cfg_scale=cfg)41            sample_fn = self.net.forward_with_cfg42        else:43            noise = torch.randn(z.shape[0], self.in_channels).cuda()44            model_kwargs = dict(c=z)45            sample_fn = self.net.forward46 47        sampled_token_latent = self.gen_diffusion.p_sample_loop(48            sample_fn, noise.shape, noise, clip_denoised=False, model_kwargs=model_kwargs, progress=False,49            temperature=temperature50        )51 52        return sampled_token_latent53 54 55def modulate(x, shift, scale):56    return x * (1 + scale) + shift57 58 59class TimestepEmbedder(nn.Module):60    """61    Embeds scalar timesteps into vector representations.62    """63    def __init__(self, hidden_size, frequency_embedding_size=256):64        super().__init__()65        self.mlp = nn.Sequential(66            nn.Linear(frequency_embedding_size, hidden_size, bias=True),67            nn.SiLU(),68            nn.Linear(hidden_size, hidden_size, bias=True),69        )70        self.frequency_embedding_size = frequency_embedding_size71 72    @staticmethod73    def timestep_embedding(t, dim, max_period=10000):74        """75        Create sinusoidal timestep embeddings.76        :param t: a 1-D Tensor of N indices, one per batch element.77                          These may be fractional.78        :param dim: the dimension of the output.79        :param max_period: controls the minimum frequency of the embeddings.80        :return: an (N, D) Tensor of positional embeddings.81        """82        # https://github.com/openai/glide-text2im/blob/main/glide_text2im/nn.py83        half = dim // 284        freqs = torch.exp(85            -math.log(max_period) * torch.arange(start=0, end=half, dtype=torch.float32) / half86        ).to(device=t.device)87        args = t[:, None].float() * freqs[None]88        embedding = torch.cat([torch.cos(args), torch.sin(args)], dim=-1)89        if dim % 2:90            embedding = torch.cat([embedding, torch.zeros_like(embedding[:, :1])], dim=-1)91        return embedding92 93    def forward(self, t):94        t_freq = self.timestep_embedding(t, self.frequency_embedding_size)95        t_emb = self.mlp(t_freq.to(self.mlp[0].weight.data.dtype))96        return t_emb97 98 99class ResBlock(nn.Module):100    """101    A residual block that can optionally change the number of channels.102    :param channels: the number of input channels.103    """104 105    def __init__(106        self,107        channels108    ):109        super().__init__()110        self.channels = channels111 112        self.in_ln = nn.LayerNorm(channels, eps=1e-6)113        self.mlp = nn.Sequential(114            nn.Linear(channels, channels, bias=True),115            nn.SiLU(),116            nn.Linear(channels, channels, bias=True),117        )118 119        self.adaLN_modulation = nn.Sequential(120            nn.SiLU(),121            nn.Linear(channels, 3 * channels, bias=True)122        )123 124    def forward(self, x, y):125        shift_mlp, scale_mlp, gate_mlp = self.adaLN_modulation(y).chunk(3, dim=-1)126        h = modulate(self.in_ln(x), shift_mlp, scale_mlp)127        h = self.mlp(h)128        return x + gate_mlp * h129 130 131class FinalLayer(nn.Module):132    """133    The final layer adopted from DiT.134    """135    def __init__(self, model_channels, out_channels):136        super().__init__()137        self.norm_final = nn.LayerNorm(model_channels, elementwise_affine=False, eps=1e-6)138        self.linear = nn.Linear(model_channels, out_channels, bias=True)139        self.adaLN_modulation = nn.Sequential(140            nn.SiLU(),141            nn.Linear(model_channels, 2 * model_channels, bias=True)142        )143 144    def forward(self, x, c):145        shift, scale = self.adaLN_modulation(c).chunk(2, dim=-1)146        x = modulate(self.norm_final(x), shift, scale)147        x = self.linear(x)148        return x149 150 151class SimpleMLPAdaLN(nn.Module):152    """153    The MLP for Diffusion Loss.154    :param in_channels: channels in the input Tensor.155    :param model_channels: base channel count for the model.156    :param out_channels: channels in the output Tensor.157    :param z_channels: channels in the condition.158    :param num_res_blocks: number of residual blocks per downsample.159    """160 161    def __init__(162        self,163        in_channels,164        model_channels,165        out_channels,166        z_channels,167        num_res_blocks,168        grad_checkpointing=False169    ):170        super().__init__()171 172        self.in_channels = in_channels173        self.model_channels = model_channels174        self.out_channels = out_channels175        self.num_res_blocks = num_res_blocks176        self.grad_checkpointing = grad_checkpointing177 178        self.time_embed = TimestepEmbedder(model_channels)179        self.cond_embed = nn.Linear(z_channels, model_channels)180 181        self.input_proj = nn.Linear(in_channels, model_channels)182 183        res_blocks = []184        for i in range(num_res_blocks):185            res_blocks.append(ResBlock(186                model_channels,187            ))188 189        self.res_blocks = nn.ModuleList(res_blocks)190        self.final_layer = FinalLayer(model_channels, out_channels)191 192        self.initialize_weights()193 194    def initialize_weights(self):195        def _basic_init(module):196            if isinstance(module, nn.Linear):197                torch.nn.init.xavier_uniform_(module.weight)198                if module.bias is not None:199                    nn.init.constant_(module.bias, 0)200        self.apply(_basic_init)201 202        # Initialize timestep embedding MLP203        nn.init.normal_(self.time_embed.mlp[0].weight, std=0.02)204        nn.init.normal_(self.time_embed.mlp[2].weight, std=0.02)205 206        # Zero-out adaLN modulation layers207        for block in self.res_blocks:208            nn.init.constant_(block.adaLN_modulation[-1].weight, 0)209            nn.init.constant_(block.adaLN_modulation[-1].bias, 0)210 211        # Zero-out output layers212        nn.init.constant_(self.final_layer.adaLN_modulation[-1].weight, 0)213        nn.init.constant_(self.final_layer.adaLN_modulation[-1].bias, 0)214        nn.init.constant_(self.final_layer.linear.weight, 0)215        nn.init.constant_(self.final_layer.linear.bias, 0)216 217    def forward(self, x, t, c):218        """219        Apply the model to an input batch.220        :param x: an [N x C] Tensor of inputs.221        :param t: a 1-D batch of timesteps.222        :param c: conditioning from AR transformer.223        :return: an [N x C] Tensor of outputs.224        """225        # import pdb; pdb.set_trace()226        x = self.input_proj(x.to(self.input_proj.weight.data.dtype))227        t = self.time_embed(t)228        c = self.cond_embed(c.to(self.cond_embed.weight.data.dtype))229 230        y = t + c231 232        if self.grad_checkpointing and not torch.jit.is_scripting():233            for block in self.res_blocks:234                x = checkpoint(block, x, y)235        else:236            for block in self.res_blocks:237                x = block(x, y)238 239        return self.final_layer(x, y)240 241    def forward_with_cfg(self, x, t, c, cfg_scale):242        half = x[: len(x) // 2]243        combined = torch.cat([half, half], dim=0)244        model_out = self.forward(combined, t, c)245        eps, rest = model_out[:, :self.in_channels], model_out[:, self.in_channels:]246        cond_eps, uncond_eps = torch.split(eps, len(eps) // 2, dim=0)247        half_eps = uncond_eps + cfg_scale * (cond_eps - uncond_eps)248        eps = torch.cat([half_eps, half_eps], dim=0)249        return torch.cat([eps, rest], dim=1)250