Spaces:
Sleeping
Sleeping
File size: 7,366 Bytes
f458392 36ddeb2 f458392 f7f03ea f458392 f7f03ea b147273 f7f03ea f458392 f7f03ea f458392 f7f03ea f458392 f7f03ea 44be7f5 f7f03ea f458392 f7f03ea f458392 f7f03ea f458392 f7f03ea 1c37637 f7f03ea 1c37637 f7f03ea 1c37637 f7f03ea 1c37637 f7f03ea 1c37637 f7f03ea 1c37637 f7f03ea 1c37637 fee5b68 f7f03ea fee5b68 834bff8 fee5b68 f7f03ea fee5b68 629a11e f7f03ea 629a11e f7f03ea 629a11e f7f03ea 629a11e f7f03ea 629a11e f7f03ea 629a11e f7f03ea 629a11e f7f03ea 629a11e f7f03ea 629a11e f7f03ea 629a11e f7f03ea 629a11e f7f03ea 629a11e f7f03ea 629a11e f7f03ea 9596f34 f7f03ea 9596f34 f7f03ea 9596f34 f7f03ea 9596f34 f7f03ea 9596f34 f7f03ea 9596f34 f7f03ea 9596f34 f7f03ea 9596f34 f7f03ea 9596f34 f7f03ea 9596f34 f7f03ea 9122c78 f7f03ea 9122c78 f7f03ea 9122c78 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | import torch
import torch.nn as nn
import math
#Varicence scheduler
T = 1000
beta_start = 1e-4
beta_end = 0.02
betas = torch.linspace(beta_start, beta_end, steps=T)
alphas = 1. - betas
alphas_cumprod = torch.cumprod(alphas, dim=0)
#SinusoidalPositionEmbedding
class SinusoidalPositionEmbeddings(torch.nn.Module):
def __init__(self, dim:int):
super().__init__()
assert dim % 2 == 0, "Embedding must divisble by 2"
self.dim = dim
def forward(self, time_stamps: torch.Tensor) -> torch.Tensor :
device = time_stamps.device
half_dim = self.dim // 2
scale = math.log(10000)/ (half_dim - 1)
freqs= torch.exp(torch.arange(half_dim, dtype=torch.float32, device=device) * -scale)
embeddings = time_stamps[:, None].float() * freqs[None, :]
embeddings = torch.cat((embeddings.sin(), embeddings.cos()), dim=-1)
return embeddings
#Time Embeddings
class Time_embeddings(torch.nn.Module):
def __init__(self, time_emb_dim: int, out_dim: int):
super().__init__()
self.sinusoidal_emb = SinusoidalPositionEmbeddings(time_emb_dim)
self.mlp = nn.Sequential(
nn.Linear(time_emb_dim, out_dim),
nn.SiLU(),
nn.Linear(out_dim, out_dim)
)
def forward (self, time_steps: torch.Tensor) -> torch.Tensor :
raw_emb = self.sinusoidal_emb(time_steps)
return self.mlp(raw_emb)
#Resblock
class ResBlock(torch.nn.Module):
def __init__(self, in_channels, out_channels, time_emb_dim):
super().__init__()
self.conv1 = nn.Conv2d(in_channels, out_channels, 3, padding=1)
self.conv2 = nn.Conv2d(out_channels, out_channels, 3, padding=1)
self.norm1 = nn.GroupNorm(8, out_channels)
self.norm2 = nn.GroupNorm(8, out_channels)
self.act = nn.SiLU()
self.time_mlp = nn.Linear(time_emb_dim, out_channels)
#Matches in_channels and out_channels for skip connections
self.residual_conv = nn.Conv2d(in_channels, out_channels, 1) if in_channels != out_channels else nn.Identity()
def forward(self, x, time_emb):
h = self.norm1(self.conv1(x))
h = self.act(h)
# inject time embedding β shape (B, out_channels) β (B, out_channels, 1, 1)
time_proj = self.act(self.time_mlp(time_emb))[:, :, None, None]
h = h + time_proj
h = self.norm2(self.conv2(h))
h = self.act(h)
return h + self.residual_conv(x)
#Downsmaple and upsmaple
class Down_sample(torch.nn.Module):
def __init__(self, channels):
super().__init__()
self.conv = nn.Conv2d(channels, channels, 4, stride=2, padding=1)
def forward(self, x):
return self.conv(x)
class Up_sample(torch.nn.Module):
def __init__(self, channels):
super().__init__()
self.conv = nn.ConvTranspose2d(channels, channels, 4, stride=2, padding=1)
def forward(self, x):
return self.conv(x)
#Assembling Unet class
class Unet(nn.Module):
def __init__(self, in_channels=3, time_emb_dim=128):
super().__init__()
# time embedding outputs 256-dim vector
self.time_embeddings = Time_embeddings(time_emb_dim, out_dim=256)
self.inc = nn.Conv2d(in_channels, 64, 3, padding=1)
# Encoder
self.down1 = ResBlock(64, 128, time_emb_dim=256)
self.down_sample1 = Down_sample(128)
self.down2 = ResBlock(128, 256, time_emb_dim=256)
self.down_sample2 = Down_sample(256)
# Bottleneck
self.bot1 = ResBlock(256, 256, time_emb_dim=256)
self.bot2 = ResBlock(256, 256, time_emb_dim=256)
# Decoder (input channels doubled due to skip connection concat)
self.up_sample1 = Up_sample(256)
self.up1 = ResBlock(512, 128, time_emb_dim=256) # 256 + 256 = 512
self.up_sample2 = Up_sample(128)
self.up2 = ResBlock(256, 64, time_emb_dim=256) # 128 + 128 = 256
self.outc = nn.Conv2d(64, in_channels, 3, padding=1)
def forward(self, x, t):
t_emb = self.time_embeddings(t) # (B,) β (B, 256)
# Encoder
x1 = self.inc(x) # (B, 64, 64, 64)
x2 = self.down1(x1, t_emb) # (B, 128, 64, 64)
x3 = self.down_sample1(x2) # (B, 128, 32, 32)
x4 = self.down2(x3, t_emb) # (B, 256, 32, 32)
x5 = self.down_sample2(x4) # (B, 256, 16, 16)
# Bottleneck
x5 = self.bot1(x5, t_emb) # (B, 256, 16, 16)
x5 = self.bot2(x5, t_emb) # (B, 256, 16, 16)
# Decoder
x6 = self.up_sample1(x5) # (B, 256, 32, 32)
x6 = torch.cat([x6, x4], dim=1) # (B, 512, 32, 32) β skip from x4
x6 = self.up1(x6, t_emb) # (B, 128, 32, 32)
x7 = self.up_sample2(x6) # (B, 128, 64, 64)
x7 = torch.cat([x7, x2], dim=1) # (B, 256, 64, 64) β skip from x2
x7 = self.up2(x7, t_emb) # (B, 64, 64, 64)
return self.outc(x7) # (B, 3, 64, 64)
#EMA weights
class EMA():
def __init__(self ,model ,decay=0.9999):
self.model = model
self.decay = decay
self.shadow = {}
self.backup = {}
def register(self):
for name, param in self.model.named_parameters():
if param.requires_grad:
self.shadow[name] = param.data.clone()
def update(self):
for name , param in self.model.named_parameters():
if param.requires_grad:
assert name in self.shadow
new_avg = self.decay*self.shadow[name] + (1. - self.decay)*param.data
self.shadow[name] = new_avg.clone()
def apply_shadow(self):
for name , param in self.model.named_parameters():
if param.requires_grad:
assert name in self.shadow
self.backup[name] = param.data.clone()
param.data.copy_(self.shadow[name])
def restore(self):
for name, param in self.model.named_parameters():
if param.requires_grad:
assert name in self.backup
param.data.copy_(self.backup[name])
self.backup = {}
#DDIM
@torch.no_grad()
def sample_ddim(model, T,img_size, batch_size=16, channels=3,ddim_step=50, device='cpu'):
model.eval()
alphas_cumprod_device = alphas_cumprod.to(device)
timestep = torch.linspace(0, T-1, steps=ddim_step, dtype=torch.long, device=device)
img = torch.randn(batch_size, channels, img_size, img_size).to(device)
for i in reversed(range(len(timestep))):
t_current =timestep[i]
t_preq = timestep[i-1] if i > 0 else -1
t_tensor = torch.full((batch_size,), t_current, dtype=torch.long, device=device)
pred_noise = model(img , t_tensor)
alphas_bar_t = alphas_cumprod[t_current]
alphas_bar_t_preq = alphas_cumprod[t_preq] if t_preq >= 0 else torch.tensor(1.0, device=device)
pred_x0 = (img - torch.sqrt(1 - alphas_bar_t) * pred_noise)/(torch.sqrt(alphas_bar_t))
pred_x0 = torch.clamp(pred_x0, -1.0, 1.0)
pred_dir = torch.sqrt(1 - alphas_bar_t_preq) * pred_noise
img = torch.sqrt(alphas_bar_t_preq) * pred_x0 + pred_dir
return img |