Mundarija (23)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Diskriminativ va generativ modellar
- 2.2. Zichlikni baholash va namuna olish
- 2.3. Maksimal likelihood va held-out log-likelihood
- 2.4. Klassik zichlik baholovchilar
- 2.5. Generativ model oilalari xaritasi
- 2.6. Avtoregressiv faktorizatsiya
- 2.7. Log-likelihood ning cheklovlari
- 2.8. Hakam-klassifikator va yodlab olish tekshiruvi
- 2.9. Tuzoqlar
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — 2D taqsimot: gistogramma, KDE va GMM
- Misol 2 — Digits: PCA + GMM bilan yangi raqamlar
- Misol 3 — Avtoregressiv piksel modeli
- Misol 4 — Yodlab olish tekshiruvi
- 5. To'g'ri va noto'g'ri tushunishlar
- 6. Keng tarqalgan xatolar va yechimlari
- 7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 8. Eng yaxshi amaliyotlar
- 9. Amaliy topshiriq
- Xulosa
26.1-dars: Generativ modellar
26-QISM — GENERATIV AI · 1-dars
1. Kirish va motivatsiya
25-qism oxirida aytganimizdek, endi matndan tashqariga chiqamiz. Aslida generativ modelni biz allaqachon ko'rganmiz: 24.9-darsdagi GPT har qadamda keyingi token uchun taqsimot berar va undan namuna olib matn yaratar edi. 25-qismda esa xuddi shu g'oyani milliardlab parametrli LLM larda ko'rdik. Bu qismda savolni umumlashtiramiz: rasm, tovush yoki jadval qatori kabi istalgan ma'lumotni yaratadigan modelni qanday qurish, qanday o'rgatish va — eng qiyini — qanday halol baholash mumkin?
Shu paytgacha kursdagi modellarning deyarli hammasi diskriminativ edi: rasm berilsa — sinfini, jumla berilsa — kayfiyatini, mijoz berilsa — ketish ehtimolini aytardi. Ular p(y|x) ni o'rganadi: "x ma'lum bo'lsa, y qanday?". Generativ model esa boshqa savolga javob beradi: "x ning o'zi qanday taqsimlangan?" — ya'ni p(x) ni (yoki sinf berilganda p(x|y) ni) o'rganadi. Bu ikki yangi imkoniyat beradi: istalgan x uchun uning qanchalik "odatiy" ekanini aytish (zichlikni baholash) va shu taqsimotdan yangi x larni chiqarish (namuna olish).
Real vaziyat. Bank firibgarlikni aniqlash modelini o'rgatish uchun ma'lumot yetmayotgan edi va jamoa "sintetik mijozlar" yaratishga qaror qildi. Birinchi generativ model ajoyib ko'rinardi: yaratilgan yozuvlar haqiqiylardan ajratib bo'lmas darajada o'xshash edi. Keyin maxfiylik bo'limi oddiy tekshiruv o'tkazdi — har sintetik yozuv uchun eng yaqin haqiqiy yozuvni topdi. Ma'lum bo'ldiki, "sintetik" mijozlarning katta qismi aslida haqiqiy mijozlarning biroz o'zgartirilgan nusxasi edi: model ma'lumotni o'rganmagan, yodlab olgan. Ko'z bilan qaralganda eng yaxshi ko'ringan model eng xavflisi bo'lib chiqdi. Bu darsning 4-misoli aynan shu tekshiruvni qiladi.
Bu darsda generativ modellashtirishning asosiy tushunchalarini kichik, lekin haqiqiy tajribalarda ko'ramiz: 2D taqsimotda zichlikni baholash va namuna olish, raqam rasmlarini yaratish, piksel-piksel ishlaydigan avtoregressiv model va yodlab olishni tekshirish. Har bir natijani ko'z bilan emas, raqam bilan o'lchaymiz.
Bu darsda:
- Diskriminativ
p(y|x)va generativp(x),p(x|y)modellar - Zichlikni baholash va namuna olish — ikki xil qobiliyat
- Maksimal likelihood va held-out log-likelihood
- Klassik baholovchilar: gistogramma, KDE, GMM
- Generativ model oilalari xaritasi
- Avtoregressiv faktorizatsiya
- Log-likelihood ning cheklovlari
- Yodlab olish tekshiruvi — baholashga kirish
- Tuzoqlar
ℹ Misollar real numpy/sklearn/torch bilan (Python 3.14, torch 2.14 CPU).
2. Nazariya — chuqur tushuntirish
2.1. Diskriminativ va generativ modellar
DISKRIMINATIV: p(y | x) "rasm berilsa - qaysi raqam?"
logistik regressiya, daraxtlar, CNN, BERT-klassifikator
x ning o'zi qanday taqsimlanganini BILMAYDI
deyarli butunlay shovqindan iborat namunalarga ham ishonch bilan javob beradi
(3-misol: ularning 0.539 qismiga ishonch > 0.9)
GENERATIV: p(x) yoki p(x | y)
"bu rasm raqamlar dunyosida qanchalik odatiy?" -> p(x) qiymati
"menga yangi raqam chiz" -> x ~ p(x)
"menga yangi 7 chiz" -> x ~ p(x | y = 7)
GMM (16-qism), Naive Bayes (14-qism), GPT 24.9-bob, VAE, GAN, diffusion
BAYES KO'PRIGI:
p(y | x) = p(x | y) * p(y) / p(x)
generativ modeldan klassifikator yasash mumkin (Naive Bayes shunday)
teskarisi - yo'q: p(y | x) dan p(x) ni tiklab bo'lmaydi
NIMA UCHUN QIYIN:
8x8 raqam = 64 o'lchov; 8x8 binar rasmlar soni 2^64 ~ 1.8 * 10^19
p(x) - shu ulkan fazoning HAR nuqtasiga ehtimol berishi kerak,
yig'indisi (integrali) esa aniq 1 bo'lishi shart
klassifikatorga 10 ta son kifoya; generativ modelga - butun taqsimotDiskriminativ model chegarani o'rganadi, generativ model esa ma'lumotning o'zini; shuning uchun generativ vazifa ancha qiyin va ko'p ma'lumot talab qiladi.
2.2. Zichlikni baholash va namuna olish
IKKI ALOHIDA QOBILIYAT:
(a) BAHOLASH: berilgan x uchun p(x) ni hisoblash
-> anomaliya aniqlash 16.10-bob, modellarni solishtirish (LL)
(b) NAMUNA OLISH: x ~ p(x) ni chiqarish
-> sintetik ma'lumot, rasm/matn yaratish, augmentatsiya
HAR MODELDA IKKALASI HAM BO'LMAYDI:
model p(x) aniq? namuna olish
gistogramma ha oson (katak + tekis shovqin)
KDE ha oson (o'quv nuqtasi + shovqin)
GMM ha oson (komponent, keyin Gauss)
avtoregressiv ha sekin: D ta ketma-ket qadam
VAE pastki chegara oson: z ~ N(0, I) -> decoder
GAN YO'Q juda oson: z -> generator
diffusion chegara/taxmin sekin: ko'p qadam
flow ha oson (teskari akslantirish)
SHARTLI MODEL:
p(x | y) - sinf (26.2 da shartli VAE), matn (Matn-rasm modellari darsida)
yoki prompt (24.9 dagi GPT - prompt = shart) "Generativ model" — bitta qobiliyat emas: ba'zilari p(x) ni aniq beradi, ba'zilari faqat namuna chiqaradi; qaysi biri kerakligi vazifaga bog'liq.
2.3. Maksimal likelihood va held-out log-likelihood
O'RGATISH MAQSADI (deyarli hamma likelihood-modellarda):
theta* = argmax (1/N) * sum_i log p_theta(x_i)
bu KL(p_data || p_theta) ni minimallashtirishga teng:
KL = E_data[log p_data(x)] - E_data[log p_theta(x)]
^ modelga bog'liq emas ^ biz maksimallashtiramiz
GPT ning cross-entropy loss i - aynan shu 24.9-bob
HELD-OUT LL - ASOSIY O'LCHOV:
o'quv LL doim murakkablik bilan o'sadi (yodlash ham "yaxshi" ko'rinadi)
val/test LL - modelning haqiqiy umumlashishi
1-misol, GMM: K = 16: o'quv -2.01, val -2.12
K = 32: o'quv -1.96, val -2.17 <- o'quv o'sdi, val tushdi
2-misol, digits PCA-20 + GMM:
K = 40: o'quv -37.46, val -96.88 (ortiqcha moslashish)
BIRLIKLAR:
nat: ln bilan; bit: log2 bilan; 1 nat = 1.443 bit
diskret rasm: bit/rasm yoki bit/piksel (3-misol: 25.26 bit/rasm)
uzluksiz ma'lumot: log-ZICHLIK, musbat ham bo'lishi mumkin
(zichlik 1 dan katta bo'la oladi); faqat bir xil fazoda solishtiriladi
-inf TUZOG'I:
bitta test nuqtasiga p = 0 berilsa - o'rtacha LL = -inf
1-misol: silliqlashsiz gistogramma, 4 ta nuqta bo'sh katakda -> -inf
yechim: silliqlash (Laplace, alfa = 0.5), har yerda musbat zichlikGenerativ modelni o'quv LL bilan emas, held-out LL bilan tanlang; o'quv LL ni yodlovchi model doim yutadi.
2.4. Klassik zichlik baholovchilar
GISTOGRAMMA:
fazoni b^d katakka bo'lamiz; p = katakdagi ulush / katak hajmi
d = 2, b = 20: 400 katak - ishlaydi
d = 64, b = 2: 2^64 katak - hech qachon to'lmaydi (o'lchamlar la'nati)
KDE (yadroli zichlik baholash):
p(x) = (1/N) * sum_i N(x; x_i, h^2 * I)
h - kenglik: kichik h -> har o'quv nuqtasi atrofida "igna" (yodlash)
katta h -> hamma narsa surtilgan
butun o'quv to'plamini saqlaydi (1-misol: 2000 son)
namuna = tasodifiy o'quv nuqtasi + N(0, h^2) shovqin -> kichik h da NUSXA
GMM (16.6-dars):
p(x) = sum_k pi_k * N(x; mu_k, Sigma_k), EM bilan o'rgatiladi
1-misolda K = 16: atigi 95 son, test LL eng yaxshi (-2.108)
halqani 16 ta "cho'zilgan Gauss" bilan yopadi
YUQORI O'LCHOVDA:
xom piksellarda (64 o'lchov) to'liq kovariatsiyali GMM - juda ko'p parametr
amaliy yo'l: avval PCA (16.8-dars) bilan 20 o'lchovga, keyin GMM
2-misol: PCA-20 dispersiyaning 0.897 qismini saqlaydiKlassik baholovchilar past o'lchovda yaxshi ishlaydi; yuqori o'lchovda ular yo o'lchamlar la'natiga uchraydi, yo o'quv ma'lumotini yodlaydi — shuning uchun neyron generativ modellar kerak.
2.5. Generativ model oilalari xaritasi
1. AVTOREGRESSIV (24.9 - GPT; bu darsning 3-misoli):
p(x) = p(x_1) * p(x_2 | x_1) * ... * p(x_D | x_1..x_{D-1})
+ LL aniq, o'rgatish oddiy (cross-entropy)
- namuna olish KETMA-KET: D qadam (8x8 da 64, 256x256 rangli rasmda ~200 ming)
matnda - asosiy usul; rasmda - PixelCNN, rasm tokenlari ustidagi transformerlar
2. LATENT O'ZGARUVCHILI (VAE - 26.2):
z ~ N(0, I), x ~ p(x | z) p(x) = integral p(x | z) p(z) dz
integral hisoblab bo'lmaydi -> pastki chegara (ELBO) maksimallashtiriladi
+ tez namuna, ma'noli latent fazo
- namunalar ko'pincha xira (o'rtachalashgan)
3. ADVERSARIAL (GAN - 26.3, 26.4):
generator G(z) va diskriminator D o'yini; p(x) umuman yo'q
+ o'tkir, realistik namunalar
- o'rgatish beqaror, mode collapse, LL bilan baholab bo'lmaydi
4. DIFFUSION (26.5, 26.6):
ma'lumotga asta-sekin shovqin qo'shiladi; model shovqinni olib tashlashni o'rganadi
+ yuqori sifat va xilma-xillik, barqaror o'rgatish
- namuna olish ko'p qadamli (sekin)
zamonaviy matn-rasm modellarining asosi
5. FLOW (normallashtiruvchi oqimlar, qisqa):
x = f(z), f - teskarilanadigan; o'zgaruvchini almashtirish formulasi:
log p(x) = log p(z) - log |det(df/dz)|
+ LL aniq, namuna tez
- arxitektura cheklangan (teskarilanish, det hisoblash)
KLASSIK (bu dars): gistogramma, KDE, GMM - past o'lchovda yaxshi etalon| Oila | p(x) |
Namuna tezligi | Namuna sifati | O'rgatish |
|---|---|---|---|---|
| Avtoregressiv | aniq | sekin (D qadam) | yaxshi | barqaror |
| VAE | pastki chegara | tez | xiraroq | barqaror |
| GAN | yo'q | tez | o'tkir | beqaror |
| Diffusion | chegara | sekin (ko'p qadam) | juda yaxshi | barqaror |
| Flow | aniq | tez | o'rtacha | barqaror |
Oila tanlovi — murosa: aniq likelihood, tez namuna, yuqori sifat va barqaror o'rgatishning hammasini birdaniga beradigan oila yo'q.
2.6. Avtoregressiv faktorizatsiya
ZANJIR QOIDASI (hech qanday taxminsiz - ANIQ):
p(x_1, ..., x_D) = prod_i p(x_i | x_1, ..., x_{i-1})
har omil - oddiy klassifikator: "oldingi piksellarga qarab keyingisi 1 mi?"
8x8 BINAR RASM, TARTIB - QATOR BO'YICHA:
x_1 x_2 ... x_8
x_9 ... <- x_12 ni bashorat qilishda x_1..x_11 ko'rinadi
...
UCH MODEL (3-misol):
mustaqil: p(x_i) - oldingi piksellarga qaramaydi 64 parametr
chiziqli: logit_i = b_i + sum_{j<i} W_ij * x_j 4 160 parametr
MADE: niqobli MLP: yashirin neyronlar ham "darajali" 20 736 parametr
i-chiqish faqat j < i kirishlarga bog'liq bo'lishi niqob bilan kafolatlanadi
NIQOB G'OYASI (24.7 dagi kauzal niqob bilan bir xil):
W_ij * niqob_ij, niqob_ij = 1 faqat j < i bo'lsa
bitta forward - barcha 64 shartli ehtimol birdaniga (o'rgatishda tez)
namuna olishda esa 64 ta ketma-ket forward (sekin)
BIT/RASM:
tekis tasodif: 64 bit (har piksel 1 bit)
3-misol test: mustaqil 37.98, chiziqli 26.57, MADE 25.26Avtoregressiv model — zanjir qoidasi + niqob: likelihood aniq va o'rgatish parallel, lekin namuna olish har doim ketma-ket.
2.7. Log-likelihood ning cheklovlari
1. YAXSHI LL, YOMON NAMUNALAR (3-misol):
p_aralash = 0.01 * p_MADE + 0.99 * p_shovqin
log2 p_aralash >= log2 p_MADE + log2(0.01) = log2 p_MADE - 6.64
test NLL: 31.89 bit - mustaqil modeldan 37.98-bob YAXSHI
lekin namunalarning ~99% i - tasodifiy shovqin
xulosa: LL 6.6 bitga yomonlashdi, namunalar esa deyarli butunlay buzildi
2. YAXSHI NAMUNALAR, YOMON LL (4-misol):
yodlovchi KDE (h = 0.5): o'quv LL -11.42, test LL -323.93
namunalari hakamga eng "ishonchli" 0.954-bob - chunki ular o'quv rasmlarining nusxasi
3. TURLI FAZODAGI LL LAR SOLISHTIRILMAYDI:
PCA-20 dagi log-zichlik va 64 pikseldagi log-zichlik - boshqa birliklar
uzluksiz zichlik va diskret ehtimol - boshqa narsalar
(diskret piksellarga uzluksiz model: "dequantization" - shovqin qo'shib)
4. YUQORI O'LCHOVDA LL MAYDA DETALLARGA E'TIBOR BERADI:
LL ning katta qismi piksel darajasidagi shovqinni to'g'ri modellashdan keladi,
inson esa shakl va ma'noga qaraydi
XULOSA:
LL - zarur, lekin yetarli emas; namuna-asosli o'lchovlar bilan birga:
hakam-klassifikator bilan "tanib olinish" (2, 3-misollar)
sinf taqsimoti - mode coverage (qaysi sinflar yaratilmayapti?)
eng yaqin o'quv namunasigacha masofa - yodlash (4-misol)
Frechet masofa (FID uslubi) - Generativ modellarni baholash darsidaLog-likelihood namuna sifatini kafolatlamaydi, yaxshi namunalar esa yuqori likelihood ni kafolatlamaydi; generativ modelni doim bir nechta mustaqil o'lchov bilan baholang.
2.8. Hakam-klassifikator va yodlab olish tekshiruvi
HAKAM-KLASSIFIKATOR:
generativ modeldan MUSTAQIL, haqiqiy ma'lumotda o'rgatilgan (MLP 64-128-10)
2-misol: test aniqligi 0.971; haqiqiy test rasmlarida ishonch > 0.9 - 0.947
o'lchovlar:
ishonch > 0.9 ulushi - namuna "aniq bir raqamga" o'xshaydimi
sinflar soni (0..9) - hamma raqamlar yaratilyaptimi (mode coverage)
CHEKLOV: hakam ham aldanadi - 3-misolda 99% shovqindan iborat namunalarning
0.539 qismiga ishonch > 0.9 berdi (diskriminativ model p(x) ni bilmaydi!)
shuning uchun doim haqiqiy test rasmlaridagi qiymat bilan solishtiring
YODLAB OLISH TEKSHIRUVI:
har namuna uchun eng yaqin O'QUV rasmigacha masofa d_nn
ma'lumotnoma: haqiqiy TEST rasmlarining o'quvgacha masofasi
(test ham o'quvni ko'rmagan - "halol yangi" rasmlar shunchalik uzoq)
4-misol: test median 17.38; 5-foizil 12.02 -> "nusxa" chegarasi
yodlovchi: namunalarning 0.784 qismi chegaradan yaqin (haqiqiyda 0.051)
GMM K=10: 0.017 - nusxa ko'chirmayapti
NEGA MUHIM:
maxfiylik (tibbiy, moliyaviy yozuvlar), mualliflik huquqi -
Generativ AI etikasi va xavfsizligi darsida batafsilYaratilgan namunani doim eng yaqin o'quv namunasi bilan solishtiring; ma'lumotnoma sifatida haqiqiy test namunalarining o'sha masofasini oling.
2.9. Tuzoqlar
Asosiy tuzoqlar: generativ modelni o'quv LL bo'yicha tanlash (yodlovchi doim yutadi); silliqlashsiz gistogramma yoki tor KDE bilan -inf LL olish; turli fazodagi (PCA va piksel, uzluksiz va diskret) LL larni solishtirish; LL yaxshilandi — demak namunalar yaxshilandi deb o'ylash; GaussianMixture.sample natijasini aralashtirmasdan ishlatish (u komponentlar bo'yicha tartiblangan qaytaradi — dastlabki namunalarning hammasi bitta komponentdan); namunalarni faqat "ko'z bilan" baholash; hakam-klassifikator ishonchini haqiqiy test rasmlaridagi qiymat bilan solishtirmaslik (hakam shovqinga ham ishonadi); yodlab olishni tekshirmaslik; avtoregressiv modelda niqobni noto'g'ri qo'yish (piksel o'zini ko'rsa, o'quv LL ajoyib, namunalar esa bema'ni); modelni urug'siz yaratish (parametr boshlang'ich qiymati — natija takrorlanmaydi).
3. Tez ma'lumotnoma
import numpy as np
from sklearn.mixture import GaussianMixture
from sklearn.neighbors import KernelDensity
# zichlikni baholash va held-out LL
gm = GaussianMixture(16, random_state=0).fit(x_oquv)
val_ll = gm.score(x_val) # o'rtacha log p(x)
kd = KernelDensity(bandwidth=0.1).fit(x_oquv)
lp = kd.score_samples(x_test) # har nuqta uchun log p(x)
# namuna olish
x_new, komp = gm.sample(1000) # komponentlar bo'yicha TARTIBLANGAN
x_new = x_new[np.random.default_rng(1).permutation(len(x_new))]
x_kde = kd.sample(1000, random_state=1)
# PCA + GMM (yuqori o'lchov)
z = pca.transform(x); x_gen = np.clip(pca.inverse_transform(gm.sample(1000)[0]), 0, 16)
# avtoregressiv: bit/rasm va piksel-piksel namuna
nll_bit = F.binary_cross_entropy_with_logits(model(x), x, reduction="none").sum(1) / math.log(2)
for i in range(64):
x[:, i] = torch.bernoulli(torch.sigmoid(model(x)[:, i]), generator=g)
# yodlab olish tekshiruvi
d_nn = torch.cdist(namuna, oquv).min(1).values
chegara = np.quantile(d_test_nn, 0.05) # haqiqiy test rasmlari asosida
nusxa_ulushi = (d_nn < chegara).float().mean()Generativ modellar xulosasi
diskriminativ p(y|x); generativ p(x) yoki p(x|y)
ikki qobiliyat: p(x) ni baholash va namuna olish - har modelda ikkalasi emas
maqsad: max E[log p(x)] = min KL(p_data || p_theta); tanlov - held-out LL bilan
oilalar: avtoregressiv, VAE, GAN, diffusion, flow - har biri murosa
LL yetarli emas: + hakam-klassifikator, sinf taqsimoti, eng yaqin qo'shni masofasi4. Batafsil misollar
Misollar real numpy/sklearn/torch bilan (Python 3.14, torch 2.14 CPU).
Misol 1 — 2D taqsimot: gistogramma, KDE va GMM
"""2D zichlikni baholash: gistogramma, KDE va GMM - held-out log-likelihood bilan tanlash."""
import math
import warnings
import numpy as np
from sklearn.mixture import GaussianMixture
from sklearn.neighbors import KernelDensity
R, SIGMA_R, SIGMA_M, ULUSH_HALQA = 2.0, 0.15, 0.3, 0.6
QUTI = 3.5 # gistogramma uchun [-3.5, 3.5]^2
def namuna(n, rng):
"""Halqa (60%) + markazdagi Gauss (40%) aralashmasi."""
halqa = rng.random(n) < ULUSH_HALQA
burchak = rng.uniform(0, 2 * math.pi, n)
r = R + SIGMA_R * rng.standard_normal(n)
x_h = np.c_[r * np.cos(burchak), r * np.sin(burchak)]
x_m = SIGMA_M * rng.standard_normal((n, 2))
return np.where(halqa[:, None], x_h, x_m)
def haqiqiy_logp(x):
"""Haqiqiy zichlik (biz bilamiz!) - 'shift' sifatida."""
r = np.linalg.norm(x, axis=1)
p_h = np.exp(-0.5 * ((r - R) / SIGMA_R) ** 2) / (SIGMA_R * math.sqrt(2 * math.pi)) / (2 * math.pi * r)
p_m = np.exp(-0.5 * (r / SIGMA_M) ** 2) / (2 * math.pi * SIGMA_M ** 2)
return np.log(ULUSH_HALQA * p_h + (1 - ULUSH_HALQA) * p_m)
class Gistogramma:
def __init__(self, b, alfa=0.0):
self.b, self.alfa = b, alfa
self.chet = np.linspace(-QUTI, QUTI, b + 1)
self.yuza = (2 * QUTI / b) ** 2
def fit(self, x):
c, _, _ = np.histogram2d(x[:, 0], x[:, 1], bins=[self.chet, self.chet])
c = c + self.alfa # Laplace silliqlash
self.p = c / c.sum()
return self
def logp(self, x):
i = np.clip(np.digitize(x[:, 0], self.chet) - 1, 0, self.b - 1)
j = np.clip(np.digitize(x[:, 1], self.chet) - 1, 0, self.b - 1)
with np.errstate(divide="ignore"):
return np.log(self.p[i, j] / self.yuza)
def sample(self, n, rng):
k = rng.choice(self.b * self.b, n, p=self.p.ravel())
i, j = np.divmod(k, self.b)
w = 2 * QUTI / self.b
return np.c_[self.chet[i] + w * rng.random(n), self.chet[j] + w * rng.random(n)]
def oila_modellari():
return {
"gistogramma": [(f"b={b}", b * b - 1, lambda b=b: Gistogramma(b, alfa=0.5)) for b in (5, 10, 20, 40)],
"KDE": [(f"h={h}", None, lambda h=h: KernelDensity(bandwidth=h)) for h in (0.05, 0.1, 0.2, 0.4)],
"GMM": [(f"K={k}", 6 * k - 1, lambda k=k: GaussianMixture(k, random_state=0, n_init=1))
for k in (1, 4, 8, 16, 32)],
}
def logp(model, x):
if isinstance(model, Gistogramma):
return model.logp(x)
return model.score_samples(x)
def main() -> None:
rng = np.random.default_rng(0)
oquv, val, test = namuna(1000, rng), namuna(1000, rng), namuna(2000, rng)
print("=== 1. Haqiqiy taqsimot: halqa (60%) + markaz (40%) ===")
print(f" o'quv 1000, val 1000, test 2000 nuqta")
print(f" haqiqiy zichlikning test log-likelihoodi: {haqiqiy_logp(test).mean():.3f} (shift)")
print("\n=== 2. Nol hisob tuzog'i: silliqlashsiz gistogramma ===")
for b in (10, 40):
g0 = Gistogramma(b).fit(oquv)
lp = g0.logp(val)
print(f" b={b:<3} bo'sh katakdagi val nuqtalari {np.isinf(lp).sum():>3} ta -> "
f"val LL = {lp.mean():.3f}")
print("\n=== 3. Har oilada val LL bo'yicha tanlash ===")
tanlangan = {}
with warnings.catch_warnings():
warnings.simplefilter("ignore")
for oila, variantlar in oila_modellari().items():
qator = []
eng = None
for nom, _, yasa in variantlar:
m = yasa().fit(oquv)
tr, va = logp(m, oquv).mean(), logp(m, val).mean()
qator.append(f"{nom} {tr:.2f}/{va:.2f}")
if eng is None or va > eng[1]:
eng = (nom, va, yasa)
tanlangan[oila] = eng
print(f" {oila:<11} (o'quv/val): " + ", ".join(qator))
print(f" {'':<11} -> tanlandi {eng[0]}")
print("\n=== 4. Tanlangan modellar: 5 ta ma'lumot urug'ida test LL (juftlashgan) ===")
natija = {o: [] for o in tanlangan}
for s in range(5):
r = np.random.default_rng(100 + s)
o_, t_ = namuna(1000, r), namuna(2000, r)
with warnings.catch_warnings():
warnings.simplefilter("ignore")
for oila, (nom, _, yasa) in tanlangan.items():
natija[oila].append(logp(yasa().fit(o_), t_).mean())
parametr = {"gistogramma": lambda n: int(n[2:]) ** 2 - 1, "KDE": lambda n: 2 * 1000,
"GMM": lambda n: 6 * int(n[2:]) - 1}
for oila, v in natija.items():
nom = tanlangan[oila][0]
print(f" {oila:<11} {nom:<6} test LL {np.mean(v):.3f} saqlanadigan sonlar: {parametr[oila](nom)}")
eng_oila = max(natija, key=lambda o: np.mean(natija[o]))
for oila in natija:
if oila == eng_oila:
continue
f = np.array(natija[oila]) - np.array(natija[eng_oila])
se = f.std(ddof=1) / math.sqrt(len(f))
print(f" {oila} - {eng_oila}: {f.mean():+.3f}, SE {se:.3f} -> "
f"{'sezilarli yomon' if f.mean() < -2 * se else 'sezilarli emas'}")
print("\n=== 5. Namuna olish: namunalar qanchalik 'haqiqiy'? ===")
chegara = np.quantile(haqiqiy_logp(test), 0.05) # haqiqiy nuqtalarning 95% shundan yuqori
print(f" o'lchov: haqiqiy log-zichlik {chegara:.2f} dan yuqori ulush (haqiqiy ma'lumotda 0.95)")
with warnings.catch_warnings():
warnings.simplefilter("ignore")
for oila, (nom, _, yasa) in tanlangan.items():
m = yasa().fit(oquv)
if oila == "gistogramma":
x = m.sample(2000, np.random.default_rng(1))
elif oila == "KDE":
x = m.sample(2000, random_state=1)
else:
x = m.sample(2000)[0]
lp = haqiqiy_logp(x)
ichida = (lp > chegara).mean()
halqa = (np.abs(np.linalg.norm(x, axis=1) - R) < 3 * SIGMA_R).mean()
print(f" {oila:<11} ichida {ichida:.3f}, halqada {halqa:.3f} (haqiqiy ~{ULUSH_HALQA * 0.997:.3f})")
if oila == "GMM":
gmm_x = x
print("\n=== 6. Haqiqiy ma'lumot va GMM namunalari (ASCII zichlik) ===")
chet = np.linspace(-2.75, 2.75, 12)
rasmlar = []
for x in (test, gmm_x):
c, _, _ = np.histogram2d(x[:, 1], x[:, 0], bins=[chet, np.linspace(-2.75, 2.75, 23)])
c = np.sqrt(c[::-1] / c.max()) # ildiz: halqa ham ko'rinsin
rasmlar.append(["".join(" .:-=+*#%@"[min(9, int(v * 10))] for v in q) for q in c])
print(f" {'haqiqiy (test)':<22} GMM namunalari")
for a, b in zip(*rasmlar):
print(f" {a} {b}")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Haqiqiy taqsimot: halqa (60%) + markaz (40%) ===
o'quv 1000, val 1000, test 2000 nuqta
haqiqiy zichlikning test log-likelihoodi: -2.062 (shift)
=== 2. Nol hisob tuzog'i: silliqlashsiz gistogramma ===
b=10 bo'sh katakdagi val nuqtalari 4 ta -> val LL = -inf
b=40 bo'sh katakdagi val nuqtalari 76 ta -> val LL = -inf
=== 3. Har oilada val LL bo'yicha tanlash ===
gistogramma (o'quv/val): b=5 -2.74/-2.80, b=10 -2.51/-2.59, b=20 -2.27/-2.39, b=40 -2.33/-2.63
-> tanlandi b=20
KDE (o'quv/val): h=0.05 -1.62/-2.39, h=0.1 -1.95/-2.13, h=0.2 -2.16/-2.22, h=0.4 -2.55/-2.60
-> tanlandi h=0.1
GMM (o'quv/val): K=1 -3.02/-3.07, K=4 -2.49/-2.58, K=8 -2.13/-2.17, K=16 -2.01/-2.12, K=32 -1.96/-2.17
-> tanlandi K=16
=== 4. Tanlangan modellar: 5 ta ma'lumot urug'ida test LL (juftlashgan) ===
gistogramma b=20 test LL -2.361 saqlanadigan sonlar: 399
KDE h=0.1 test LL -2.125 saqlanadigan sonlar: 2000
GMM K=16 test LL -2.108 saqlanadigan sonlar: 95
gistogramma - GMM: -0.253, SE 0.009 -> sezilarli yomon
KDE - GMM: -0.018, SE 0.005 -> sezilarli yomon
=== 5. Namuna olish: namunalar qanchalik 'haqiqiy'? ===
o'lchov: haqiqiy log-zichlik -3.80 dan yuqori ulush (haqiqiy ma'lumotda 0.95)
gistogramma ichida 0.758, halqada 0.503 (haqiqiy ~0.598)
KDE ichida 0.902, halqada 0.582 (haqiqiy ~0.598)
GMM ichida 0.959, halqada 0.589 (haqiqiy ~0.598)
=== 6. Haqiqiy ma'lumot va GMM namunalari (ASCII zichlik) ===
haqiqiy (test) GMM namunalari
.
:----=---. .:--=-=-::.
.:=-:.. ::---. .-==-:. .:-=:
.==. :=-. .--: . . :=-.
-=: .=++=. :-- -=- .:#+-: :=-
.==. :-#@@*- :-=: :-. .=*@%*=. .--
:-. .-*+=: .=: .:=. :=++=: :=:
.--. . :=-: .--. .=:
.:=-::. ..::=-: ..:--:: ::--:.
.:---:-=-::. :--:--==-:.
:Nima ko'rsatdi: haqiqiy taqsimotni biz bilamiz — halqa (60%) va markazdagi Gauss (40%) — shuning uchun uning test log-likelihoodi -2.062 "shift" bo'lib xizmat qiladi: hech bir model o'rtacha bundan sezilarli yuqoriga chiqolmaydi. 2-bo'lim eng oddiy tuzoqni ko'rsatdi: silliqlashsiz gistogrammada bitta val nuqtasi bo'sh katakka tushsa, o'rtacha LL -inf bo'ladi — b=10 da bunday nuqtalar 4 ta, b=40 da 76 ta. Shuning uchun keyingi bo'limlarda alfa = 0.5 silliqlash ishlatildi. 3-bo'limda har oila val LL bo'yicha tanlandi va hamma joyda bir xil manzara: o'quv LL murakkablik bilan o'sadi, val LL esa bir nuqtadan keyin tushadi. KDE da bu eng yaqqol: h=0.05 o'quvda -1.62 (haqiqiy shiftdan ham yuqori — bu yodlash belgisi!), val da esa -2.39. GMM da K=32 o'quvda K=16 dan yaxshi (-1.96 va -2.01), val da yomon (-2.17 va -2.12). 4-bo'lim tanlangan modellarni 5 ta yangi ma'lumot urug'ida juftlashgan solishtirdi: GMM K=16 test LL -2.108 — shiftga (-2.062) juda yaqin; KDE farqi -0.018 (SE 0.005) kichik, lekin sezilarli, gistogramma esa -0.253 ga yomon. Qaror qoidasi ("eng yaxshisidan sezilarli yomon bo'lmagan eng sodda") bu yerda oson: GMM ham eng yaxshi, ham eng ixcham — 95 son, KDE esa butun o'quv to'plamini (2000 son) saqlaydi. 5-bo'lim namunalarni haqiqiy zichlik bilan tekshirdi: GMM namunalarining 0.959 qismi haqiqiy ma'lumotning 95% li sohasida, halqadagi ulush 0.589 (haqiqiy ~0.598); gistogramma katakning ichida tekis tarqatgani uchun namunalarning 0.758 qismigina sohada. ASCII rasm buni ko'z bilan ham tasdiqlaydi: GMM halqani ham, markazni ham qamradi. Bog'liq bo'limlar: 2.3, 2.4.
Misol 2 — Digits: PCA + GMM bilan yangi raqamlar
"""Digits da GMM (PCA dan keyin) bilan yangi raqamlar yaratish va ularni klassifikator bilan tekshirish."""
import warnings
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
from sklearn.datasets import load_digits
from sklearn.decomposition import PCA
from sklearn.mixture import GaussianMixture
from sklearn.model_selection import train_test_split
BELGI = " .:-=+*#%@"
def ascii_qator(rasmlar, izohlar):
"""8x8 rasmlarni (0..16) yonma-yon ASCII qatorlarga aylantiradi."""
satrlar = [" ".join(f"{s:<8}" for s in izohlar)]
for r in range(8):
satrlar.append(" ".join(
"".join(BELGI[min(9, int(v / 16 * 10))] for v in np.clip(im.reshape(8, 8)[r], 0, 16))
for im in rasmlar))
return satrlar
class Klassifikator(nn.Module):
"""O'zimiz o'rgatadigan 'hakam': 64 -> 128 -> 10."""
def __init__(self):
super().__init__()
self.h = nn.Linear(64, 128)
self.chiq = nn.Linear(128, 10)
def forward(self, x):
return self.chiq(F.relu(self.h(x / 16)))
def klassifikator_orgat(x, y, seed=0):
torch.manual_seed(seed)
m = Klassifikator()
opt = torch.optim.Adam(m.parameters(), lr=1e-2, weight_decay=1e-4)
xt, yt = torch.tensor(x, dtype=torch.float32), torch.tensor(y)
g = torch.Generator().manual_seed(seed)
for _ in range(60):
for idx in torch.randperm(len(xt), generator=g).split(64):
loss = F.cross_entropy(m(xt[idx]), yt[idx])
opt.zero_grad()
loss.backward()
opt.step()
return m.eval()
@torch.no_grad()
def baholash(m, x):
p = torch.softmax(m(torch.tensor(x, dtype=torch.float32)), -1).numpy()
return p.argmax(1), p.max(1)
def main() -> None:
torch.set_num_threads(1)
d = load_digits()
x_oquv, x_test, y_oquv, y_test = train_test_split(
d.data, d.target, test_size=0.25, stratify=d.target, random_state=0)
x_o, x_v = x_oquv[:1000], x_oquv[1000:]
print("=== 1. Hakam-klassifikator (generativ modeldan mustaqil) ===")
hakam = klassifikator_orgat(x_oquv, y_oquv)
pred, ish = baholash(hakam, x_test)
print(f" test aniqligi {np.mean(pred == y_test):.3f}; haqiqiy test rasmlarida "
f"ishonch > 0.9 ulushi {np.mean(ish > 0.9):.3f}")
print("\n=== 2. PCA(20) + GMM: komponentlar sonini val LL bilan tanlash ===")
pca = PCA(20, random_state=0).fit(x_o)
print(f" PCA 20 komponent dispersiyaning {pca.explained_variance_ratio_.sum():.3f} qismini saqlaydi")
z_o, z_v = pca.transform(x_o), pca.transform(x_v)
natija = []
with warnings.catch_warnings():
warnings.simplefilter("ignore")
for k in (1, 5, 10, 20, 40):
gm = GaussianMixture(k, covariance_type="full", random_state=0).fit(z_o)
natija.append((k, gm.score(z_o), gm.score(z_v)))
print(f" K={k:<3} o'quv LL {natija[-1][1]:8.2f}, val LL {natija[-1][2]:8.2f}")
eng_k = max(natija, key=lambda t: t[2])[0]
print(f" -> tanlandi K={eng_k} (o'quv LL K bilan doim o'sadi, val LL - yo'q)")
print("\n=== 3. 1000 ta yangi raqam: tanib olinish va sinf taqsimoti ===")
z_all = pca.transform(x_oquv)
with warnings.catch_warnings():
warnings.simplefilter("ignore")
modellar = {f"K={k}": GaussianMixture(k, covariance_type="full", random_state=0).fit(z_all)
for k in sorted({1, eng_k})}
namunalar, tanish = {}, {}
for nom, gm in modellar.items():
z, komp = gm.sample(1000) # DIQQAT: komponentlar bo'yicha tartiblangan!
if nom != "K=1":
print(f" {nom}: gm.sample dagi dastlabki 6 komponent: {komp[:6].tolist()} -> aralashtiramiz")
z = z[np.random.default_rng(1).permutation(len(z))]
x = np.clip(pca.inverse_transform(z), 0, 16)
namunalar[nom] = x
p, i = baholash(hakam, x)
soni = np.bincount(p, minlength=10)
ulush = soni / soni.sum()
tanish[nom] = np.mean(i > 0.9)
entr = -(ulush[ulush > 0] * np.log(ulush[ulush > 0])).sum() / np.log(10)
print(f" {nom:<5} ishonch > 0.9: {np.mean(i > 0.9):.3f}; sinflar: {' '.join(map(str, soni))}; "
f"entropiya {entr:.3f}")
print(f" haqiqiy test: ishonch > 0.9: {np.mean(ish > 0.9):.3f}")
a, b = tanish["K=1"], tanish[f"K={eng_k}"]
se = np.sqrt(a * (1 - a) / 1000 + b * (1 - b) / 1000)
print(f" K={eng_k} - K=1: {b - a:+.3f}, SE {se:.3f} -> "
f"{'sezilarli' if abs(b - a) > 2 * se else 'sezilarli emas'}")
print("\n=== 4. Namunalar (ASCII) ===")
for nom in modellar:
x = namunalar[nom][:6]
p, i = baholash(hakam, x)
for s in ascii_qator(x, [f"{nom}:{a}" for a in p]):
print(" " + s)
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Hakam-klassifikator (generativ modeldan mustaqil) ===
test aniqligi 0.971; haqiqiy test rasmlarida ishonch > 0.9 ulushi 0.947
=== 2. PCA(20) + GMM: komponentlar sonini val LL bilan tanlash ===
PCA 20 komponent dispersiyaning 0.897 qismini saqlaydi
K=1 o'quv LL -64.37, val LL -64.49
K=5 o'quv LL -58.14, val LL -59.18
K=10 o'quv LL -54.57, val LL -57.69
K=20 o'quv LL -50.07, val LL -61.56
K=40 o'quv LL -37.46, val LL -96.88
-> tanlandi K=10 (o'quv LL K bilan doim o'sadi, val LL - yo'q)
=== 3. 1000 ta yangi raqam: tanib olinish va sinf taqsimoti ===
K=1 ishonch > 0.9: 0.478; sinflar: 86 85 113 138 104 69 97 106 113 89; entropiya 0.993
K=10: gm.sample dagi dastlabki 6 komponent: [0, 0, 0, 0, 0, 0] -> aralashtiramiz
K=10 ishonch > 0.9: 0.865; sinflar: 84 90 90 104 96 105 102 97 116 116; entropiya 0.998
haqiqiy test: ishonch > 0.9: 0.947
K=10 - K=1: +0.387, SE 0.019 -> sezilarli
=== 4. Namunalar (ASCII) ===
K=1:6 K=1:7 K=1:5 K=1:0 K=1:7 K=1:8
-*#= -#%+ :%@* #@+- @@= #@*
.*+-= .*=+: :@*=# +@@*- #@@+ :@@@=
:@+:= --@= -# :+ #* -: :+-@= .+%@=
.@@#= -=+@@- :=:+=. :@= =- :*==@+ *@@=.
=-:*: =%+*@= .. .+- =@@=@+ -@%@@- +@+=.
.*-.#* :-=:- .== == :@=:%+ ..:@% ---#:
.@*-#+ .. +*.+: #@@* @- #+@@
-*@* =*: -@#=. .%* .+ #@@.
K=10:2 K=10:4 K=10:7 K=10:9 K=10:7 K=10:5
*@- -%:. =##*- -+#= *%# -*@%:
-%#+ :#% . .%%@#: .#+%@. :@+@= @*--:
.-=@ .=#::= *=*+ :%*#@. .: @- :@-+.
*@ :@@=@* . -+. .+*##. .-+%+: -@@@#.
#% -@@*@= .=@@@- :*. .#@#=. . -@:
-*+-. .:++%. .#@++: .:%- =% :: @:
#%%%= :#* .# .. =.=@: =* .%=-*
*@@+: .:@- +* -+@#. #+ . -#*.Nima ko'rsatdi: avval generativ modeldan mustaqil "hakam" o'rgatdik: test aniqligi 0.971, haqiqiy test rasmlarining 0.947 qismiga u 0.9 dan yuqori ishonch beradi — bu keyingi hamma raqamlar uchun ma'lumotnoma. 2-bo'limda 64 pikselni PCA bilan 20 o'lchovga tushirdik (dispersiyaning 0.897 qismi) va GMM komponentlari sonini val LL bilan tanladik: o'quv LL K bilan tinmay o'sdi (-64.37 dan -37.46 gacha), val LL esa K=10 da eng yuqori (-57.69), K=40 da -96.88 ga qulab tushdi — 40 ta to'liq kovariatsiyali komponent 1000 rasmni yodlay boshladi. 3-bo'limdagi tuzoq: gm.sample namunalarni komponentlar bo'yicha tartiblab qaytaradi — dastlabki 6 tasining hammasi 0-komponentdan; aralashtirmasak, "birinchi 6 namuna" hammasi bir xil raqam bo'lib chiqar edi. Asosiy natija: bitta Gauss (K=1) namunalarining atigi 0.478 qismi aniq taniladi, K=10 niki — 0.865 (haqiqiy 0.947 ga ancha yaqin); farq +0.387, SE 0.019 — sezilarli. Sinf taqsimoti ikkalasida ham tekis (entropiya 0.993 va 0.998, maksimal 1): hech bir raqam "tushib qolmagan". ASCII namunalar farqni ko'rsatadi: K=1 raqamlari "hamma raqamlarning o'rtachasi" ga o'xshash xira dog'lar, K=10 niki esa aniq shaklli raqamlar. Bog'liq bo'limlar: 2.2, 2.4, 2.8.
Misol 3 — Avtoregressiv piksel modeli
"""Avtoregressiv piksel modeli: binar 8x8 raqamlar, p(x) = p(x1) p(x2|x1) ... p(x64|x1..x63)."""
import math
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
D = 64
class Mustaqil(nn.Module):
"""Bazaviy: har piksel alohida Bernoulli - piksellar orasida bog'liqlik yo'q."""
def __init__(self):
super().__init__()
self.b = nn.Parameter(torch.zeros(D))
def forward(self, x):
return self.b.expand(len(x), D)
class NiqobliChiziqli(nn.Linear):
def __init__(self, kirish, chiqish, niqob):
super().__init__(kirish, chiqish)
self.register_buffer("niqob", niqob.float())
def forward(self, x):
return F.linear(x, self.weight * self.niqob, self.bias)
class MADE(nn.Module):
"""Avtoregressiv MLP: i-chiqish faqat 0..i-1 piksellarga bog'liq (niqoblar bilan)."""
def __init__(self, h=128, seed=0):
super().__init__()
g = torch.Generator().manual_seed(seed)
tartib = torch.arange(D) # piksel tartibi: qator bo'yicha
daraja_h = torch.randint(0, D - 1, (h,), generator=g) # yashirin neyron "darajasi"
self.l1 = NiqobliChiziqli(D, h, daraja_h[:, None] >= tartib[None, :])
self.l2 = NiqobliChiziqli(h, D, tartib[:, None] > daraja_h[None, :])
self.to_g = NiqobliChiziqli(D, D, tartib[:, None] > tartib[None, :]) # to'g'ridan-to'g'ri
def forward(self, x):
return self.l2(torch.relu(self.l1(x))) + self.to_g(x)
class ChiziqliAR(nn.Module):
"""Eng sodda avtoregressiv model: i-piksel logiti = oldingi piksellarning chiziqli funksiyasi."""
def __init__(self):
super().__init__()
tartib = torch.arange(D)
self.l = NiqobliChiziqli(D, D, tartib[:, None] > tartib[None, :])
def forward(self, x):
return self.l(x)
class Klassifikator(nn.Module):
def __init__(self):
super().__init__()
self.h = nn.Linear(D, 128)
self.chiq = nn.Linear(128, 10)
def forward(self, x):
return self.chiq(F.relu(self.h(x)))
def klassifikator_orgat(x, y, seed=0):
torch.manual_seed(seed)
m = Klassifikator()
opt = torch.optim.Adam(m.parameters(), lr=1e-2, weight_decay=1e-4)
g = torch.Generator().manual_seed(seed)
for _ in range(60):
for idx in torch.randperm(len(x), generator=g).split(64):
loss = F.cross_entropy(m(x[idx]), y[idx])
opt.zero_grad()
loss.backward()
opt.step()
return m.eval()
def nll_bit(model, x):
"""Bitta rasm uchun o'rtacha -log2 p(x) (bit)."""
with torch.no_grad():
return F.binary_cross_entropy_with_logits(model(x), x, reduction="none").sum(1).mean().item() / math.log(2)
def orgat(klass, x, qadamlar=1500, seed=0):
torch.manual_seed(seed)
model = klass()
opt = torch.optim.Adam(model.parameters(), lr=3e-3)
g = torch.Generator().manual_seed(seed)
for _ in range(qadamlar):
idx = torch.randint(0, len(x), (128,), generator=g)
loss = F.binary_cross_entropy_with_logits(model(x[idx]), x[idx], reduction="none").sum(1).mean()
opt.zero_grad()
loss.backward()
opt.step()
return model.eval()
@torch.no_grad()
def namuna_ol(model, n, g):
"""Piksel-piksel: 64 qadam, har qadamda bitta pikselni Bernoulli dan olamiz."""
x = torch.zeros(n, D)
for i in range(D):
p = torch.sigmoid(model(x)[:, i])
x[:, i] = torch.bernoulli(p, generator=g)
return x
def main() -> None:
torch.set_num_threads(1)
d = load_digits()
xb = (d.data > 7).astype(np.float32)
x_o, x_t, y_o, y_t = train_test_split(xb, d.target, test_size=0.25, stratify=d.target, random_state=0)
xo, xt = torch.tensor(x_o), torch.tensor(x_t)
print("=== 1. Test NLL (bit/rasm; kam - yaxshi) ===")
print(f" tekis tasodif (har piksel 0.5): {D:.1f} bit")
modellar = {}
for nom, m in [("mustaqil", Mustaqil), ("chiziqli", ChiziqliAR), ("MADE", MADE)]:
m = orgat(m, xo)
modellar[nom] = m
print(f" {nom:<9} parametr {sum(p.numel() for p in m.parameters()):>6}: "
f"o'quv {nll_bit(m, xo):6.2f}, test {nll_bit(m, xt):6.2f} bit")
with torch.no_grad():
har = {n: F.binary_cross_entropy_with_logits(m(xt), xt, reduction="none").sum(1).numpy() / math.log(2)
for n, m in modellar.items()}
f = har["MADE"] - har["chiziqli"]
se = f.std(ddof=1) / math.sqrt(len(f))
print(f" MADE - chiziqli (juftlashgan, {len(f)} test rasm): {f.mean():+.2f} bit, SE {se:.2f} -> "
f"{'MADE sezilarli yaxshi' if f.mean() < -2 * se else "sezilarli farq yo'q"}")
hakam = klassifikator_orgat(xo, torch.tensor(y_o))
with torch.no_grad():
pt = torch.softmax(hakam(xt), -1)
print(f"\n=== 2. Piksel-piksel namunalar (hakam: binar test aniqligi "
f"{(pt.argmax(1).numpy() == y_t).mean():.3f}) ===")
print(f" haqiqiy test: ishonch > 0.9 ulushi {(pt.max(1).values > 0.9).float().mean().item():.3f}")
namunalar = {}
for nom, m in modellar.items():
x = namuna_ol(m, 1000, torch.Generator().manual_seed(1))
namunalar[nom] = x
with torch.no_grad():
p = torch.softmax(hakam(x), -1)
soni = np.bincount(p.argmax(1).numpy(), minlength=10)
print(f" {nom:<9} ishonch > 0.9 ulushi {(p.max(1).values > 0.9).float().mean().item():.3f}; "
f"sinflar: {' '.join(map(str, soni))}")
if nom != "chiziqli":
for r in range(8):
print(" " + " ".join("".join("#" if v else "." for v in im.view(8, 8)[r].tolist())
for im in x[:6]))
print("\n=== 3. LL ning cheklovi: 1% MADE + 99% tasodifiy shovqin ===")
nll_aralash = -np.log2(0.01 * 2.0 ** (-har["MADE"]) + 0.99 * 2.0 ** (-D))
print(f" aralash model test NLL: {nll_aralash.mean():.2f} bit "
f"(MADE {har['MADE'].mean():.2f} + ~{math.log2(100):.2f})")
print(f" mustaqil model test NLL: {har['mustaqil'].mean():.2f} bit")
g = torch.Generator().manual_seed(2)
tanlov = torch.rand(1000, generator=g) < 0.01
x = torch.where(tanlov[:, None], namuna_ol(modellar["MADE"], 1000, g),
torch.bernoulli(torch.full((1000, D), 0.5), generator=g))
print(f" aralash modeldan 1000 namuna: MADE dan {int(tanlov.sum())} ta, qolgani shovqin")
print(" manba ishonch > 0.9 eng yaqin o'quv rasmigacha (Hamming)")
for nom, v in [("haqiqiy test", xt), ("MADE", namunalar["MADE"]),
("mustaqil", namunalar["mustaqil"]), ("aralash", x)]:
with torch.no_grad():
ish = torch.softmax(hakam(v), -1).max(1).values
masofa = torch.cdist(v, xo, p=1).min(1).values
print(f" {nom:<18} {(ish > 0.9).float().mean().item():>12.3f} {masofa.mean().item():>10.2f}")
if nll_aralash.mean() < har["mustaqil"].mean():
print(" -> LL bo'yicha aralash 'mustaqil' dan yaxshi, lekin namunalarning ~99% i shovqin")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Test NLL (bit/rasm; kam - yaxshi) ===
tekis tasodif (har piksel 0.5): 64.0 bit
mustaqil parametr 64: o'quv 37.83, test 37.98 bit
chiziqli parametr 4160: o'quv 26.08, test 26.57 bit
MADE parametr 20736: o'quv 23.19, test 25.26 bit
MADE - chiziqli (juftlashgan, 450 test rasm): -1.31 bit, SE 0.13 -> MADE sezilarli yaxshi
=== 2. Piksel-piksel namunalar (hakam: binar test aniqligi 0.933) ===
haqiqiy test: ishonch > 0.9 ulushi 0.920
mustaqil ishonch > 0.9 ulushi 0.520; sinflar: 48 113 117 114 82 52 55 82 245 92
...##... ...##... ....#... ...##... #..###.. ...##...
...###.. ....###. ..#..#.. ...#.#.. #.##.#.. .#.##...
...#..#. ...##... .##..#.. #.###... .##.##.. ..#...#.
##..#... ..####.# .####.#. ...#.... ...##.#. ..###...
..#.##.. ...##... ..#.###. ...##... ...##..# ###.....
.....#.. ....#.#. .....#.. ......#. ..#...#. ..#.#...
..#.###. ..###... .#.##... ...###.# ...##.#. ...###..
...#.#.. ..###... ..##.#.. ...#.#.. ...#..#. ...##...
chiziqli ishonch > 0.9 ulushi 0.689; sinflar: 80 126 107 130 87 111 75 83 86 115
MADE ishonch > 0.9 ulushi 0.727; sinflar: 71 120 96 97 104 101 98 88 96 129
...##... ...##... ....#... ....#... ...###.. ...##...
...##... ...##... ........ ...#.... ..##.#.. ...##...
...#.... ...##... ..##.... ..##.... .##..#.. ...#..#.
....#... ..###... .####.#. ..##.... ..###... ..##..#.
..####.. ..###... ..####.. ..###... ...##... .###..#.
..##.#.. ...##... .....#.. ..###.#. ...##... ..###...
..#.###. ...##... ....#... ...##.#. ...##... ...###..
...###.. ...##... ........ ...###.. ...#.... ...##...
=== 3. LL ning cheklovi: 1% MADE + 99% tasodifiy shovqin ===
aralash model test NLL: 31.89 bit (MADE 25.26 + ~6.64)
mustaqil model test NLL: 37.98 bit
aralash modeldan 1000 namuna: MADE dan 13 ta, qolgani shovqin
manba ishonch > 0.9 eng yaqin o'quv rasmigacha (Hamming)
haqiqiy test 0.920 3.27
MADE 0.727 4.63
mustaqil 0.520 9.30
aralash 0.539 22.76
-> LL bo'yicha aralash 'mustaqil' dan yaxshi, lekin namunalarning ~99% i shovqinNima ko'rsatdi: 8x8 raqamlarni binar qildik (piksel > 7) va uchta avtoregressiv modelni solishtirdik. Tekis tasodif 64 bit talab qiladi; piksellarni mustaqil deb hisoblaydigan model — 37.98 bit, oldingi piksellarga chiziqli qaraydigan model — 26.57, niqobli MLP (MADE) — 25.26 bit. MADE va chiziqli model orasidagi juftlashgan farq (450 test rasm bo'yicha) -1.31 bit, SE 0.13 — sezilarli; lekin asosiy sakrash "mustaqil" dan "avtoregressiv" ga o'tishda (~11 bit): piksellar orasidagi bog'liqlik raqamning o'zi. MADE ning o'quv va test NLL i orasidagi farq (23.19 va 25.26) biroz ortiqcha moslashishni ko'rsatadi. 2-bo'limda 64 qadamda piksel-piksel namuna oldik. Mustaqil model namunalari — tarqoq nuqtalar, hakam ularning 0.520 qismini "taniydi" va 8 ga og'adi (245 ta — xira dog' hakamga "8" ga o'xshaydi); MADE namunalari — bir-biriga bog'langan chiziqlar, 0.727 taniladi, sinflar tekisroq taqsimlangan. 3-bo'lim LL ning cheklovini raqam bilan ko'rsatdi: 1% MADE va 99% tasodifiy shovqin aralashmasi test NLL da 31.89 bit oldi — mustaqil modeldan yaxshi (37.98), holbuki 1000 namunadan atigi 13 tasi MADE dan, qolgani shovqin. Bu yerda hakam ham aldandi: shovqinli aralashmaga u 0.539 ulushda yuqori ishonch berdi — haqiqiy test rasmlaridan (0.920) past, lekin mustaqil model darajasida. Faqat eng yaqin o'quv rasmigacha Hamming masofasi haqiqatni ochdi: haqiqiy test 3.27, MADE 4.63, aralashma esa 22.76. Xulosa: bitta o'lchov yetmaydi — LL, hakam va masofa birga. Bog'liq bo'limlar: 2.6, 2.7, 2.8.
Misol 4 — Yodlab olish tekshiruvi
"""Yodlab olish tekshiruvi: namunalar o'quv rasmlarining nusxasimi?"""
import warnings
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
from sklearn.datasets import load_digits
from sklearn.decomposition import PCA
from sklearn.mixture import GaussianMixture
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KernelDensity
BELGI = " .:-=+*#%@"
class Klassifikator(nn.Module):
def __init__(self):
super().__init__()
self.h = nn.Linear(64, 128)
self.chiq = nn.Linear(128, 10)
def forward(self, x):
return self.chiq(F.relu(self.h(x / 16)))
def klassifikator_orgat(x, y, seed=0):
torch.manual_seed(seed)
m = Klassifikator()
opt = torch.optim.Adam(m.parameters(), lr=1e-2, weight_decay=1e-4)
xt, yt = torch.tensor(x, dtype=torch.float32), torch.tensor(y)
g = torch.Generator().manual_seed(seed)
for _ in range(60):
for idx in torch.randperm(len(xt), generator=g).split(64):
loss = F.cross_entropy(m(xt[idx]), yt[idx])
opt.zero_grad()
loss.backward()
opt.step()
return m.eval()
@torch.no_grad()
def ishonch(m, x):
return torch.softmax(m(torch.tensor(x, dtype=torch.float32)), -1).max(1).values.numpy()
def eng_yaqin(x, baza):
"""Har x uchun eng yaqin baza rasmigacha Evklid masofa va uning indeksi."""
d = torch.cdist(torch.tensor(x, dtype=torch.float32), torch.tensor(baza, dtype=torch.float32))
m = d.min(1)
return m.values.numpy(), m.indices.numpy()
def ascii_juftlar(chap, ong, izoh):
satrlar = [izoh]
for r in range(8):
satrlar.append(" ".join(
"".join(BELGI[min(9, int(v / 16 * 10))] for v in np.clip(a.reshape(8, 8)[r], 0, 16)) + " | " +
"".join(BELGI[min(9, int(v / 16 * 10))] for v in np.clip(b.reshape(8, 8)[r], 0, 16))
for a, b in zip(chap, ong)))
return satrlar
def main() -> None:
torch.set_num_threads(1)
d = load_digits()
x_oquv, x_test, y_oquv, y_test = train_test_split(
d.data, d.target, test_size=0.25, stratify=d.target, random_state=0)
x_o, x_v = x_oquv[:1000], x_oquv[1000:]
hakam = klassifikator_orgat(x_oquv, y_oquv)
pca = PCA(20, random_state=0).fit(x_o)
z_o, z_v, z_t = pca.transform(x_o), pca.transform(x_v), pca.transform(x_test)
print("=== 1. Ma'lumotnoma: haqiqiy test rasmlari o'quvdan qanchalik uzoq? ===")
d_test, _ = eng_yaqin(x_test, x_o)
chegara = np.quantile(d_test, 0.05)
print(f" test -> eng yaqin o'quv rasmi: median {np.median(d_test):.2f}, 5-foizil {chegara:.2f}")
print(f" 'nusxa' deymiz: eng yaqin o'quvgacha masofa < {chegara:.2f} "
f"(haqiqiy test rasmlarining atigi 5% i)")
print("\n=== 2. KDE kengligini val LL bilan tanlash (PCA-20 fazosida) ===")
qator = []
for h in (0.5, 1.0, 2.0, 3.0, 4.0, 6.0):
kd = KernelDensity(bandwidth=h).fit(z_o)
qator.append((h, kd.score_samples(z_o).mean(), kd.score_samples(z_v).mean()))
for h, tr, va in qator:
print(f" h={h:<4} o'quv LL {tr:8.2f}, val LL {va:8.2f}")
eng_h = max(qator, key=lambda t: t[2])[0]
print(f" -> tanlandi h={eng_h}")
print("\n=== 3. Uch model: LL va namunalar ===")
with warnings.catch_warnings():
warnings.simplefilter("ignore")
modellar = {
"yodlovchi (KDE h=0.5)": KernelDensity(bandwidth=0.5).fit(z_o),
f"KDE h={eng_h}": KernelDensity(bandwidth=eng_h).fit(z_o),
"GMM K=10": GaussianMixture(10, random_state=0).fit(z_o),
}
print(" model o'quv LL test LL ishonch>0.9 masofa(med) nusxa")
namunalar = {}
for nom, m in modellar.items():
if isinstance(m, KernelDensity):
z = m.sample(1000, random_state=1)
else:
z = m.sample(1000)[0][np.random.default_rng(1).permutation(1000)]
x = np.clip(pca.inverse_transform(z), 0, 16)
namunalar[nom] = x
dd, _ = eng_yaqin(x, x_o)
print(f" {nom:<22} {m.score_samples(z_o).mean():8.2f} {m.score_samples(z_t).mean():9.2f} "
f"{np.mean(ishonch(hakam, x) > 0.9):12.3f} {np.median(dd):12.2f} {np.mean(dd < chegara):8.3f}")
print(f" {'haqiqiy test':<22} {'':>8} {'':>9} {np.mean(ishonch(hakam, x_test) > 0.9):12.3f} "
f"{np.median(d_test):12.2f} {np.mean(d_test < chegara):8.3f}")
print("\n=== 4. Namuna | eng yaqin o'quv rasmi ===")
for nom in ("yodlovchi (KDE h=0.5)", "GMM K=10"):
x = namunalar[nom][:4]
_, idx = eng_yaqin(x, x_o)
for s in ascii_juftlar(x, x_o[idx], f" {nom}:"):
print(" " + s)
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Ma'lumotnoma: haqiqiy test rasmlari o'quvdan qanchalik uzoq? ===
test -> eng yaqin o'quv rasmi: median 17.38, 5-foizil 12.02
'nusxa' deymiz: eng yaqin o'quvgacha masofa < 12.02 (haqiqiy test rasmlarining atigi 5% i)
=== 2. KDE kengligini val LL bilan tanlash (PCA-20 fazosida) ===
h=0.5 o'quv LL -11.42, val LL -273.35
h=1.0 o'quv LL -25.29, val LL -88.58
h=2.0 o'quv LL -39.15, val LL -62.01
h=3.0 o'quv LL -47.25, val LL -57.76
h=4.0 o'quv LL -52.98, val LL -58.60
h=6.0 o'quv LL -60.82, val LL -62.74
-> tanlandi h=3.0
=== 3. Uch model: LL va namunalar ===
model o'quv LL test LL ishonch>0.9 masofa(med) nusxa
yodlovchi (KDE h=0.5) -11.42 -323.93 0.954 10.20 0.784
KDE h=3.0 -47.25 -58.66 0.879 15.14 0.081
GMM K=10 -54.57 -57.97 0.902 18.20 0.017
haqiqiy test 0.947 17.38 0.051
=== 4. Namuna | eng yaqin o'quv rasmi ===
yodlovchi (KDE h=0.5):
*+#= | *%#- %%@%: | :%@@@. -*@#. | *#@@% .%@- | :#%-
*%.*= | %%::# =%-+@- | *#=+@+ -@:-%. | -@-:%+ .@+=# | .@+*@.
.@=.+: | .@=:#- . *@. | #@. #= :* | *- .%. :%.:%. | .%..@.
:@@@- | .@@@- -@+ | :@* .+..*= | % #- *%@* | *@@=
.+@: | +@ +@- | +@: . -*: | . -% +##. | =%@.
-%. | .@ .@* | @* *: | %. :+.%= | .* #-
#= | *- -.@% | -=:@% +% | -% ++ #: | =+ %.
%: | @ @@%=. | -@@@= *- | %- :@%= | :@@=
GMM K=10:
+@#*. | %@@: -%@= | -@%. %- | .% -#@#- | :%@%
:@**@: | :@+*@. +#*@ | #@#% +@ | %# +##%- | %**@
-@-+@. | -@ +@. -@@% | ##%% .%: : | =@-. -#: | +*
:**%* | .%*@@- :@@- | .@%. :@%.+= | .@*-@. -*%= | -%@+
:==#- | .*+@- .#@% | +%@. -@**#. | -@**@- +@@#: | *@@+-
. .#= | @- .@.+* | @-+# -*+%@ | -#@%. :#+ | .**
::+@- | ..*@ .@-#% | @::@: .=-@% | @= .#- | %-
+@@= | %@%: =@@#: | -@@#. @*. | .@= =#. | -@.Nima ko'rsatdi: 1-bo'lim ma'lumotnomani o'rnatdi: haqiqiy test rasmlari eng yaqin o'quv rasmidan median 17.38 masofada (piksel birliklarida), ularning atigi 5% i 12.02 dan yaqin — shu qiymatni "nusxa" chegarasi deb oldik. 2-bo'limda KDE kengligi val LL bilan tanlandi (h=3.0); tor h=0.5 o'quvda eng yaxshi LL (-11.42) va val da eng yomon (-273.35) berdi — yodlashning klassik belgisi. 3-bo'lim uchta modelni hamma o'lchov bilan solishtirdi. Yodlovchi KDE: o'quv LL -11.42, test LL -323.93; namunalari hakamga eng ishonchli (0.954 — haqiqiy testdan ham yuqori!), lekin ularning 0.784 qismi "nusxa" chegarasidan yaqin (haqiqiy testda 0.051). Ya'ni faqat "tanib olinish" ga qaragan kishi eng yomon modelni eng yaxshi deb tanlagan bo'lar edi. Val bilan tanlangan KDE (h=3.0) nusxa ulushini 0.081 ga tushirdi, GMM K=10 esa — 0.017; ikkalasining test LL i deyarli bir xil (-58.66 va -57.97). GMM namunalari o'quv rasmlaridan haqiqiy test rasmlari kabi uzoqda (median 18.20 va 17.38), ya'ni yangi. 4-bo'limdagi juftlar buni ko'z bilan ham ko'rsatadi: yodlovchi namunasi va eng yaqin o'quv rasmi deyarli bir xil, GMM namunasi esa eng yaqin qo'shnisidan aniq farq qiladi. Yodlovchi masofasi nolga teng emas (median 10.20), chunki model PCA-20 fazosida ishlaydi va qayta tiklash mayda detallarni yo'qotadi. Bog'liq bo'limlar: 2.3, 2.7, 2.8.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
| "Generativ model — faqat rasm/matn chizadigan model" | U p(x) ni o'rganadi: baholash (anomaliya, LL) va namuna olish — ikki qobiliyat |
| "Klassifikator ham p(x) ni biladi" | Yo'q: 3-misolda hakam 99% shovqindan iborat namunalarning 0.539 qismiga yuqori ishonch berdi |
| "O'quv LL yuqori — model yaxshi" | Yodlovchi KDE: o'quv -11.42, test -323.93 |
| "LL yaxshiroq — namunalar yaxshiroq" | 1% model + 99% shovqin mustaqil modeldan LL da yaxshi (31.89 va 37.98 bit) |
| "Namunalar haqiqiyga o'xshasa — model yaxshi" | Yodlovchi namunalari eng "ishonchli" (0.954), lekin 0.784 qismi nusxa |
| "Ko'p komponent — yaxshi GMM" | Digits da K=40 val LL -96.88, K=10 — -57.69 |
| "Turli modellarning LL ini to'g'ridan-to'g'ri solishtirsa bo'ladi" | Faqat bir xil fazo va bir xil birlikda |
| "Avtoregressiv faqat matn uchun" | 3-misolda piksel-piksel: MADE 25.26 bit/rasm |
| "GAN, VAE, diffusion — bir xil narsa" | p(x) aniqligi, namuna tezligi va barqarorlik bo'yicha tubdan farq qiladi |
6. Keng tarqalgan xatolar va yechimlari
1. O'quv LL bilan tanlash
eng = max(modellar, key=lambda m: m.score(x_oquv)) # ⚠️
eng = max(modellar, key=lambda m: m.score(x_val)) # ✅2. Silliqlashsiz gistogramma
p = soni / soni.sum() # bo'sh katak -> log 0 = -inf # ⚠️
p = (soni + 0.5) / (soni + 0.5).sum() # ✅3. GaussianMixture.sample ni aralashtirmaslik
x, _ = gm.sample(1000); korsat(x[:6]) # hammasi 0-komponentdan # ⚠️
x, _ = gm.sample(1000)
x = x[np.random.default_rng(1).permutation(len(x))]; korsat(x[:6]) # ✅4. Turli fazodagi LL ni solishtirish
print(gmm_pca20.score(z_test), made_bit_rasm) # ⚠️
# bir xil fazo va birlikda: hammasi PCA-20 da yoki hammasi bit/rasm da # ✅5. Avtoregressiv niqobda diagonal
niqob = tartib[:, None] >= tartib[None, :] # piksel o'zini ko'radi # ⚠️
niqob = tartib[:, None] > tartib[None, :] # ✅6. Modelni urug'dan oldin yaratish
modellar = [MADE(), ChiziqliAR()]; torch.manual_seed(0) # ⚠️
torch.manual_seed(0); model = MADE() # ✅7. Yodlashni tekshirmaslik
print("namunalar juda realistik!") # ⚠️
d_nn = torch.cdist(namuna, oquv).min(1).values
print((d_nn < np.quantile(d_test_nn, 0.05)).float().mean()) # ✅7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 09-qism (o'tilgan): ehtimollik taqsimotlari, zichlik, Bayes formulasi
- 16-qism (o'tilgan): GMM va EM 16.6-bob, PCA 16.8-bob, anomaliya aniqlash 16.10-bob — past zichlik = anomaliya
- 24.9-dars (o'tilgan): GPT — avtoregressiv generativ model, cross-entropy = maksimal likelihood, namuna olish strategiyalari
- 25-qism (o'tilgan): LLM — shartli avtoregressiv generatsiya; baholash va xavfsizlik (25.10, 25.13)
- Keyingi darslar: 26.2 — VAE (latent o'zgaruvchi, ELBO); 26.3-26.4 — GAN; 26.5-26.6 — diffusion; 26.7 — Frechet masofa va boshqa baholash usullari; 26.9 — yodlash, maxfiylik va etika
8. Eng yaxshi amaliyotlar
Modelni held-out LL bo'yicha tanlang; o'quv LL faqat ortiqcha moslashishni ko'rish uchun.
Zichlik modelida har yerda musbat ehtimol bo'lsin (silliqlash, minimal kenglik).
LL ni faqat bir xil fazo va birlikda solishtiring; birlikni (nat, bit/rasm) doim yozing.
Namunalarni mustaqil hakam-klassifikator bilan o'lchang va qiymatni haqiqiy test rasmlaridagi bilan solishtiring.
Sinf taqsimotini tekshiring — biror sinf yaratilmayotgan bo'lishi mumkin.
Har generativ modelda yodlab olish tekshiruvini o'tkazing: eng yaqin o'quv namunasigacha masofa va test asosidagi chegara.
Sodda etalondan boshlang (mustaqil model, bitta Gauss, KDE) — murakkab model undan sezilarli yaxshi bo'lishi kerak.
Namuna olishni
torch.Generator/random_statebilan takrorlanadigan qiling; modelni urug'dan keyin yarating.
9. Amaliy topshiriq
Vazifa 1: Bashorat qiling
1. # diskriminativ va generativ model nimani o'rganadi?
2. # p(x|y) va p(y) dan p(y|x) ni qanday olamiz?
3. # max E[log p_theta(x)] qaysi KL ni minimallashtiradi?
4. # silliqlashsiz gistogrammada bitta val nuqtasi bo'sh katakda - o'rtacha LL?
5. # KDE da h -> 0 bo'lsa o'quv LL va test LL nima bo'ladi?
6. # 8x8 binar rasm uchun tekis tasodif necha bit?
7. # avtoregressiv modelda namuna olish uchun nechta forward kerak (64 piksel)?
8. # 1% model + 99% shovqin aralashmasi LL ni necha bitga yomonlashtiradi (ko'pi bilan)?
9. # GAN p(x) ni beradimi?
10. # nega hakam-klassifikator ishonchi yetarli o'lchov emas?
11. # "nusxa" chegarasini nimaga qarab tanlaymiz?
12. # PCA-20 dagi GMM LL ini bit/rasm dagi MADE NLL i bilan solishtirsa bo'ladimi?Javoblar
- Diskriminativ —
p(y|x); generativ —p(x)yokip(x|y) - Bayes:
p(y|x) = p(x|y) p(y) / p(x),p(x) = sum_y p(x|y) p(y) KL(p_data || p_theta)-inf- O'quv LL
+infga intiladi (har nuqta ustida igna), test LL-infga - 64 bit
- 64 ta ketma-ket forward
log2(100) ~ 6.64bit- Yo'q — faqat namuna chiqaradi
- Hakam
p(x)ni bilmaydi: shovqinga ham yuqori ishonch beradi (3-misolda0.539), nusxalarga esa eng yuqori (0.954) - Haqiqiy test namunalarining eng yaqin o'quv namunasigacha masofasi taqsimotiga (masalan 5-foizil)
- Yo'q — boshqa fazo va boshqa birlik (uzluksiz log-zichlik va diskret bit)
Vazifa 2: Xatolarni tuzating
1. natija = {k: GaussianMixture(k).fit(x_oquv).score(x_oquv) for k in (1, 5, 10, 40)}
eng_k = max(natija, key=natija.get)
2. x, _ = gm.sample(500)
print("birinchi 10 namuna sinflari:", hakam(x[:10]).argmax(1))
3. niqob = torch.tril(torch.ones(64, 64))
logit = F.linear(x, W * niqob, b)
4. models = [MADE() for _ in range(3)]
for s, m in enumerate(models):
torch.manual_seed(s); orgat(m)
5. print("yangi raqamlar sifatli:", (hakam_ishonch(namunalar) > 0.9).mean())Javoblar
1. natija = {k: GaussianMixture(k, random_state=0).fit(x_oquv).score(x_val)
for k in (1, 5, 10, 40)} # val LL bilan, urug' bilan
eng_k = max(natija, key=natija.get)
2. x, _ = gm.sample(500)
x = x[np.random.default_rng(0).permutation(len(x))] # komponent tartibini buzish
print("birinchi 10 namuna sinflari:", hakam(x[:10]).argmax(1))
3. niqob = torch.tril(torch.ones(64, 64), diagonal=-1) # diagonal YO'Q: j < i
logit = F.linear(x, W * niqob, b)
4. models = []
for s in range(3):
torch.manual_seed(s) # urug' YARATISHDAN oldin
models.append(orgat(MADE()))
5. tanish = (hakam_ishonch(namunalar) > 0.9).mean()
tanish_test = (hakam_ishonch(x_test) > 0.9).mean() # ma'lumotnoma
d_nn = torch.cdist(namunalar, oquv).min(1).values # + yodlash tekshiruvi
print(tanish, tanish_test, (d_nn < chegara).float().mean())Vazifa 3: 2D zichlik
Modellang:
- "Ikki oy" (
make_moons,noise=0.1) taqsimotida gistogramma, KDE va GMM - Har oilada val LL bilan tanlash
- 5 urug'da juftlashgan test LL va "eng sodda" qoidasi
- Namunalarni ASCII da chizish
Vazifa 4: Digits generatsiyasi
Modellang:
- PCA ning 10, 20, 30 komponentida GMM
- Har biri uchun hakam bilan tanib olinish va sinf taqsimoti
- Qaysi PCA o'lchovida namunalar eng yaxshi?
Vazifa 5: Avtoregressiv model
Modellang:
- Piksel tartibini o'zgartiring (ustun bo'yicha yoki tasodifiy)
- Test NLL tartibga bog'liqmi? (Nazariy jihatdan zanjir qoidasi har tartibda aniq)
- MADE da yashirin qatlamni 64 va 256 ga o'zgartirib, o'quv/test NLL farqini kuzating
Vazifa 6: Yodlash
Modellang:
- KDE kengligini 0.5 dan 6 gacha o'zgartiring
- Har biri uchun test LL va "nusxa" ulushi
- Ikkalasini bitta jadvalda — qaysi kenglikda ikkalasi ham maqbul?
Vazifa 7: O'ylash
Mahsulot menejeri aytdi: "Bizning sintetik mijozlar generatorimiz ajoyib — tahlilchilar 100 ta yozuvdan qaysi biri sintetik ekanini topa olmadi. Keling, ularni hamkor kompaniyaga maxfiy ma'lumot o'rniga beraylik." Siz nima deysiz?
Javob
Qisqa javob: "ajratib bo'lmaydi" — xavfsizlik belgisi emas; eng realistik generator ko'pincha eng ko'p yodlagan generator bo'ladi. Berishdan oldin yodlab olish tekshiruvi shart.
1. Nega xavfli. 4-misolda yodlovchi KDE namunalari hakamga eng "haqiqiy" ko'rindi (0.954 — haqiqiy test rasmlaridan ham yuqori), lekin ularning 0.784 qismi o'quv namunalarining deyarli nusxasi edi. Inson tahlilchisi ham xuddi shunday aldanadi: nusxa haqiqiydan farq qilmaydi, chunki u haqiqiy.
2. Nima o'lchash kerak. Har sintetik yozuv uchun eng yaqin haqiqiy (o'quv) yozuvgacha masofa; ma'lumotnoma — modelga kirmagan haqiqiy test yozuvlarining o'sha masofasi. Nusxa ulushi test darajasidan (5% chegara bilan — 0.05 atrofida) sezilarli yuqori bo'lsa — generator yodlagan.
3. Qo'shimcha tekshiruvlar. Kam uchraydigan kombinatsiyalar (masalan, noyob kasb + kichik shahar + yosh) sintetik ma'lumotda aynan takrorlanyaptimi — ular shaxsni aniqlashga yetadi. Held-out LL — o'quv LL dan juda farq qilsa, model yodlagan.
4. Himoya. Kamroq murakkab model yoki kuchliroq regulyarizatsiya (4-misolda val bilan tanlangan kenglik nusxa ulushini 0.784 dan 0.081 ga tushirdi), differentsial maxfiylik bilan o'rgatish, yuridik ko'rib chiqish.
Tavsiya:
# 1. d_nn(sintetik -> o'quv) va d_nn(test -> o'quv) taqsimotlarini solishtirish
# 2. nusxa ulushi (test 5-foizili chegara) - test darajasida bo'lishi kerak
# 3. noyob kombinatsiyalar tekshiruvi
# 4. o'quv va held-out LL farqi
# 5. natijalar maxfiylik bo'limi bilan kelishilgandan keyin berishMenejerga javob: "Tahlilchilar farqlay olmagani — sifat belgisi, lekin maxfiylik belgisi emas: agar generator haqiqiy mijozlarni yodlagan bo'lsa, ular ham haqiqiydan farq qilmaydi. Keling, avval har sintetik yozuvning eng yaqin haqiqiy yozuvgacha masofasini o'lchaymiz va nusxa ulushini haqiqiy yangi yozuvlardagi darajasi bilan solishtiramiz. Shundan keyingina berish haqida gaplashamiz."
Nimani mustahkamlaydi: 2.3, 2.7, 2.8-bo'limlar.
Xulosa
Bu darsda generativ modellashtirishning asosiy g'oyalarini kichik, lekin haqiqiy tajribalarda ko'rdik: 2D va 8x8 rasmlarda zichlikni baholash, namuna olish, avtoregressiv piksel modeli va yodlab olish tekshiruvi.
Eng muhim uch fikr:
Generativ model
p(x)ni o'rganadi va held-out LL bilan tanlanadi. 1-misolda haqiqiy taqsimotning test LL i-2.062; val bilan tanlangan GMM (K=16, 95 son)-2.108ga yetdi va KDE (-2.125) hamda gistogrammadan (-2.361) juftlashgan taqqoslashda sezilarli yaxshi chiqdi. Hamma oilada o'quv LL murakkablik bilan o'sdi, val LL esa bir nuqtadan keyin tushdi; digits da GMMK=40val LL-96.88ga qulab tushdi (K=10—-57.69). Silliqlashsiz gistogramma bitta bo'sh katak tufayli-infberdi.Log-likelihood yetarli emas — namuna-asosli o'lchovlar bilan birga. 3-misolda avtoregressiv MADE test NLL
25.26bit/rasm berdi (mustaqil model37.98), lekin 1% MADE va 99% shovqin aralashmasi ham31.89bit bilan mustaqil modelni "yutdi". Hakam-klassifikator ham aldanadi — shovqinli aralashmaning0.539qismiga yuqori ishonch berdi; faqat eng yaqin o'quv rasmigacha masofa (22.76, haqiqiy testda3.27) haqiqatni ochdi. 2-misolda hakam bitta Gauss (0.478) vaK=10GMM (0.865) namunalarini aniq ajratdi, sinf taqsimoti esa ikkalasida ham tekis edi.Yodlab olishni tekshirish — generativ modelni baholashning birinchi qadami. 4-misolda yodlovchi KDE namunalari hakamga eng ishonchli ko'rindi (
0.954), lekin ularning0.784qismi o'quv rasmlarining nusxasi edi (haqiqiy test rasmlarida0.051); test LL esa-323.93. Val bilan tanlangan KDE va GMM nusxa ulushini0.081va0.017ga tushirdi.
Keyingi darsda Avtoenkoder va VAE: rasmni kichik latent vektorga siqib, qayta tiklaydigan tarmoq quramiz, oddiy avtoenkoder latentidan namuna olish nega yomon ishlashini o'lchaymiz va VAE qanday qilib latent fazoni namuna olishga yaroqli qilishini — ELBO va reparametrizatsiya hiylasi orqali — ko'ramiz.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!