Mundarija (22)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Bayes formulasidan modelgacha
- 2.2. "Sodda" taxmin nega ishlaydi
- 2.3. Uch variant
- 2.4. Silliqlash
- 2.5. Matn bilan ishlash
- 2.6. Kalibrlash muammosi
- 2.7. Tuzoqlar
- 2.8. Tez, sodda va kutilmaganda kuchli
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — Qo'lda Bayes: spam filtri
- Misol 2 — "Sodda" taxmin buzilganda
- Misol 3 — Uch variant va belgi turi
- Misol 4 — Matn tasniflash: NB va boshqalar
- 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
14.3-dars: Naive Bayes
14-QISM — KLASSIFIKATSIYA · 3-dars
1. Kirish va motivatsiya
Naive Bayes — ehtimollar nazariyasiga (9-qism) to'g'ridan-to'g'ri asoslangan klassifikator. U Bayes formulasini qo'llaydi va bitta "sodda" (naive) taxmin qiladi: belgilar sinf berilganda o'zaro mustaqil. Bu taxmin deyarli har doim noto'g'ri — lekin model baribir ajoyib ishlaydi, ayniqsa matn bilan.
Naive Bayes muhim, chunki u: eng tez klassifikator (bitta o'tish yetarli), kam ma'lumotda barqaror, minglab belgi bilan bemalol ishlaydi va spam filtrlar, matn tasniflagichlar, tibbiy skriningda hali ham qo'llaniladi.
Bu darsda: Bayes formulasidan modelgacha, "sodda" taxminning ma'nosi, uch variant (Gaussian, Multinomial, Bernoulli), silliqlash (Laplace), matn bilan ishlash va nega ehtimollari kalibrlanmagan.
Real vaziyat. Qo'llab-quvvatlash xizmati kuniga 4 000 ta xat oladi va ularni 9 ta kategoriyaga ajratishi kerak. Neyron tarmoq 87% aniqlik berdi, lekin har o'zgarishda 40 daqiqa o'qitish va GPU talab qildi. Multinomial Naive Bayes + TF-IDF 83% berdi va 1.2 soniyada o'qitiladi — jamoa uni tanladi: har kuni yangilanadi, hech qanday infratuzilma kerak emas.
Bu darsda Naive Bayes ni o'rganamiz.
Bu darsda:
- Bayes formulasidan modelgacha
- "Sodda" taxmin
- Uch variant
- Silliqlash
- Matn bilan ishlash
- Kalibrlash muammosi
- Tuzoqlar
- Amaliy: matn tasniflash
ℹ Misollar real numpy/sklearn bilan (Python 3.14).
2. Nazariya — chuqur tushuntirish
2.1. Bayes formulasidan modelgacha
Bayes (9-qism): P(y | x) = P(x | y) · P(y) / P(x)
Bashorat: argmax_k P(y=k) · P(x | y=k) (P(x) hammaga bir xil — tushib qoladi)
Muammo: P(x | y) — ko'p o'lchamli taqsimot, uni baholash uchun juda ko'p ma'lumot kerak
(10 ta binar belgi → 2^10 = 1024 kombinatsiya har sinf uchun)
NAIVE taxmin: belgilar sinf berilganda mustaqil
P(x | y) = P(x1 | y) · P(x2 | y) · ... · P(xp | y)
→ har belgi uchun alohida bir o'lchovli taqsimot yetarli "Sodda" taxmin hisoblash muammosini hal qiladi: 2^p ta parametr o'rniga p ta bir o'lchovli taqsimot. Amalda ehtimollar logarifmda yig'iladi (log P(y) + sum log P(xj|y)) — bu ko'paytmaning nolga aylanishini oldini oladi va tezroq ishlaydi.
2.2. "Sodda" taxmin nega ishlaydi
Taxmin deyarli HAR DOIM noto'g'ri:
matnda "mashina" va "o'rganish" so'zlari mustaqil emas
Lekin klassifikatsiya uchun ehtimol QIYMATI emas, TARTIBI muhim:
argmax to'g'ri sinfni tanlasa yetarli
Bog'liq belgilar "ovozni ikki marta sanaydi" → ehtimollar 0 yoki 1 ga siljiydi
→ BASHORAT ko'pincha to'g'ri, EHTIMOL esa haddan tashqari ishonchli Bu — Naive Bayes ning asosiy paradoksi: noto'g'ri taxmin, to'g'ri bashorat. Sabab: qaror uchun argmax yetarli, aniq ehtimol emas. Shuning uchun NB ni reyting yoki yorliq uchun ishlating, predict_proba natijasini esa ehtimol sifatida ishlatmang (14.10 — kalibrlash).
2.3. Uch variant
GaussianNB — uzluksiz belgilar; har belgi sinf ichida normal taqsimlangan deb
parametrlar: har sinf va belgi uchun o'rtacha va dispersiya
MultinomialNB — SANOQ belgilar (so'z chastotasi, TF-IDF); matn uchun standart
BernoulliNB — BINAR belgilar (so'z bor/yo'q); qisqa matnlarda yaxshi
CategoricalNB — kategorik belgilar
Aralash belgilar bo'lsa: har turga alohida NB va ehtimollarni ko'paytirish
yoki boshqa algoritm Variant belgi turidan kelib chiqadi — bu eng ko'p xato qilinadigan joy. Matnda MultinomialNB (chastota) yoki BernoulliNB (mavjudlik); jadval ma'lumotida GaussianNB. Noto'g'ri variant tanlansa, natija keskin yomonlashadi.
2.4. Silliqlash
Muammo: o'quvda uchramagan so'z → P(so'z | sinf) = 0 → butun ko'paytma 0
Laplace (additive) silliqlash:
P(xj | y) = (sanoq + alpha) / (jami + alpha · V)
alpha = 1 — Laplace; alpha < 1 — Lidstone; alpha = 0 — silliqlashsiz (xavfli)
sklearn: MultinomialNB(alpha=1.0), BernoulliNB(alpha=1.0)
alpha — CV bilan tanlanadi (odatda 0.01..1.0) Silliqlash — NB ning majburiy qismi: usiz bitta noma'lum so'z butun bashoratni nolga tushiradi. alpha regularizatsiya rolini ham bajaradi: katta alpha modelni bir tekisroq (ehtiyotkorroq) qiladi. Uni CV bilan tanlash odatda sezilarli yaxshilanish beradi.
2.5. Matn bilan ishlash
from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
from sklearn.naive_bayes import ComplementNB, MultinomialNB
from sklearn.pipeline import Pipeline
Pipeline([("vec", TfidfVectorizer(ngram_range=(1, 2), min_df=2)),
("m", MultinomialNB(alpha=0.1))])
ComplementNB — nomutanosib matn to'plamlari uchun MultinomialNB ning yaxshilangan varianti Matn — NB ning tabiiy sohasi: minglab siyrak belgi, ko'p sinf, tez o'qitish. TfidfVectorizer (chastota × teskari hujjat chastotasi) odatda oddiy sanoqdan yaxshiroq. ComplementNB nomutanosib to'plamlarda MultinomialNB dan barqarorroq.
2.6. Kalibrlash muammosi
NB ehtimollari haddan tashqari ishonchli: 0.999 yoki 0.001 ga intiladi
sabab: bog'liq belgilar "dalilni" bir necha marta sanaydi
Oqibat:
· reyting (AUC) yaxshi bo'lishi mumkin
· ehtimol qiymati yaroqsiz (narx formulalariga kiritib bo'lmaydi — 9.9)
Yechim: CalibratedClassifierCV (sigmoid yoki isotonic) — 14.10Bu — NB ni logistik regressiyadan ajratadigan asosiy amaliy farq 13.10-bob: LogReg kalibrlangan ehtimol beradi, NB esa yo'q. Agar sizga faqat yorliq yoki reyting kerak bo'lsa, farq yo'q; ehtimol kerak bo'lsa — kalibrlash shart.
2.7. Tuzoqlar
Asosiy tuzoqlar: noto'g'ri variant tanlash (matnda GaussianNB); silliqlashsiz ishlatish; predict_proba ni ehtimol deb ishlatish; GaussianNB ni kuchli qiyshiq belgilar bilan (avval log yoki quantile transformatsiya); korrelyatsiyalangan belgilar ko'p bo'lsa ishonchni oshirib yuborishi; alpha ni CV siz qoldirish; matnda stop so'zlar va min_df ni sozlamaslik; NB ni jadval ma'lumotida boshqa modellarsiz tanlash.
2.8. Tez, sodda va kutilmaganda kuchli
Naive Bayes Bayes formulasini "belgilar sinf ichida mustaqil" taxmini bilan qo'llaydi: p ta bir o'lchovli taqsimot yetarli bo'ladi. Taxmin deyarli har doim noto'g'ri, lekin argmax to'g'ri chiqadi — shuning uchun bashorat yaxshi, ehtimol esa kalibrlanmagan. Variant belgi turidan kelib chiqadi: Gaussian (uzluksiz), Multinomial (sanoq/TF-IDF), Bernoulli (binar). Silliqlash (alpha) majburiy. Keyingi dars — LDA va QDA.
3. Tez ma'lumotnoma
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import GridSearchCV
from sklearn.naive_bayes import BernoulliNB, ComplementNB, GaussianNB, MultinomialNB
from sklearn.pipeline import Pipeline
GaussianNB() # uzluksiz belgilar
MultinomialNB(alpha=1.0) # sanoq / TF-IDF
BernoulliNB(alpha=1.0, binarize=0.0) # binar
matn = Pipeline([("vec", TfidfVectorizer(min_df=2, ngram_range=(1, 2))),
("m", MultinomialNB())])
GridSearchCV(matn, {"m__alpha": [0.01, 0.05, 0.1, 0.5, 1.0]}, cv=5)
model.feature_log_prob_ # log P(belgi | sinf)
model.class_log_prior_ # log P(sinf)
QOIDA: variantni belgi turiga moslang · alpha ni sozlang · ehtimolga ishonmangNaive Bayes xulosasi
argmax P(y) · prod P(xj|y) · log fazoda yig'indi
Taxmin noto'g'ri, bashorat to'g'ri; ehtimol kalibrlanmagan
Gaussian / Multinomial / Bernoulli — belgi turiga qarab
alpha silliqlash majburiy · matn uchun eng tez tanlov4. Batafsil misollar
Misollar real numpy/sklearn bilan (Python 3.14).
Misol 1 — Qo'lda Bayes: spam filtri
"""Naive Bayes ni nolldan hisoblash (real numpy/sklearn)."""
import numpy as np
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
def main() -> None:
xatlar = [
("bepul chegirma yutuq hoziroq bosing", 1),
("yutuq bepul sovg'a bosing havola", 1),
("chegirma aksiya bepul yetkazib berish", 1),
("hisobot tayyor uchrashuv ertaga", 0),
("loyiha hisobot jamoa uchrashuv", 0),
("ertaga jamoa yig'ilish rejasi", 0),
]
matn = [m for m, _ in xatlar]
y = np.array([t for _, t in xatlar])
vec = CountVectorizer()
X = vec.fit_transform(matn).toarray()
sozlar = vec.get_feature_names_out()
print("=== 1. Lug'at ===")
print(f" {len(sozlar)} ta so'z, {len(matn)} ta xat "
f"({y.sum()} spam, {(y == 0).sum()} oddiy)")
print("\n=== 2. Qo'lda hisoblash (alpha = 1) ===")
alpha = 1.0
V = len(sozlar)
log_oldin = {}
log_ehtimol = {}
for k in [0, 1]:
mos = X[y == k]
log_oldin[k] = np.log((y == k).sum() / len(y))
sanoq = mos.sum(axis=0)
log_ehtimol[k] = np.log((sanoq + alpha) / (sanoq.sum() + alpha * V))
print(f" log P(spam) = {log_oldin[1]:.4f}, log P(oddiy) = {log_oldin[0]:.4f}")
print("\n=== 3. Yangi xatni tasniflash ===")
yangi = "bepul yutuq hoziroq"
x = vec.transform([yangi]).toarray()[0]
ballar = {k: log_oldin[k] + float(x @ log_ehtimol[k]) for k in [0, 1]}
print(f" xat: '{yangi}'")
print(f" log-ball: oddiy {ballar[0]:.4f}, spam {ballar[1]:.4f}")
maks = max(ballar.values())
norm = {k: np.exp(v - maks) for k, v in ballar.items()}
jami = sum(norm.values())
print(f" ehtimollar: oddiy {norm[0] / jami:.4f}, spam {norm[1] / jami:.4f}")
print("\n=== 4. sklearn bilan tekshirish ===")
m = MultinomialNB(alpha=1.0).fit(X, y)
p = m.predict_proba(x.reshape(1, -1))[0]
print(f" sklearn ehtimollari: oddiy {p[0]:.4f}, spam {p[1]:.4f}")
print(f" qo'lda hisoblangan bilan mos: "
f"{np.allclose([norm[0] / jami, norm[1] / jami], p)}")
eng = np.argsort(m.feature_log_prob_[1] - m.feature_log_prob_[0])[::-1][:4]
print(f" eng 'spamli' so'zlar: {[sozlar[i] for i in eng]}")
print(" ⭐ NB — bir necha satr kod va bitta o'tish")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Lug'at ===
19 ta so'z, 6 ta xat (3 spam, 3 oddiy)
=== 2. Qo'lda hisoblash (alpha = 1) ===
log P(spam) = -0.6931, log P(oddiy) = -0.6931
=== 3. Yangi xatni tasniflash ===
xat: 'bepul yutuq hoziroq'
log-ball: oddiy -11.0904, spam -8.0942
ehtimollar: oddiy 0.0476, spam 0.9524
=== 4. sklearn bilan tekshirish ===
sklearn ehtimollari: oddiy 0.0476, spam 0.9524
qo'lda hisoblangan bilan mos: True
eng 'spamli' so'zlar: ['bepul', 'chegirma', 'yutuq', 'bosing']
⭐ NB — bir necha satr kod va bitta o'tishNima ko'rsatdi: 2.1, 2.4-bo'limlar.
Misol 2 — "Sodda" taxmin buzilganda
"""Bog'liq belgilar bashoratga va ehtimolga qanday ta'sir qiladi (real numpy/sklearn)."""
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import brier_score_loss, log_loss, roc_auc_score
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import GaussianNB
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
def yarat(takror: int, seed: int = 5, n: int = 4000):
"""Bitta ma'noli belgi 'takror' marta nusxalanadi (kuchli bog'liqlik)."""
rng = np.random.default_rng(seed)
y = rng.integers(0, 2, n)
asos = rng.normal(y * 1.2, 1.0, n)
ustunlar = [asos + rng.normal(0, 0.05, n) for _ in range(takror)]
shovqin = rng.normal(0, 1, (n, 3))
X = np.column_stack(ustunlar + [shovqin])
return X, y
def main() -> None:
print("=== 1. Nusxalar soni ortganda ===")
print(f" {'nusxa':>6} {'NB aniqlik':>11} {'NB AUC':>8} {'NB log-loss':>12} "
f"{'NB Brier':>9}")
for takror in [1, 2, 5, 15]:
X, y = yarat(takror)
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.3, random_state=0,
stratify=y)
m = GaussianNB().fit(Xtr, ytr)
p = m.predict_proba(Xte)[:, 1]
print(f" {takror:>6} {(m.predict(Xte) == yte).mean():>11.4f} "
f"{roc_auc_score(yte, p):>8.4f} {log_loss(yte, p):>12.4f} "
f"{brier_score_loss(yte, p):>9.4f}")
print(" (aniqlik va AUC deyarli o'zgarmaydi, ehtimol sifati yomonlashadi)")
print("\n=== 2. Ehtimollar taqsimoti ===")
for takror in [1, 15]:
X, y = yarat(takror)
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.3, random_state=0,
stratify=y)
p = GaussianNB().fit(Xtr, ytr).predict_proba(Xte)[:, 1]
chekka = ((p < 0.01) | (p > 0.99)).mean()
print(f" nusxa {takror:>2}: chekka ehtimollar (<0.01 yoki >0.99) ulushi "
f"{chekka:.1%}, o'rtacha {p.mean():.3f}")
print("\n=== 3. Logistik regressiya bilan solishtirish ===")
X, y = yarat(15)
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.3, random_state=0,
stratify=y)
log = Pipeline([("sc", StandardScaler()),
("m", LogisticRegression(max_iter=2000))]).fit(Xtr, ytr)
nb = GaussianNB().fit(Xtr, ytr)
for nom, m in [("GaussianNB", nb), ("LogReg", log)]:
p = m.predict_proba(Xte)[:, 1]
print(f" {nom:<11}: aniqlik {(m.predict(Xte) == yte).mean():.4f}, "
f"AUC {roc_auc_score(yte, p):.4f}, "
f"log-loss {log_loss(yte, p):.4f}, Brier {brier_score_loss(yte, p):.4f}")
print("\n=== 4. Kalibrlash egri chizig'i ===")
from sklearn.calibration import calibration_curve
p_nb = nb.predict_proba(Xte)[:, 1]
haqiqiy, bashorat = calibration_curve(yte, p_nb, n_bins=5, strategy="quantile")
for b, h in zip(bashorat, haqiqiy):
print(f" NB bashorat {b:.4f} → haqiqiy ulush {h:.4f}")
print(" ⭐ Bashorat to'g'ri, ehtimol haddan tashqari ishonchli")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Nusxalar soni ortganda ===
nusxa NB aniqlik NB AUC NB log-loss NB Brier
1 0.7325 0.7982 0.5454 0.1833
2 0.7275 0.7993 0.6140 0.1952
5 0.7275 0.7999 1.1042 0.2306
15 0.7258 0.7997 3.0388 0.2591
(aniqlik va AUC deyarli o'zgarmaydi, ehtimol sifati yomonlashadi)
=== 2. Ehtimollar taqsimoti ===
nusxa 1: chekka ehtimollar (<0.01 yoki >0.99) ulushi 0.3%, o'rtacha 0.510
nusxa 15: chekka ehtimollar (<0.01 yoki >0.99) ulushi 83.7%, o'rtacha 0.519
=== 3. Logistik regressiya bilan solishtirish ===
GaussianNB : aniqlik 0.7258, AUC 0.7997, log-loss 3.0388, Brier 0.2591
LogReg : aniqlik 0.7183, AUC 0.7975, log-loss 0.5462, Brier 0.1837
=== 4. Kalibrlash egri chizig'i ===
NB bashorat 0.0000 → haqiqiy ulush 0.1375
NB bashorat 0.0010 → haqiqiy ulush 0.3250
NB bashorat 0.5959 → haqiqiy ulush 0.5000
NB bashorat 0.9999 → haqiqiy ulush 0.6958
NB bashorat 1.0000 → haqiqiy ulush 0.8417
⭐ Bashorat to'g'ri, ehtimol haddan tashqari ishonchliNima ko'rsatdi: 2.2, 2.6-bo'limlar.
Misol 3 — Uch variant va belgi turi
"""GaussianNB, MultinomialNB, BernoulliNB (real numpy/sklearn)."""
import numpy as np
from sklearn.model_selection import StratifiedKFold, cross_val_score
from sklearn.naive_bayes import BernoulliNB, GaussianNB, MultinomialNB
def main() -> None:
rng = np.random.default_rng(8)
cv = StratifiedKFold(5, shuffle=True, random_state=0)
n = 3000
print("=== 1. Uzluksiz belgilar (normal) ===")
y = rng.integers(0, 2, n)
X_uzluksiz = rng.normal(y[:, None] * 0.9, 1.0, (n, 6))
for nom, m in [("GaussianNB", GaussianNB()),
("MultinomialNB", MultinomialNB()),
("BernoulliNB", BernoulliNB())]:
try:
# MultinomialNB manfiy qiymat qabul qilmaydi — siljitamiz
Xi = X_uzluksiz - X_uzluksiz.min() if nom == "MultinomialNB" else X_uzluksiz
b = cross_val_score(m, Xi, y, cv=cv).mean()
print(f" {nom:<14}: CV aniqlik {b:.4f}")
except ValueError as xato:
print(f" {nom:<14}: xato — {xato}")
print("\n=== 2. Sanoq belgilari (so'z chastotasi) ===")
y2 = rng.integers(0, 2, n)
tezlik = np.where(y2[:, None] == 1,
np.array([3.0, 0.5, 2.0, 0.4, 1.0, 0.3]),
np.array([0.4, 2.5, 0.5, 2.2, 0.8, 1.2]))
X_sanoq = rng.poisson(tezlik)
for nom, m in [("GaussianNB", GaussianNB()),
("MultinomialNB", MultinomialNB()),
("BernoulliNB", BernoulliNB())]:
print(f" {nom:<14}: CV aniqlik "
f"{cross_val_score(m, X_sanoq, y2, cv=cv).mean():.4f}")
print("\n=== 3. Binar belgilar (so'z bor/yo'q) ===")
X_binar = (X_sanoq > 0).astype(int)
for nom, m in [("GaussianNB", GaussianNB()),
("MultinomialNB", MultinomialNB()),
("BernoulliNB", BernoulliNB())]:
print(f" {nom:<14}: CV aniqlik "
f"{cross_val_score(m, X_binar, y2, cv=cv).mean():.4f}")
print("\n=== 4. Qiyshiq belgilar: transformatsiya yordam beradi ===")
y3 = rng.integers(0, 2, n)
X_qiyshiq = rng.lognormal(y3[:, None] * 0.5, 1.0, (n, 5))
print(f" xom (lognormal) : CV aniqlik "
f"{cross_val_score(GaussianNB(), X_qiyshiq, y3, cv=cv).mean():.4f}")
print(f" log olingandan keyin: CV aniqlik "
f"{cross_val_score(GaussianNB(), np.log(X_qiyshiq), y3, cv=cv).mean():.4f}")
print(" ⭐ Variantni belgi turiga moslang, taqsimotni tekshiring")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Uzluksiz belgilar (normal) ===
GaussianNB : CV aniqlik 0.8697
MultinomialNB : CV aniqlik 0.5053
BernoulliNB : CV aniqlik 0.7903
=== 2. Sanoq belgilari (so'z chastotasi) ===
GaussianNB : CV aniqlik 0.9607
MultinomialNB : CV aniqlik 0.9630
BernoulliNB : CV aniqlik 0.9137
=== 3. Binar belgilar (so'z bor/yo'q) ===
GaussianNB : CV aniqlik 0.9107
MultinomialNB : CV aniqlik 0.9133
BernoulliNB : CV aniqlik 0.9137
=== 4. Qiyshiq belgilar: transformatsiya yordam beradi ===
xom (lognormal) : CV aniqlik 0.6057
log olingandan keyin: CV aniqlik 0.7063
⭐ Variantni belgi turiga moslang, taqsimotni tekshiringNima ko'rsatdi: 2.3-bo'lim.
Misol 4 — Matn tasniflash: NB va boshqalar
"""Matn tasniflash: NB, LogReg va chiziqli SVM (real sklearn)."""
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, f1_score
from sklearn.model_selection import GridSearchCV, StratifiedKFold
from sklearn.naive_bayes import ComplementNB, MultinomialNB
from sklearn.pipeline import Pipeline
from sklearn.svm import LinearSVC
LUGAT = {
0: ["kosmos", "raketa", "orbita", "yulduz", "sayyora", "modul", "teleskop"],
1: ["mashina", "dvigatel", "gildirak", "tezlik", "yoqilgi", "salon", "tormoz"],
2: ["siyosat", "hukumat", "saylov", "qonun", "parlament", "vazir", "byudjet"],
3: ["grafika", "piksel", "render", "ekran", "rang", "kadr", "soya"],
}
UMUMIY = ["va", "bu", "uchun", "bilan", "juda", "ham", "lekin", "keyin",
"tizim", "loyiha", "tahlil", "natija", "sinov", "guruh"]
def yarat(n: int, seed: int):
"""Har hujjat: 4 ta mavzu so'zi, 12 ta umumiy, 9 ta CHALKASHTIRUVCHI
(chalkashtiruvchilar tasodifiy mavzulardan — vazifani qiyinlashtiradi).
"""
rng = np.random.default_rng(seed)
matnlar, yorliqlar = [], []
for _ in range(n):
k = int(rng.integers(0, 4))
sozlar = list(rng.choice(LUGAT[k], 4))
sozlar += list(rng.choice(UMUMIY, 12))
for _ in range(9):
boshqa = int(rng.integers(0, 4))
sozlar.append(str(rng.choice(LUGAT[boshqa])))
rng.shuffle(sozlar)
matnlar.append(" ".join(sozlar))
yorliqlar.append(k)
return matnlar, np.array(yorliqlar)
def main() -> None:
tr_matn, ytr = yarat(2400, seed=1)
te_matn, yte = yarat(1200, seed=2)
print("=== 1. Ma'lumot ===")
print(f" o'quv {len(tr_matn)}, test {len(te_matn)}, "
f"{len(np.unique(ytr))} kategoriya")
print(f" namuna hujjat: '{tr_matn[0][:60]}...'")
print("\n=== 2. Modellar ===")
modellar = {
"MultinomialNB": MultinomialNB(alpha=0.1),
"ComplementNB": ComplementNB(alpha=0.1),
"LogReg": LogisticRegression(max_iter=2000, C=5.0),
"LinearSVC": LinearSVC(C=1.0, max_iter=10_000),
}
for nom, m in modellar.items():
quvur = Pipeline([("vec", TfidfVectorizer(min_df=2)), ("m", m)])
quvur.fit(tr_matn, ytr)
pred = quvur.predict(te_matn)
lugat = len(quvur.named_steps["vec"].get_feature_names_out())
print(f" {nom:<14}: aniqlik {accuracy_score(yte, pred):.4f}, "
f"F1 macro {f1_score(yte, pred, average='macro'):.4f}, "
f"lug'at {lugat}")
print("\n=== 3. alpha ni sozlash ===")
quvur = Pipeline([("vec", TfidfVectorizer(min_df=2)), ("m", MultinomialNB())])
qidiruv = GridSearchCV(quvur, {"m__alpha": [0.01, 0.05, 0.1, 0.5, 1.0]},
cv=StratifiedKFold(3, shuffle=True, random_state=0),
scoring="f1_macro").fit(tr_matn, ytr)
print(f" eng yaxshi alpha = {qidiruv.best_params_['m__alpha']}")
print(f" CV F1 macro = {qidiruv.best_score_:.4f}")
print(f" test F1 macro = "
f"{f1_score(yte, qidiruv.predict(te_matn), average='macro'):.4f}")
print("\n=== 4. Har sinf uchun eng ma'noli so'zlar ===")
eng_model = qidiruv.best_estimator_
sozlar = eng_model.named_steps["vec"].get_feature_names_out()
nb = eng_model.named_steps["m"]
for k in range(3):
farq = nb.feature_log_prob_[k] - nb.feature_log_prob_.mean(axis=0)
top = np.argsort(farq)[::-1][:5]
print(f" sinf {k}: {[sozlar[i] for i in top]}")
print(" ⭐ NB — matn uchun eng tez va tushunarli baza")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Ma'lumot ===
o'quv 2400, test 1200, 4 kategoriya
namuna hujjat: 'tormoz tezlik juda sinov bilan loyiha salon tormoz mashina h...'
=== 2. Modellar ===
MultinomialNB : aniqlik 0.9117, F1 macro 0.9116, lug'at 42
ComplementNB : aniqlik 0.9117, F1 macro 0.9115, lug'at 42
LogReg : aniqlik 0.9108, F1 macro 0.9106, lug'at 42
LinearSVC : aniqlik 0.9125, F1 macro 0.9124, lug'at 42
=== 3. alpha ni sozlash ===
eng yaxshi alpha = 0.5
CV F1 macro = 0.9097
test F1 macro = 0.9107
=== 4. Har sinf uchun eng ma'noli so'zlar ===
sinf 0: ['teleskop', 'kosmos', 'orbita', 'modul', 'yulduz']
sinf 1: ['tezlik', 'salon', 'dvigatel', 'yoqilgi', 'tormoz']
sinf 2: ['qonun', 'hukumat', 'parlament', 'byudjet', 'vazir']
⭐ NB — matn uchun eng tez va tushunarli bazaNima ko'rsatdi: 2.5-bo'lim.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
| "Taxmin noto'g'ri — model yaroqsiz" | Bashorat baribir yaxshi |
| "predict_proba — haqiqiy ehtimol" | Kalibrlanmagan |
| "Bitta NB varianti bor" | Belgi turiga qarab uchta |
| "Silliqlash ixtiyoriy" | Majburiy |
| "alpha ni sozlash kerak emas" | CV bilan sezilarli foyda |
| "NB eskirgan" | Matnda hali ham baza |
| "NB har qanday belgi bilan" | Taqsimot muhim |
| "NB sekin" | Eng tez klassifikator |
6. Keng tarqalgan xatolar va yechimlari
1. Noto'g'ri variant
GaussianNB().fit(tfidf_matritsa, y) # ⚠️
MultinomialNB(alpha=0.1).fit(tfidf_matritsa, y) # ✅2. Silliqlashsiz
MultinomialNB(alpha=0.0) # ⚠️
MultinomialNB(alpha=0.1) # ✅3. Ehtimolni qaror formulasiga kiritish
foyda = nb.predict_proba(X)[:, 1] * LTV - narx # ⚠️
CalibratedClassifierCV(nb, method="sigmoid", cv=5) # 14.10 # ✅4. Qiyshiq belgilar bilan GaussianNB
GaussianNB().fit(X_lognormal, y) # ⚠️
GaussianNB().fit(np.log(X_lognormal), y) # ✅5. alpha ni sozlamaslik
MultinomialNB() # alpha = 1.0 # ⚠️
GridSearchCV(pipe, {"m__alpha": [0.01, 0.05, 0.1, 0.5, 1]}, cv=5) # ✅6. Matnda vektorizatorni sozlamaslik
TfidfVectorizer() # ⚠️
TfidfVectorizer(min_df=2, ngram_range=(1, 2)) # ✅7. Vektorizator pipeline'dan tashqarida
X = TfidfVectorizer().fit_transform(hamma_matn) # leakage # ⚠️
Pipeline([("vec", TfidfVectorizer()), ("m", MultinomialNB())]) # ✅7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 9-qism (o'tilgan): Bayes formulasi va ehtimol
- 12.9-dars (o'tilgan): Pipeline va leakage
- 14.1-dars (o'tilgan): Generativ modellar
- 14.10-dars: Kalibrlash
- 14.11-dars: Matn klassifikatsiyasi
8. Eng yaxshi amaliyotlar
Variantni belgi turiga moslang.
alpha ni CV bilan tanlang.
Matnda pipeline ichida vektorlashtiring.
Ehtimolni kalibrlang (kerak bo'lsa).
Qiyshiq belgilarni transformatsiya qiling.
NB ni baza sifatida ishlating.
ComplementNB ni nomutanosib to'plamda sinang.
Eng ma'noli belgilarni ko'ring.
9. Amaliy topshiriq
Vazifa 1: Bashorat qiling
1. # Bayes formulasi?
2. # "naive" taxmin nima?
3. # nega bu taxmin kerak?
4. # nega noto'g'ri taxmin ishlaydi?
5. # uch variant?
6. # matn uchun qaysi biri?
7. # silliqlash nima uchun?
8. # alpha = 0 bo'lsa?
9. # NB ehtimollari qanday?
10. # kalibrlash qanday qilinadi?
11. # NB ning asosiy afzalligi?
12. # ComplementNB qachon?Javoblar
- P(y|x) = P(x|y)P(y)/P(x)
- Belgilar sinf ichida mustaqil
- 2^p o'rniga p parametr
- argmax to'g'ri chiqadi
- Gaussian, Multinomial, Bernoulli
- Multinomial (yoki Bernoulli)
- Ko'rilmagan belgi nolga tushirmasligi uchun
- Bitta yangi so'z bashoratni buzadi
- Haddan tashqari ishonchli
- CalibratedClassifierCV
- Tezlik va soddalik
- Nomutanosib matn to'plamlarida
Vazifa 2: Xatolarni tuzating
1. GaussianNB().fit(tfidf, y)
2. MultinomialNB(alpha=0.0)
3. foyda = nb.predict_proba(X)[:, 1] * 500000
4. GaussianNB().fit(daromad_ustuni, y) # lognormal
5. X = TfidfVectorizer().fit_transform(hammasi); cross_val_score(nb, X, y)Javoblar
1. MultinomialNB(alpha=0.1).fit(tfidf, y)
2. MultinomialNB(alpha=0.1)
3. CalibratedClassifierCV(nb, method="sigmoid", cv=5)
4. GaussianNB().fit(np.log(daromad_ustuni), y)
5. Pipeline([("vec", TfidfVectorizer()), ("m", nb)])Vazifa 3: Qo'lda NB
Modellang:
- Kichik matn to'plami
- Qo'lda hisoblash
- sklearn bilan tekshirish
- Eng ma'noli so'zlar
Vazifa 4: Taxmin buzilishi
Modellang:
- Nusxalangan belgilar
- Aniqlik va ehtimol
- Kalibrlash egri chizig'i
- Xulosa
Vazifa 5: Variantlar
Modellang:
- Uch xil belgi turi
- Uch variant
- Taqqoslash
- Tavsiya
Vazifa 6: Matn
Modellang:
- TF-IDF pipeline
- NB va boshqalar
- alpha sozlash
- Tezlik
Vazifa 7: O'ylash
Naive Bayes ning taxmini deyarli har doim buzilgan bo'lsa ham, u o'nlab yillar davomida amaliyotda qoladi. "Noto'g'ri, lekin foydali" modellar haqida bu bizga nima deydi?
Javob
Qisqa javob: model taxminlarining to'g'riligi bilan emas, qarorning to'g'riligi bilan baholanadi. Naive Bayes — "barcha modellar noto'g'ri, ba'zilari foydali" tamoyilining eng toza namunasi.
1. Nega noto'g'ri taxmin ishlaydi
- Klassifikatsiya uchun
argmaxyetarli, aniq ehtimol emas - Bog'liqlik ko'pincha barcha sinflarga bir xil ta'sir qiladi va tartibni buzmaydi
- Kuchli taxmin = kuchli regularizatsiya: kam ma'lumotda variance kamayadi (12.5)
2. Qayerda buziladi
| Vazifa | NB mosmi |
|---|---|
| Yorliq bashorat | Ha |
| Reyting (AUC) | Odatda ha |
| Ehtimol (narx formulasi) | Yo'q — kalibrlash kerak |
| Koeffitsiyent talqini | Ehtiyot bilan |
3. Umumiy saboq
- Taxminlarni tekshirish kerak, lekin maqsad kontekstida (13.4 bilan bir xil mantiq)
- Soddalashtirish — kamchilik emas, almashinuv: bias ↑, variance ↓
- Modelni baholash mezoni — CV va biznes metrikasi, taxminlar ro'yxati emas
4. Amaliy tavsiya
- NB ni baza sifatida ishlating (ayniqsa matnda)
- Ehtimol kerak bo'lsa kalibrlang
- Murakkab model NB ni sezilarli yengmasa — NB ni qoldiring
- Taxmin buzilishini natija orqali o'lchang
5. Xulosa
- Barcha modellar noto'g'ri
- Foydalilik — qarorda
- Sodda taxmin — regularizatsiya shakli
- Baholash mezonini aralashtirmang
Nimani mustahkamlaydi: 2.2, 2.6-bo'limlar.
Xulosa
Bu darsda Naive Bayes ni o'rgandik.
Eng muhim uch fikr:
Bayes + mustaqillik taxmini.
argmax_k P(y=k) · prod_j P(x_j | y=k)— ko'p o'lchovli taqsimot o'rnigapta bir o'lchovli taqsimot yetarli bo'ladi. Amalda ehtimollar logarifmda yig'iladi. Taxmin deyarli har doim buzilgan, lekin argmax to'g'ri chiqadi.Bashorat to'g'ri, ehtimol kalibrlanmagan. Bog'liq belgilar "dalilni bir necha marta sanaydi", shuning uchun NB ehtimollari 0 yoki 1 ga siljiydi: aniqlik va AUC yaxshi qoladi, log-loss va Brier yomonlashadi. Ehtimol kerak bo'lsa —
CalibratedClassifierCV14.10-bob.Variant belgi turidan kelib chiqadi. GaussianNB (uzluksiz, taqsimot normal bo'lsa yoki log bilan tuzatilsa), MultinomialNB (sanoq/TF-IDF — matn uchun standart), BernoulliNB (binar). Silliqlash (
alpha) majburiy va CV bilan tanlanadi. NB — eng tez klassifikator: matn vazifalarida u har doim birinchi baza bo'lishga arziydi.
Keyingi darsda LDA va QDAni o'rganamiz: normal taqsimotga asoslangan generativ modellar, chiziqli va kvadratik chegaralar, o'lchamni kamaytirish uchun LDA.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!