GAN menghasilkan sampel tajam tetapi membayar mahal dalam hal kestabilan: dua jaringan yang saling berhadapan membuat training mudah goyah, sebagaimana kita lihat pada chapter Stabilitas Training GAN . Diffusion model menempuh jalur yang sama sekali berbeda: alih-alih mempertemukan dua model dalam satu permainan, diffusion merusak data secara bertahap dengan derau Gaussian sampai tersisa derau murni, lalu melatih satu jaringan untuk membalik proses tersebut langkah demi langkah. Training-nya menjadi masalah regresi biasa — memprediksi derau yang ditambahkan — sehingga jauh lebih stabil, dan kualitas sampelnya kini menjadi acuan industri. Chapter ini memperkenalkan gagasan besarnya lewat perbandingan keluarga model generatif dan demonstrasi nyata pada sinyal 1D.

Posisi Diffusion di antara Keluarga Model Generatif #

Ketiga keluarga besar yang telah kita bahas — VAE, GAN, dan kini diffusion — menyelesaikan masalah yang sama dengan mekanisme belajar yang berbeda. Tabel berikut merangkum posisi masing-masing:

AspekVAEGANDiffusion
Cara belajarrekonstruksi + regularizer KLgenerator vs discriminator bersaingmemprediksi derau (MSE)
Objectifsatu loss gabunganminimax dua pemainregresi derau per langkah
Kualitas sampelcenderung kaburtajamtajam dan beragam
Kestabilan trainingstabilgoyah, perlu banyak trikstabil
Kecepatan samplingcepat (satu forward pass)sangat cepatlambat (ratusan langkah)

VAE pada chapter Variational Autoencoder kompak dan stabil, tetapi asumsi Gaussian pada laten membuat rekonstruksinya cenderung kabur. GAN pada chapter Generative Adversarial Network menghasilkan sampel tajam, tetapi keseimbangan dua jaringan mudah pecah. Diffusion menukar kecepatan sampling dengan kestabilan training dan kualitas — kompromi yang terbukti produktif untuk data berdimensi besar seperti gambar.

Ide Dasar: Menambahkan Derau, Lalu Mempelajari Pembaliknya #

Proses diffusion terdiri dari dua arah. Forward process menambahkan derau Gaussian kecil secara bertahap selama T langkah (biasanya T = 1000): data bersih x_0 berubah perlahan menjadi x_1, x_2, …, hingga x_T yang praktis tak terbedakan dari derau murni. Reverse process adalah arah yang dipelajari: sebuah jaringan denoiser menerima x_t dan t, lalu menebak derau yang harus dibuang agar kembali ke x_t-1. Sampling dilakukan dengan menarik derau acak sebagai x_T, lalu membalik T langkah hingga diperoleh data baru x_0.

Rantai ke bawah pada diagram adalah forward process — tetap dan tidak melibatkan pelatihan. Rantai dari x_T naik kembali adalah reverse process yang dipelajari jaringan denoiser; panahnya membalik arah alur data saat sampling. Pada Chapter Forward dan Reverse Diffusion kita akan menuliskan kedua proses ini sebagai distribusi Gaussian secara formal.

Melihat Derau Bertahap dengan Angka Nyata #

Berkas proses_derau.py menerapkan forward process pada gelombang sinus 8 titik, memakai jadwal derau linear dari makalah DDPM (beta naik dari 1e-4 ke 0.02), lalu mencetak kondisi sinyal pada empat timestep. Skrip ditutup dengan eksperimen kecil yang menjelaskan mengapa denoiser harus dipelajari, bukan dihitung langsung:

python
"""Forward diffusion pada sinyal 1D: derau ditambahkan bertahap.

Sinyal gelombang sinus 8 titik dideraui selama T = 1000 langkah.
Skrip mencetak nilai sinyal pada beberapa timestep, menunjukkan SNR
yang menurun, lalu membuktikan mengapa proses baliknya membutuhkan
denoiser yang dipelajari: tanpa mengetahui derau yang benar-benar
ditambahkan, pembalikan langsung menghasilkan nilai tak bermakna.
"""

import numpy as np

rng = np.random.default_rng(42)

# ---------- 1. Sinyal bersih: satu periode gelombang sinus, 8 titik ----------
n = 8
sinyal = np.sin(2.0 * np.pi * np.arange(n) / n)

# ---------- 2. Jadwal derau linear (DDPM): beta kecil -> besar ----------
T = 1000
beta = np.linspace(1e-4, 0.02, T)
alpha = 1.0 - beta
alpha_bar = np.cumprod(alpha)          # alpha_bar[t-1] = alpha_1 * ... * alpha_t

# ---------- 3. Forward diffusion iteratif ----------
x = sinyal.copy()
riwayat = {0: x.copy()}
for t in range(1, T + 1):
    eps = rng.standard_normal(n)
    x = np.sqrt(1.0 - beta[t - 1]) * x + np.sqrt(beta[t - 1]) * eps
    if t in (250, 500, 1000):
        riwayat[t] = x.copy()

print("sinyal x_0 (gelombang sinus, 8 titik):")
print(" ", np.round(sinyal, 3))
print(f"\nJadwal linear: beta_1 = {beta[0]:.5f}, beta_{T} = {beta[-1]:.2f}")
print()
print("  t   | 4 nilai pertama x_t                     | RMSE vs x_0 | SNR (dB)")
print("------+------------------------------------------+-------------+---------")
for t in (0, 250, 500, 1000):
    xt = riwayat[t]
    rmse = np.sqrt(np.mean((xt - sinyal) ** 2))
    if t == 0:
        snr_teks = "inf"
    else:
        ab = alpha_bar[t - 1]
        snr_teks = f"{10.0 * np.log10(ab / (1.0 - ab)):7.1f}"
    print(f" {t:4d} | {np.round(xt[:4], 3)} | {rmse:11.3f} | {snr_teks:>7}")

# ---------- 4. Konsep denoiser: pembalikan butuh derau yang tepat ----------
ab500 = alpha_bar[499]
eps = rng.standard_normal(n)
x500 = np.sqrt(ab500) * sinyal + np.sqrt(1.0 - ab500) * eps
tebakan = rng.standard_normal(n)

pulih_benar = (x500 - np.sqrt(1.0 - ab500) * eps) / np.sqrt(ab500)
pulih_tebakan = (x500 - np.sqrt(1.0 - ab500) * tebakan) / np.sqrt(ab500)

print()
print(f"Pulihkan x_0 dari x_500 (alpha_bar_500 = {ab500:.4f}):")
print("  dengan derau yang benar : RMSE",
      f"{np.sqrt(np.mean((pulih_benar - sinyal) ** 2)):.4f}")
print("  dengan derau tebakan    : RMSE",
      f"{np.sqrt(np.mean((pulih_tebakan - sinyal) ** 2)):.4f}")
print()
print("Amplitudo sinyal tersisa di t=500 : sqrt(alpha_bar) =",
      f"{np.sqrt(ab500):.4f}")
print("Amplitudo derau di t=500          : sqrt(1-alpha_bar) =",
      f"{np.sqrt(1.0 - ab500):.4f}")

Output yang Dihasilkan:

text
sinyal x_0 (gelombang sinus, 8 titik):
  [ 0.     0.707  1.     0.707  0.    -0.707 -1.    -0.707]

Jadwal linear: beta_1 = 0.00010, beta_1000 = 0.02

  t   | 4 nilai pertama x_t                     | RMSE vs x_0 | SNR (dB)
------+------------------------------------------+-------------+---------
    0 | [0.    0.707 1.    0.707] |       0.000 |     inf
  250 | [-1.276 -0.004 -1.121  0.091] |       0.966 |     0.4
  500 | [ 0.304  0.867 -0.654 -0.141] |       0.736 |   -10.7
 1000 | [-0.338 -0.206  0.465 -2.571] |       1.286 |   -43.9

Pulihkan x_0 dari x_500 (alpha_bar_500 = 0.0786):
  dengan derau yang benar : RMSE 0.0000
  dengan derau tebakan    : RMSE 4.8609

Amplitudo sinyal tersisa di t=500 : sqrt(alpha_bar) = 0.2803
Amplitudo derau di t=500          : sqrt(1-alpha_bar) = 0.9599

Tiga fakta terbaca langsung dari keluaran. Pertama, nilai sinyal berubah nyata antar timestep: titik kedua bernilai 0.707 di t=0, menjadi -0.004 di t=250, lalu 0.867 di t=500 — jejak gelombang sinus praktis hilang. Kedua, SNR (rasio sinyal terhadap derau) menurun monoton dari inf ke -43.9 dB; pada t=250 sinyal dan derau sudah sama kuat, dan pada t=1000 yang tersisa hampir murni derau. Ketiga, di t=500 amplitudo sinyal tersisa hanya 0.2803 sedangkan amplitudo derau mencapai 0.9599. Mari kita telaah kode di atas baris per baris:

  1. Baris 12 (default_rng(42)): generator derau ber-seed membuat seluruh keluaran reproducible — nilai yang sama muncul pada setiap eksekusi.
  2. Baris 15-16 (sinyal): np.sin membentuk satu periode sinus 8 titik; nilai-nilainya persis 0, 0.707, 1, 0.707, 0, -0.707, -1, -0.707.
  3. Baris 19-22 (jadwal derau): beta naik linear dari 1e-4 ke 0.02; alpha = 1 - beta; np.cumprod menghitung alpha_bar — hasil kali beruntun alpha yang melacak sisa amplitudo sinyal, notasi lengkapnya dibahas pada chapter berikutnya.
  4. Baris 27-31 (loop forward): setiap langkah mengalikan x dengan sqrt(1-beta_t) (sinyal menyusut) dan menambahkan sqrt(beta_t) kali derau segar; snapshot disimpan pada t = 250, 500, 1000.
  5. Baris 39-47 (tabel): RMSE mengukur seberapa jauh x_t dari x_0; SNR dihitung dari alpha_bar — angka inf di t=0 menandakan belum ada derau sama sekali.
  6. Baris 50-56 (eksperimen pembalikan): x_500 dibangun langsung dari x_0 memakai bentuk ringkas x_t = sqrt(alpha_bar_t) x_0 + sqrt(1-alpha_bar_t) eps (rumus ini kita turunkan pada chapter berikutnya). Membalik rumus dengan eps yang sama memulihkan x_0 sempurna (RMSE 0.0000), tetapi memakai derau tebakan menghasilkan RMSE 4.8609 — hampir tujuh kali amplitudo sinyal asli.

Bagian terakhir itulah inti masalahnya: pembalikan matematis selalu tersedia, tetapi membutuhkan eps yang tidak kita ketahui. Diffusion model menyelesaikannya dengan melatih jaringan untuk menebak eps dari (x_t, t) — tugas regresi ber-loss MSE yang sama sekali tidak melibatkan dua jaringan yang saling berhadapan.

Mengapa Training Diffusion Stabil #

Stabilitas diffusion berasal dari bentuk objectifnya. Denoiser belajar memprediksi derau dengan MSE — fungsi loss yang mulus, bertanda tunggal, dan turunannya teratur — persis keluarga loss yang kita bedah pada chapter Loss Function . Tidak ada minimax, tidak ada gradien yang saling meniadakan antar dua model, dan tidak ada mode collapse karena proses forward menyentuh seluruh ruang data secara gradual. Imbalannya ada di sisi inference: menghasilkan satu sampel menuntut T kali evaluasi jaringan (ratusan hingga ribuan), itulah alasan riset decoding diffusion berkonsentrasi memangkas jumlah langkah.

Aplikasi: Gambar, Audio, dan Lainnya #

Pada domain gambar, diffusion model menjadi dasar text-to-image generatif yang paling dikenal — Stable Diffusion — yang akan kita bedah arsitekturnya pada chapter Latent Diffusion . Pada domain audio, model generatif berbasis diffusion mensintesis bentuk gelombang atau spektrogram ucapan dan musik. Penerapan lain membentang dari video, struktur molekul untuk penemuan obat, hingga imputasi data deret waktu. Makalah fondasi DDPM (Denoising Diffusion Probabilistic Models) oleh Ho dkk. tahun 2020 tersedia di arxiv.org/abs/2006.11239 — sumber notasi beta, alpha, dan alpha_bar yang kita pakai sepanjang section ini.

Kita sekarang memegang gambaran besarnya: forward merusak bertahap, reverse dipelajari, sampling membalik dari derau murni. Pertanyaan berikutnya bersifat matematis: bagaimana menuliskan kedua proses itu sebagai distribusi Gaussian, dan mengapa rantai ribuan langkah bisa dilompati oleh satu rumus tertutup? Chapter Forward dan Reverse Diffusion menjawabnya dengan derivasi ringkas dan implementasi NumPy yang angkanya bisa dicocokkan.