|
|
|
@ -3,15 +3,14 @@ from abc import abstractmethod
|
|
|
|
|
|
|
|
|
|
import numpy as np
|
|
|
|
|
import torch as th
|
|
|
|
|
import torch.nn as nn
|
|
|
|
|
import torch.nn.functional as F
|
|
|
|
|
from torch import nn
|
|
|
|
|
|
|
|
|
|
from imaginairy.modules.attention import SpatialTransformer
|
|
|
|
|
from imaginairy.modules.diffusion.util import (
|
|
|
|
|
avg_pool_nd,
|
|
|
|
|
checkpoint,
|
|
|
|
|
conv_nd,
|
|
|
|
|
linear,
|
|
|
|
|
normalization,
|
|
|
|
|
timestep_embedding,
|
|
|
|
|
zero_module,
|
|
|
|
@ -19,15 +18,14 @@ from imaginairy.modules.diffusion.util import (
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# dummy replace
|
|
|
|
|
def convert_module_to_f16(x):
|
|
|
|
|
def convert_module_to_f16(_):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def convert_module_to_f32(x):
|
|
|
|
|
def convert_module_to_f32(_):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## go
|
|
|
|
|
class AttentionPool2d(nn.Module):
|
|
|
|
|
"""
|
|
|
|
|
Adapted from CLIP: https://github.com/openai/CLIP/blob/main/clip/model.py
|
|
|
|
@ -123,7 +121,7 @@ class Upsample(nn.Module):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TransposedUpsample(nn.Module):
|
|
|
|
|
"Learned 2x upsampling without padding"
|
|
|
|
|
"""Learned 2x upsampling without padding"""
|
|
|
|
|
|
|
|
|
|
def __init__(self, channels, out_channels=None, ks=5):
|
|
|
|
|
super().__init__()
|
|
|
|
@ -229,7 +227,7 @@ class ResBlock(TimestepBlock):
|
|
|
|
|
|
|
|
|
|
self.emb_layers = nn.Sequential(
|
|
|
|
|
nn.SiLU(),
|
|
|
|
|
linear(
|
|
|
|
|
nn.Linear(
|
|
|
|
|
emb_channels,
|
|
|
|
|
2 * self.out_channels if use_scale_shift_norm else self.out_channels,
|
|
|
|
|
),
|
|
|
|
@ -492,7 +490,7 @@ class UNetModel(nn.Module):
|
|
|
|
|
), "Fool!! You forgot to use the spatial transformer for your cross-attention conditioning..."
|
|
|
|
|
from omegaconf.listconfig import ListConfig
|
|
|
|
|
|
|
|
|
|
if type(context_dim) == ListConfig:
|
|
|
|
|
if isinstance(context_dim, ListConfig):
|
|
|
|
|
context_dim = list(context_dim)
|
|
|
|
|
|
|
|
|
|
if num_heads_upsample == -1:
|
|
|
|
@ -527,9 +525,9 @@ class UNetModel(nn.Module):
|
|
|
|
|
|
|
|
|
|
time_embed_dim = model_channels * 4
|
|
|
|
|
self.time_embed = nn.Sequential(
|
|
|
|
|
linear(model_channels, time_embed_dim),
|
|
|
|
|
nn.Linear(model_channels, time_embed_dim),
|
|
|
|
|
nn.SiLU(),
|
|
|
|
|
linear(time_embed_dim, time_embed_dim),
|
|
|
|
|
nn.Linear(time_embed_dim, time_embed_dim),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if self.num_classes is not None:
|
|
|
|
@ -786,223 +784,5 @@ class UNetModel(nn.Module):
|
|
|
|
|
h = h.type(x.dtype)
|
|
|
|
|
if self.predict_codebook_ids:
|
|
|
|
|
return self.id_predictor(h)
|
|
|
|
|
else:
|
|
|
|
|
return self.out(h)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class EncoderUNetModel(nn.Module):
|
|
|
|
|
"""
|
|
|
|
|
The half UNet model with attention and timestep embedding.
|
|
|
|
|
For usage, see UNet.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
def __init__(
|
|
|
|
|
self,
|
|
|
|
|
image_size,
|
|
|
|
|
in_channels,
|
|
|
|
|
model_channels,
|
|
|
|
|
out_channels,
|
|
|
|
|
num_res_blocks,
|
|
|
|
|
attention_resolutions,
|
|
|
|
|
dropout=0,
|
|
|
|
|
channel_mult=(1, 2, 4, 8),
|
|
|
|
|
conv_resample=True,
|
|
|
|
|
dims=2,
|
|
|
|
|
use_checkpoint=False,
|
|
|
|
|
use_fp16=False,
|
|
|
|
|
num_heads=1,
|
|
|
|
|
num_head_channels=-1,
|
|
|
|
|
num_heads_upsample=-1,
|
|
|
|
|
use_scale_shift_norm=False,
|
|
|
|
|
resblock_updown=False,
|
|
|
|
|
use_new_attention_order=False,
|
|
|
|
|
pool="adaptive",
|
|
|
|
|
*args,
|
|
|
|
|
**kwargs,
|
|
|
|
|
):
|
|
|
|
|
super().__init__()
|
|
|
|
|
|
|
|
|
|
if num_heads_upsample == -1:
|
|
|
|
|
num_heads_upsample = num_heads
|
|
|
|
|
|
|
|
|
|
self.in_channels = in_channels
|
|
|
|
|
self.model_channels = model_channels
|
|
|
|
|
self.out_channels = out_channels
|
|
|
|
|
self.num_res_blocks = num_res_blocks
|
|
|
|
|
self.attention_resolutions = attention_resolutions
|
|
|
|
|
self.dropout = dropout
|
|
|
|
|
self.channel_mult = channel_mult
|
|
|
|
|
self.conv_resample = conv_resample
|
|
|
|
|
self.use_checkpoint = use_checkpoint
|
|
|
|
|
self.dtype = th.float16 if use_fp16 else th.float32
|
|
|
|
|
self.num_heads = num_heads
|
|
|
|
|
self.num_head_channels = num_head_channels
|
|
|
|
|
self.num_heads_upsample = num_heads_upsample
|
|
|
|
|
|
|
|
|
|
time_embed_dim = model_channels * 4
|
|
|
|
|
self.time_embed = nn.Sequential(
|
|
|
|
|
linear(model_channels, time_embed_dim),
|
|
|
|
|
nn.SiLU(),
|
|
|
|
|
linear(time_embed_dim, time_embed_dim),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
self.input_blocks = nn.ModuleList(
|
|
|
|
|
[
|
|
|
|
|
TimestepEmbedSequential(
|
|
|
|
|
conv_nd(dims, in_channels, model_channels, 3, padding=1)
|
|
|
|
|
)
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
self._feature_size = model_channels
|
|
|
|
|
input_block_chans = [model_channels]
|
|
|
|
|
ch = model_channels
|
|
|
|
|
ds = 1
|
|
|
|
|
for level, mult in enumerate(channel_mult):
|
|
|
|
|
for _ in range(num_res_blocks):
|
|
|
|
|
layers = [
|
|
|
|
|
ResBlock(
|
|
|
|
|
ch,
|
|
|
|
|
time_embed_dim,
|
|
|
|
|
dropout,
|
|
|
|
|
out_channels=mult * model_channels,
|
|
|
|
|
dims=dims,
|
|
|
|
|
use_checkpoint=use_checkpoint,
|
|
|
|
|
use_scale_shift_norm=use_scale_shift_norm,
|
|
|
|
|
)
|
|
|
|
|
]
|
|
|
|
|
ch = mult * model_channels
|
|
|
|
|
if ds in attention_resolutions:
|
|
|
|
|
layers.append(
|
|
|
|
|
AttentionBlock(
|
|
|
|
|
ch,
|
|
|
|
|
use_checkpoint=use_checkpoint,
|
|
|
|
|
num_heads=num_heads,
|
|
|
|
|
num_head_channels=num_head_channels,
|
|
|
|
|
use_new_attention_order=use_new_attention_order,
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
self.input_blocks.append(TimestepEmbedSequential(*layers))
|
|
|
|
|
self._feature_size += ch
|
|
|
|
|
input_block_chans.append(ch)
|
|
|
|
|
if level != len(channel_mult) - 1:
|
|
|
|
|
out_ch = ch
|
|
|
|
|
self.input_blocks.append(
|
|
|
|
|
TimestepEmbedSequential(
|
|
|
|
|
ResBlock(
|
|
|
|
|
ch,
|
|
|
|
|
time_embed_dim,
|
|
|
|
|
dropout,
|
|
|
|
|
out_channels=out_ch,
|
|
|
|
|
dims=dims,
|
|
|
|
|
use_checkpoint=use_checkpoint,
|
|
|
|
|
use_scale_shift_norm=use_scale_shift_norm,
|
|
|
|
|
down=True,
|
|
|
|
|
)
|
|
|
|
|
if resblock_updown
|
|
|
|
|
else Downsample(
|
|
|
|
|
ch, conv_resample, dims=dims, out_channels=out_ch
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
ch = out_ch
|
|
|
|
|
input_block_chans.append(ch)
|
|
|
|
|
ds *= 2
|
|
|
|
|
self._feature_size += ch
|
|
|
|
|
|
|
|
|
|
self.middle_block = TimestepEmbedSequential(
|
|
|
|
|
ResBlock(
|
|
|
|
|
ch,
|
|
|
|
|
time_embed_dim,
|
|
|
|
|
dropout,
|
|
|
|
|
dims=dims,
|
|
|
|
|
use_checkpoint=use_checkpoint,
|
|
|
|
|
use_scale_shift_norm=use_scale_shift_norm,
|
|
|
|
|
),
|
|
|
|
|
AttentionBlock(
|
|
|
|
|
ch,
|
|
|
|
|
use_checkpoint=use_checkpoint,
|
|
|
|
|
num_heads=num_heads,
|
|
|
|
|
num_head_channels=num_head_channels,
|
|
|
|
|
use_new_attention_order=use_new_attention_order,
|
|
|
|
|
),
|
|
|
|
|
ResBlock(
|
|
|
|
|
ch,
|
|
|
|
|
time_embed_dim,
|
|
|
|
|
dropout,
|
|
|
|
|
dims=dims,
|
|
|
|
|
use_checkpoint=use_checkpoint,
|
|
|
|
|
use_scale_shift_norm=use_scale_shift_norm,
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
self._feature_size += ch
|
|
|
|
|
self.pool = pool
|
|
|
|
|
if pool == "adaptive":
|
|
|
|
|
self.out = nn.Sequential(
|
|
|
|
|
normalization(ch),
|
|
|
|
|
nn.SiLU(),
|
|
|
|
|
nn.AdaptiveAvgPool2d((1, 1)),
|
|
|
|
|
zero_module(conv_nd(dims, ch, out_channels, 1)),
|
|
|
|
|
nn.Flatten(),
|
|
|
|
|
)
|
|
|
|
|
elif pool == "attention":
|
|
|
|
|
assert num_head_channels != -1
|
|
|
|
|
self.out = nn.Sequential(
|
|
|
|
|
normalization(ch),
|
|
|
|
|
nn.SiLU(),
|
|
|
|
|
AttentionPool2d(
|
|
|
|
|
(image_size // ds), ch, num_head_channels, out_channels
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
elif pool == "spatial":
|
|
|
|
|
self.out = nn.Sequential(
|
|
|
|
|
nn.Linear(self._feature_size, 2048),
|
|
|
|
|
nn.ReLU(),
|
|
|
|
|
nn.Linear(2048, self.out_channels),
|
|
|
|
|
)
|
|
|
|
|
elif pool == "spatial_v2":
|
|
|
|
|
self.out = nn.Sequential(
|
|
|
|
|
nn.Linear(self._feature_size, 2048),
|
|
|
|
|
normalization(2048),
|
|
|
|
|
nn.SiLU(),
|
|
|
|
|
nn.Linear(2048, self.out_channels),
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
raise NotImplementedError(f"Unexpected {pool} pooling")
|
|
|
|
|
|
|
|
|
|
def convert_to_fp16(self):
|
|
|
|
|
"""
|
|
|
|
|
Convert the torso of the model to float16.
|
|
|
|
|
"""
|
|
|
|
|
self.input_blocks.apply(convert_module_to_f16)
|
|
|
|
|
self.middle_block.apply(convert_module_to_f16)
|
|
|
|
|
|
|
|
|
|
def convert_to_fp32(self):
|
|
|
|
|
"""
|
|
|
|
|
Convert the torso of the model to float32.
|
|
|
|
|
"""
|
|
|
|
|
self.input_blocks.apply(convert_module_to_f32)
|
|
|
|
|
self.middle_block.apply(convert_module_to_f32)
|
|
|
|
|
|
|
|
|
|
def forward(self, x, timesteps):
|
|
|
|
|
"""
|
|
|
|
|
Apply the model to an input batch.
|
|
|
|
|
:param x: an [N x C x ...] Tensor of inputs.
|
|
|
|
|
:param timesteps: a 1-D batch of timesteps.
|
|
|
|
|
:return: an [N x K] Tensor of outputs.
|
|
|
|
|
"""
|
|
|
|
|
emb = self.time_embed(timestep_embedding(timesteps, self.model_channels))
|
|
|
|
|
|
|
|
|
|
results = []
|
|
|
|
|
h = x.type(self.dtype)
|
|
|
|
|
for module in self.input_blocks:
|
|
|
|
|
h = module(h, emb)
|
|
|
|
|
if self.pool.startswith("spatial"):
|
|
|
|
|
results.append(h.type(x.dtype).mean(dim=(2, 3)))
|
|
|
|
|
h = self.middle_block(h, emb)
|
|
|
|
|
if self.pool.startswith("spatial"):
|
|
|
|
|
results.append(h.type(x.dtype).mean(dim=(2, 3)))
|
|
|
|
|
h = th.cat(results, axis=-1)
|
|
|
|
|
return self.out(h)
|
|
|
|
|
else:
|
|
|
|
|
h = h.type(x.dtype)
|
|
|
|
|
return self.out(h)
|
|
|
|
|
return self.out(h)
|
|
|
|
|