Wojtekb30's picture
Upload 11 files
316a030 verified
Raw
History Blame Contribute Delete
4.84 kB
import torch
import torch.nn as nn
import torch.nn.functional as F
class EMAVectorQuantizer(nn.Module):
def __init__(
self,
num_embeddings=512,
embedding_dim=256,
commitment_cost=0.25,
decay=0.99,
epsilon=1e-5,
):
super().__init__()
self.num_embeddings = num_embeddings
self.embedding_dim = embedding_dim
self.commitment_cost = commitment_cost
self.decay = decay
self.epsilon = epsilon
embed = torch.randn(num_embeddings, embedding_dim)
self.register_buffer("embedding", embed)
self.register_buffer("cluster_size", torch.zeros(num_embeddings))
self.register_buffer("ema_w", embed.clone())
def forward(self, z):
z = z.permute(0, 2, 1).contiguous()
z_flattened = z.view(-1, self.embedding_dim)
distances = (
torch.sum(z_flattened**2, dim=1, keepdim=True)
+ torch.sum(self.embedding**2, dim=1)
- 2 * torch.matmul(z_flattened, self.embedding.t())
)
min_encoding_indices = torch.argmin(distances, dim=1)
z_q = F.embedding(min_encoding_indices, self.embedding)
if self.training:
encodings = F.one_hot(min_encoding_indices, self.num_embeddings).float()
self.cluster_size.data.mul_(self.decay).add_(encodings.sum(0), alpha=1 - self.decay)
n = self.cluster_size.sum()
cluster_size = (self.cluster_size + self.epsilon) / (
n + self.num_embeddings * self.epsilon
) * n
dw = torch.matmul(encodings.t(), z_flattened)
self.ema_w.data.mul_(self.decay).add_(dw, alpha=1 - self.decay)
self.embedding.data.copy_(self.ema_w / cluster_size.unsqueeze(1))
loss = self.commitment_cost * F.mse_loss(z_q.detach(), z_flattened)
z_q = z_flattened + (z_q - z_flattened).detach()
z_q = z_q.view(z.shape).permute(0, 2, 1).contiguous()
return z_q, min_encoding_indices.view(z.shape[0], z.shape[1]), loss
class RVQ(nn.Module):
def __init__(self, num_levels=3, num_embeddings=512, embedding_dim=256):
super().__init__()
self.num_levels = num_levels
self.quantizers = nn.ModuleList(
[EMAVectorQuantizer(num_embeddings, embedding_dim) for _ in range(num_levels)]
)
def forward(self, z):
quantized_out = 0
residual = z
all_indices = []
total_loss = 0
for quantizer in self.quantizers:
z_q, indices, loss = quantizer(residual)
quantized_out = quantized_out + z_q
residual = residual - z_q
all_indices.append(indices)
total_loss += loss
return quantized_out, torch.stack(all_indices, dim=1), total_loss
class ResBlock1D(nn.Module):
def __init__(self, channels):
super().__init__()
self.net = nn.Sequential(
nn.Conv1d(channels, channels, kernel_size=3, padding=1),
nn.LeakyReLU(0.2, inplace=True),
nn.Conv1d(channels, channels, kernel_size=3, padding=1),
)
def forward(self, x):
return x + self.net(x)
class MotionEncoder(nn.Module):
def __init__(self, in_channels=263, latent_dim=512):
super().__init__()
self.net = nn.Sequential(
nn.Conv1d(in_channels, 512, kernel_size=3, padding=1),
nn.LeakyReLU(0.2, inplace=True),
ResBlock1D(512),
ResBlock1D(512),
ResBlock1D(512),
nn.Conv1d(512, latent_dim, kernel_size=8, stride=4, padding=2),
)
def forward(self, x):
return self.net(x)
class MotionDecoder(nn.Module):
def __init__(self, latent_dim=512, out_channels=263):
super().__init__()
self.net = nn.Sequential(
nn.ConvTranspose1d(latent_dim, 512, kernel_size=8, stride=4, padding=2),
nn.LeakyReLU(0.2, inplace=True),
ResBlock1D(512),
ResBlock1D(512),
ResBlock1D(512),
nn.Conv1d(512, out_channels, kernel_size=3, padding=1),
)
def forward(self, z_q):
return self.net(z_q)
class MotionRVQ_VAE(nn.Module):
def __init__(self):
super().__init__()
self.encoder = MotionEncoder(in_channels=263, latent_dim=512)
self.rvq = RVQ(num_levels=4, num_embeddings=1024, embedding_dim=512)
self.decoder = MotionDecoder(latent_dim=512, out_channels=263)
def forward(self, x):
z = self.encoder(x)
z_q, token_indices, commitment_loss = self.rvq(z)
x_recon = self.decoder(z_q)
return x_recon, token_indices, commitment_loss