231 საკითხავი

Decoding Diffusion Models: Core Concepts და PyTorch კოდი

მიერ Neha Boloor8m2025/05/07
Read on Terminal Reader

Ძალიან გრძელი; Წაკითხვა

დიფუზიის მოდელები არის ტიპის გენერატული მოდელი მანქანური სასწავლოში. ისინი გამოიყენება მაღალი ხარისხის მონაცემების წარმოებისთვის, რომელიც იწყება სუფთა სიჩქარით. მონაცემები დიფუზიის ნაბიჯების მეშვეობით იწყება Markov chain- ის შემდეგ. ეს შემდეგ გადარჩენის მიერ გაწავლოთ კონვერტალური პროცესს.
featured image - Decoding Diffusion Models: Core Concepts და PyTorch კოდი
Neha Boloor HackerNoon profile picture
0-item
1-item

ამ სტატიაში, მე გსურთ შეამოწმოთ დიფუზიის მოდელები, რათა გაძლევთ ძირითადი, ძირითადი ინტელუზიის მათგან, კოდი დაწავლა ძირითადი დიფუზიის მოდელი PyTorch- ში.


Definition:

კონფიგურაცია :

Diffusion modelეს არის ტიპის გენერატული მოდელი მანქანა სასწავლო, გამოიყენება შექმნას მაღალი ხარისხის მონაცემები [გალითად, სურათები] იწყება სუფთა ტუმბოს. მონაცემები არის ხმაური მეშვეობით დიფუზიის ნაბიჯები შემდეგ Markov ქსელის [როგორც ეს არის სერია stochastic მოვლენები, სადაც თითოეული ნაბიჯი დამოკიდებულია წინა დროის ნაბიჯზე] და შემდეგ reconstructed გაწავლოთ შეუზღუდავი პროცესი.


გთხოვთ, შეამოწმეთ, რა არის ძირითადი იდეა დიფუზიის მოდელები. ამ სტატიაში, რომელიც გამოიყენებაDeep Unsupervised Learning გამოყენებით Non-Equilibrium Thermodynamics”[1]ავტორი აცხადებს, რომ ეს არის:

Deep Unsupervised Learning გამოყენებით Non-Equilibrium Thermodynamics


ძირითადი იდეა, რომელიც ეფუძნება non-equilibrium სტატისტიკური ფიზიკისა, არის სისტემურად და slowly გაზიაროს სტრუქტურა მონაცემთა გაზიარების მეშვეობით iterative forward diffusion პროცესი. ჩვენ შემდეგ გაეცნოთ reverse diffusion პროცესი, რომელიც განახლება სტრუქტურა მონაცემები, მიღების მაღალი მოქნილი და ხელმისაწვდომი გენერატული მოდელი მონაცემები.

The essential idea, inspired by non-equilibrium statistical physics, is to systematically and slowly destroy structure in a data distribution through an iterative forward diffusion process. We then learn a reverse diffusion process that restores structure in data, yielding a highly flexible and tractable generative model of the data.


ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო ფართო

  • Forward Diffusion Phase: We start with a real, high-quality image and add noise to it in steps to arrive at pure noise. Basically, we want to destroy the structure in the non-random data distribution that exists at the start. A single step of noise addition in Forward Diffusion can be formulated as this

    Here, q is our forward process, x_t ​ the output of the forward process at time step t, x_(t-1)​ is an input at time step t. N is a normal distribution with sqrt(1 - β_t) x_{t-1} mean and β_tI variance.


    β_t [also called the schedule] here controls the amount of noise added at time step = t whose value ranges from 0→1. Depending on the type of schedule you use, you arrive at what is close to pure noise sooner or later. i.e. β_1,…,β_T is a variance schedule (that is either learned or fixed) which, if well-behaved, ensures that x_T is almost an isotropic Gaussian at sufficiently large T. Visualization of a sample in the forward Diffusion with T=300 and step_size=30 with linear schedule


  • Reverse Diffusion Phase: This is where the actual machine learning takes place. As the name suggests, we try to transform the noise back into a sample from the target distribution in this phase. i.e. the model is learning to denoise pure Gaussian noise into a clean image. Once the neural network has been trained, this ability can be used to generate new images out of Gaussian noise through step-by-step reverse diffusion.

    Since one cannot readily estimate q(x_(t-1)|x_t), we need to learn a model p_theta to approximate the conditional probabilities for the reverse diffusion process.

    Reverse Diffusion Phase model formulation


  • We want to model the probability density of an earlier time step given the current. If we apply this reverse formula for all time steps T→0, we can trace our steps back to the original data distribution. The time step information is provided usually as positional embeddings to the model. It is worth mentioning here that the diffusion model predicts the entire noise to be removed at a given timestep to make it equivalent to the image at the start, and not just the delta between the current and previous time step. However, we only subtract part of it and move to the next step. That is how the diffusion process works.


ძირითადად, დიფუზიის მოდელიdestroys the structure in training dataმას შემდეგ, რაც Gauss- ის სიჩქარე და შემდეგlearns to recoverმას შემდეგ, რაც სასწავლო, მას შეუძლია გამოიყენოთ დიფუზიის მოდელი მონაცემების შექმნა უბრალოდpassing randomly sampled noise through the “learned” denoising processდეტალური მექანიკური აღწერა, შეამოწმეთ ამ დღიურში [4].



Implementation:

განახლება :

ჩვენ გამოიყენებთOxford Flowers102 მონაცემთა კომპლექტი, რომელიც შეიცავს სურათები ფურცელი 102 კატეგორიებში, და შექმნათ ძალიან მარტივი მოდელი ამ სტატიაში, რათა გაიგოთ ძირითადი იდეა და რეპუტაცია დიფუზიის მოდელები.


Forward phase:იმიტომ, რომ Gaussians არის ასევე Gaussians, მიუხედავად იმისა, რომ სიტყვის შემცირება სექციური, ერთი შეიძლება წინასწარ დააკმაყოფილოს სიტყვული ვერსია input სურათის კონკრეტული დროის ნაბიჯი [2].


def linear_beta_schedule(timesteps, start=1e-4, end=2e-2):
    """Creates a linearly increasing noise schedule."""
    return torch.linspace(start, end, timesteps)

def get_idx_from_list(vals, t, x_shape):
    """ Returns a specific index t of a passed list of values vals. """
    batch_size = t.shape[0]
    out = vals.gather(-1, t.cpu())
    return out.reshape(batch_size, *((1,) * (len(x_shape) - 1))).to(t.device)

def forward_diffusion_sample(x_0, t, device="cpu"):
    """ Takes an image and a timestep as input and returns the noisy version of it."""
    noise = torch.randn_like(x_0)
    sqrt_alphas_cumprod_t = get_index_from_list(sqrt_alphas_cumprod, t, x_0.shape)
    sqrt_one_minus_alphas_cumprod_t = get_idx_from_list(sqrt_one_minus_alphas_cumprod, t, x_0.shape)
    return sqrt_alphas_cumprod_t.to(device) * x_0.to(device) + sqrt_one_minus_alphas_cumprod_t.to(device) * noise.to(device), noise.to(device)


T = 300  # Total number of timesteps
betas = linear_beta_schedule(T)
# Precompute values for efficiency
alphas = 1. - betas
alphas_cumprod = torch.cumprod(alphas, dim=0)
alphas_cumprod_prev = F.pad(alphas_cumprod[:-1], (1, 0), value=1.0)

sqrt_recip_alphas = torch.sqrt(1. / alphas)
sqrt_alphas_cumprod = torch.sqrt(alphas_cumprod)
sqrt_one_minus_alphas_cumprod = torch.sqrt(1. - alphas_cumprod)
posterior_variance = betas * (1. - alphas_cumprod_prev) / (1. - alphas_cumprod)


Reverse Diffusion Phase:ეს არის denoising ფაზა, სადაც მოდელი გაიგებს, რომ შეფასოთ ხმა, რომელიც დაამატა თითოეული დრო ნაბიჯში. ჩვენ გამოიყენებთ მარტივი U-Net ნერვული ქსელის, რომელიც იღებს ხმაური სურათი და დრო ნაბიჯ [დაწვრილებით პოზიციური შეფუთვა] და პროგნოზი ხმაური. თითოეულიConvBlockშემდეგი ფართობი იყენებს sinusoidal time step embedding, მოკლე დროის კონტაქტი, რათა შეესაბამება convolutional output. ეს არქიტექტურა ეფუძნება [2] და გაუმჯობესებული ვარიანტი, რომელიც გამოქვეყნდა [3].


class SinusoidalPositionEmbeddings(nn.Module):
    def __init__(self, dim):
        super().__init__()
        self.dim = dim

    def forward(self, t):
        half_dim = self.dim // 2
        scale = math.log(10000) / (half_dim - 1)
        freqs = torch.exp(torch.arange(half_dim, device=t.device) * -scale)
        angles = t[:, None] * freqs[None, :]
        return torch.cat([angles.sin(), angles.cos()], dim=-1)

class ConvBlock(nn.Module):
    def __init__(self, in_channels, out_channels, time_emb_dim, upsample=False):
        super().__init__()
        self.time_mlp = nn.Linear(time_emb_dim, out_channels)
        self.upsample = upsample

        self.conv1 = nn.Conv2d(in_channels * 2 if upsample else in_channels, out_channels, kernel_size=3, padding=1)
        self.transform = (
            nn.ConvTranspose2d(out_channels, out_channels, kernel_size=4, stride=2, padding=1)
            if upsample else
            nn.Conv2d(out_channels, out_channels, kernel_size=4, stride=2, padding=1)
        )
        self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1)
        self.bn1 = nn.BatchNorm2d(out_channels)
        self.bn2 = nn.BatchNorm2d(out_channels)
        self.relu = nn.ReLU()

    def forward(self, x, t):
        h = self.bn1(self.relu(self.conv1(x)))
        time_emb = self.relu(self.time_mlp(t))[(..., ) + (None,) * 2]
        h = h + time_emb
        h = self.bn2(self.relu(self.conv2(h)))
        return self.transform(h)

class SimpleUNet(nn.Module):
    """Simplified U-Net for denoising diffusion models."""

    def __init__(self):
        super().__init__()
        image_channels = 3
        down_channels = (64, 128, 256, 512, 1024)
        up_channels = (1024, 512, 256, 128, 64)
        output_channels = 3
        time_emb_dim = 32

        self.time_mlp = nn.Sequential(
            SinusoidalPositionEmbeddings(time_emb_dim),
            nn.Linear(time_emb_dim, time_emb_dim),
            nn.ReLU()
        )
        self.init_conv = nn.Conv2d(image_channels, down_channels[0], kernel_size=3, padding=1)

        self.down_blocks = nn.ModuleList([
            ConvBlock(down_channels[i], down_channels[i+1], time_emb_dim)
            for i in range(len(down_channels) - 1)
        ])

        self.up_blocks = nn.ModuleList([
            ConvBlock(up_channels[i], up_channels[i+1], time_emb_dim, upsample=True)
            for i in range(len(up_channels) - 1)
        ])

        self.final_conv = nn.Conv2d(up_channels[-1], output_channels, kernel_size=1)

    def forward(self, x, t):
        t_emb = self.time_mlp(t)
        x = self.init_conv(x)
        skip_connections = []

        for block in self.down_blocks:
            x = block(x, t_emb)
            skip_connections.append(x)

        for block in self.up_blocks:
            skip_x = skip_connections.pop()
            x = torch.cat([x, skip_x], dim=1)
            x = block(x, t_emb)
        return self.final_conv(x)

model = SimpleUnet()


სასწავლო მიზანი არის მარტივი MSE დაკარგვა, კომპიუტერული განსხვავება რეალური ხმა და მოდელის პროგნოზი, რომ ხმა.

def get_loss(model, x_0, t, device):
    x_noisy, noise = forward_diffusion_sample(x_0, t, device)
    noise_pred = model(x_noisy, t)
    return F.mse_loss(noise, noise_pred)


საბოლოოდ, მას შემდეგ, რაც მოდელის ტრენინგი 300 ასაკის განმავლობაში, ჩვენ შეგვიძლია დაიწყოს წარმოების ~ რეალისტური-გურცელი სურათები ფურცელი მიერ ნიმუშავების სუფთა Gaussian ტუმბოს და გაფართოების მას მეშვეობით სასწავლო reverse დიფუზიის პროცესში. ქვემოთ რამდენიმე ნიმუშები მე შეუძლიათ შექმნათ ამ გზით. ეს იქნება ღირს ექსპერიმენტი ზოგიერთი ვარიანტი ზემოთ არქიტექტურა, სწავლის სიჩქარე, გრაფიკერი, და რაოდენობის ასაკის ტრენინგი.

Sample output generated

Sample output generated

Sample output generated



References:

  1. Deep Unsupervised Learning გამოყენებით Nonequilibrium Thermodynamics Sohl-Dickstein, J. et al.[2015]
  2. Denialing Diffusion Probabilistic Models Ho et al. [2020]
  3. გაფართოების მოდელები შეხვდა GANs on Image Synthesis Dhariwal და Nichol [2021]
  4. ამ საოცარი დღიურში გაცნობიერად გაცნობიერებს დიფუზიის მოდელები.
  5. ეს repository ხელმისაწვდომია რესურსების კოლექცია და დისპუსის მოდელები.
ამ საოცარი დღიურიეს repository


Trending Topics

blockchaincryptocurrencyhackernoon-top-storyprogrammingsoftware-developmenttechnologystartuphackernoon-booksBitcoinbooks