Mundarija (22)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Cheklovsiz daraxt
- 2.2. Pre-pruning giperparametrlari
- 2.3. Cost-complexity pruning
- 2.4. O'quv egri chizig'i
- 2.5. max_features
- 2.6. Giperparametr tanlash
- 2.7. Tuzoqlar
- 2.8. Qachon to'xtash — asosiy savol
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — Cheklovsiz daraxt va chuqurlik
- Misol 2 — min_samples_leaf va boshqa cheklovlar
- Misol 3 — Cost-complexity pruning
- Misol 4 — To'liq sozlash va shovqin darajasi
- 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
15.2-dars: O'sish va to'xtash shartlari
15-QISM — DARAXTLAR VA ANSAMBLLAR · 2-dars
1. Kirish va motivatsiya
Cheklovsiz daraxt har doim o'quv ma'lumotini 100% yodlaydi: u har bir namunani alohida bargga joylashtirguncha bo'linaveradi. Bu — overfitting ning eng toza ko'rinishi 12.4-bob. Shuning uchun daraxt bilan ishlashning asosiy qismi — uni qachon to'xtatishni hal qilish.
To'xtatishning ikki yo'li bor: oldindan (pre-pruning — max_depth, min_samples_leaf) va keyin (post-pruning — daraxtni to'liq o'stirib, keyin keraksiz shoxlarni kesish). Ikkinchisi nazariy jihatdan yaxshiroq, birinchisi amalda ko'proq ishlatiladi.
Bu darsda: max_depth, min_samples_split, min_samples_leaf, max_leaf_nodes, min_impurity_decrease, max_features, cost-complexity pruning (ccp_alpha), o'quv egri chizig'i va giperparametr tanlash.
Real vaziyat. Talabalarning o'qishni tashlash ehtimolini bashorat qiluvchi daraxt o'quvda 100% aniqlik berdi va universitet rahbariyati uni joriy qilishga qaror qildi. Test to'plamida esa aniqlik 0.61 chiqdi — tasodifiydan biroz yaxshiroq. max_depth=5 va min_samples_leaf=30 qo'yilgach, o'quv 0.79 ga tushdi, lekin test 0.77 ga ko'tarildi. O'quv aniqligining tushishi — yaxshilanish edi.
Bu darsda daraxt o'sishini nazorat qilishni o'rganamiz.
Bu darsda:
- Cheklovsiz daraxt va overfitting
- Pre-pruning giperparametrlari
- Cost-complexity pruning
- O'quv egri chizig'i
- max_features
- Giperparametr tanlash
- Tuzoqlar
- Amaliy: sozlash
ℹ Misollar real numpy/pandas/sklearn bilan (Python 3.14).
2. Nazariya — chuqur tushuntirish
2.1. Cheklovsiz daraxt
DecisionTreeClassifier() — standart: HECH QANDAY chekov yo'q
max_depth=None, min_samples_split=2, min_samples_leaf=1
Natija: har barg TOZA bo'lguncha bo'linadi
o'quv aniqligi = 1.0000 (takrorlanmaydigan namunalar bo'lsa)
barglar soni ~ namunalar soni tartibida
test aniqligi: shovqinli ma'lumotda keskin past DecisionTreeClassifier() ni standart parametrlar bilan ishlatish — eng keng tarqalgan xato. O'quv aniqligi 1.0000 chiqishi modelning yaxshiligini emas, cheklov yo'qligini bildiradi.
2.2. Pre-pruning giperparametrlari
max_depth — eng ko'p qo'llaniladigan; 3-10 odatiy
min_samples_split — tugunni bo'lish uchun kerakli minimal namuna (>= 2)
min_samples_leaf — bargdagi minimal namuna (eng ISHONCHLI chekov)
max_leaf_nodes — barglarning umumiy soni (chuqurlikdan moslashuvchan)
min_impurity_decrease — kamayish shu qiymatdan kichik bo'lsa bo'linmaydi
max_features — har bo'linishda ko'riladigan belgilar soni
class_weight — nomutanosib sinflar uchun 14.9-bob
min_samples_leaf: float bersangiz — ULUSH (0.01 = 1%) min_samples_leaf — eng ishonchli chekov: u har bargda yetarlicha namuna bo'lishini kafolatlaydi, ya'ni barg bashorati statistik ma'noga ega bo'ladi. max_depth esa faqat yo'l uzunligini cheklaydi — chuqurlik kichik bo'lsa ham bitta bargda 2 ta namuna qolishi mumkin.
2.3. Cost-complexity pruning
Daraxtni TO'LIQ o'stirib, keyin kesish (post-pruning)
R_alpha(T) = R(T) + alpha * |barglar(T)|
R(T) — daraxt xatosi (nopoklik)
alpha — murakkablik jarimasi
alpha oshgan sari: kichikroq daraxt
alpha = 0 — to'liq daraxt
alpha -> katta — faqat ildiz
sklearn:
yol = d.cost_complexity_pruning_path(X, y) # ccp_alphas, impurities
DecisionTreeClassifier(ccp_alpha=tanlangan) cost_complexity_pruning_path mumkin bo'lgan barcha alpha larni beradi — ular orasidan CV bilan tanlanadi. Bu pre-pruning dan ustun tomoni: kesish ma'lumotga qarab amalga oshiriladi, oldindan taxmin qilingan chuqurlikka emas.
2.4. O'quv egri chizig'i
Chuqurlik oshgan sari:
o'quv aniqligi — monoton O'SADI (1.0 gacha)
CV aniqligi — oshadi, MAKSIMUMGA yetadi, keyin tushadi
farq (gap) — monoton oshadi
Eng yaxshi chuqurlik = CV maksimumi (yoki 1-SE qoidasi bo'yicha soddaroq)
Ko'p ma'lumot -> chuqurroq daraxt afzal
Ko'p shovqin -> sayozroq daraxt afzalO'quv aniqligiga qarab qaror qabul qilmang — u har doim chuqurlik bilan o'sadi va hech qachon overfitting ni ko'rsatmaydi. Faqat CV yoki alohida validatsiya to'plami 12.3-bob haqiqatni aytadi.
2.5. max_features
max_features — har bo'linishda TASODIFIY tanlangan belgilar soni
None (standart) — barcha belgilar
"sqrt" — sqrt(p) ta
"log2" — log2(p) ta
int / float — aniq son / ulush
Bitta daraxtda: odatda None (kerak emas)
Random Forest da: MAJBURIY 15.5-bob — daraxtlarni bir-biridan farqlantiradi max_features bitta daraxt uchun deyarli foydasiz, lekin ansambl uchun hal qiluvchi: aynan u daraxtlarni korrelyatsiyasiz qiladi va shu orqali ansambl dispersiyasini kamaytiradi 15.4-bob.
2.6. Giperparametr tanlash
setka = {"max_depth": [3, 5, 8, 12, None],
"min_samples_leaf": [1, 5, 20, 50],
"criterion": ["gini"]} # criterion ni sozlamang
q = GridSearchCV(DecisionTreeClassifier(random_state=0), setka,
cv=StratifiedKFold(5, shuffle=True, random_state=0),
scoring="roc_auc").fit(X, y) scoring ni vazifaga mos tanlang 12.7-bob: nomutanosib sinflarda accuracy emas, roc_auc yoki average_precision. Aks holda grid "hammani ko'pchilik sinfga tegishli" deb aytadigan daraxtni tanlashi mumkin.
2.7. Tuzoqlar
Asosiy tuzoqlar: standart parametrlar bilan qoldirish; o'quv aniqligiga qarab baholash; faqat max_depth ni sozlab, min_samples_leaf ni unutish; ccp_alpha ni CV siz tanlash; nomutanosib sinflarda accuracy bo'yicha sozlash; juda kichik min_samples_leaf (1-2) ni "aniqroq" deb hisoblash; sozlashni test to'plamida qilish (12.9 — leakage); bitta daraxtni uzoq sozlash (ansambl osonroq yaxshi natija beradi).
2.8. Qachon to'xtash — asosiy savol
Cheklovsiz daraxt o'quvni yodlaydi (aniqlik 1.0000) va testda yomon ishlaydi. Yechim — pre-pruning (max_depth, ayniqsa min_samples_leaf) yoki post-pruning (ccp_alpha, cost_complexity_pruning_path bilan). Tanlov CV orqali qilinadi, o'quv aniqligi bo'yicha emas. max_features bitta daraxtga kam foyda beradi, lekin ansambl uchun majburiy. Keyingi dars — daraxt beqarorligi.
3. Tez ma'lumotnoma
from sklearn.model_selection import GridSearchCV, StratifiedKFold, validation_curve
from sklearn.tree import DecisionTreeClassifier
DecisionTreeClassifier(max_depth=5, min_samples_leaf=20, max_leaf_nodes=None,
min_impurity_decrease=0.0, ccp_alpha=0.0,
class_weight=None, random_state=0)
# post-pruning
yol = DecisionTreeClassifier(random_state=0).cost_complexity_pruning_path(X, y)
alphalar = yol.ccp_alphas
# o'quv egri chizig'i
oquv, cvb = validation_curve(DecisionTreeClassifier(random_state=0), X, y,
param_name="max_depth",
param_range=[2, 4, 6, 8, 12], cv=5)
QOIDA: min_samples_leaf eng ishonchli · CV bo'yicha tanla ·
o'quv aniqligiga ishonmaTo'xtash xulosasi
Cheklovsiz daraxt o'quvni yodlaydi 1.0000-bob
Pre-pruning: max_depth, min_samples_leaf (eng ishonchli), max_leaf_nodes
Post-pruning: ccp_alpha (cost_complexity_pruning_path + CV)
Tanlov faqat CV bo'yicha; max_features ansambl uchun4. Batafsil misollar
Misollar real numpy/pandas/sklearn bilan (Python 3.14).
Misol 1 — Cheklovsiz daraxt va chuqurlik
"""Overfitting ni ko'rish va chuqurlik bilan nazorat qilish (real numpy/sklearn)."""
import numpy as np
from sklearn.model_selection import StratifiedKFold, cross_val_score, train_test_split
from sklearn.tree import DecisionTreeClassifier
def yarat(seed: int = 4, n: int = 2000, shovqin: float = 0.12):
"""Qoidaga asoslangan ma'lumot: daraxt uchun tabiiy vazifa."""
rng = np.random.default_rng(seed)
X = rng.normal(0, 1, (n, 8))
qoida = (((X[:, 0] > 0.4) & (X[:, 1] < 0.0))
| ((X[:, 2] > 0.0) & (X[:, 3] > 0.5))
| (X[:, 4] < -1.2))
y = qoida.astype(int)
alm = rng.random(n) < shovqin # atayin buzilgan yorliqlar
y[alm] = 1 - y[alm]
return X, y
def main() -> None:
X, y = yarat()
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.3, random_state=0,
stratify=y)
cv = StratifiedKFold(5, shuffle=True, random_state=0)
print("=== 1. Cheklovsiz daraxt ===")
d = DecisionTreeClassifier(random_state=0).fit(Xtr, ytr)
print(f" chuqurlik {d.get_depth()}, barglar {d.get_n_leaves()}")
print(f" o'quv aniqligi {d.score(Xtr, ytr):.4f}")
print(f" test aniqligi {d.score(Xte, yte):.4f}")
print(f" farq {d.score(Xtr, ytr) - d.score(Xte, yte):.4f}")
print("\n=== 2. Chuqurlik bo'yicha o'quv egri chizig'i ===")
print(f" {'depth':>6} {'barglar':>9} {'o_quv':>8} {'CV':>8} {'test':>8} "
f"{'farq':>8}")
eng_cv, eng_d = -1.0, None
for chuqurlik in [2, 3, 4, 5, 6, 8, 12, 20, None]:
m = DecisionTreeClassifier(max_depth=chuqurlik, random_state=0).fit(Xtr, ytr)
oquv = m.score(Xtr, ytr)
cvb = cross_val_score(DecisionTreeClassifier(max_depth=chuqurlik,
random_state=0),
Xtr, ytr, cv=cv).mean()
test = m.score(Xte, yte)
if cvb > eng_cv:
eng_cv, eng_d = cvb, chuqurlik
nom = "None" if chuqurlik is None else str(chuqurlik)
print(f" {nom:>6} {m.get_n_leaves():>9} {oquv:>8.4f} {cvb:>8.4f} "
f"{test:>8.4f} {oquv - cvb:>8.4f}")
print(f" eng yaxshi CV: max_depth={eng_d} ({eng_cv:.4f})")
print("\n=== 3. Bayes chegarasi ===")
print(f" yorliqlarning 12% i buzilgan -> nazariy maksimum 0.8800")
print(f" cheklovsiz daraxt: {d.score(Xte, yte):.4f}")
m = DecisionTreeClassifier(max_depth=eng_d, random_state=0).fit(Xtr, ytr)
print(f" sozlangan daraxt: {m.score(Xte, yte):.4f}")
print("\n=== 4. Ma'lumot hajmi ta'siri ===")
print(f" {'n':>6} {'eng yaxshi depth':>18} {'CV':>8}")
for n in [200, 500, 2000, 8000]:
Xn, yn = yarat(n=n)
eng, edepth = -1.0, None
for chuqurlik in [2, 3, 4, 6, 8, 12]:
b = cross_val_score(DecisionTreeClassifier(max_depth=chuqurlik,
random_state=0),
Xn, yn, cv=cv).mean()
if b > eng:
eng, edepth = b, chuqurlik
print(f" {n:>6} {edepth:>18} {eng:>8.4f}")
print(" ⭐ Ko'proq ma'lumot -> chuqurroq daraxt")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Cheklovsiz daraxt ===
chuqurlik 16, barglar 193
o'quv aniqligi 1.0000
test aniqligi 0.7500
farq 0.2500
=== 2. Chuqurlik bo'yicha o'quv egri chizig'i ===
depth barglar o_quv CV test farq
2 4 0.7264 0.7193 0.6900 0.0071
3 7 0.7929 0.7786 0.7667 0.0143
4 12 0.8657 0.8443 0.8333 0.0214
5 22 0.8921 0.8450 0.8433 0.0471
6 40 0.9086 0.8371 0.8367 0.0714
8 94 0.9450 0.8100 0.8133 0.1350
12 168 0.9843 0.7743 0.7767 0.2100
20 193 1.0000 0.7650 0.7500 0.2350
None 193 1.0000 0.7650 0.7500 0.2350
eng yaxshi CV: max_depth=5 0.8450-bob
=== 3. Bayes chegarasi ===
yorliqlarning 12% i buzilgan -> nazariy maksimum 0.8800
cheklovsiz daraxt: 0.7500
sozlangan daraxt: 0.8433
=== 4. Ma'lumot hajmi ta'siri ===
n eng yaxshi depth CV
200 3 0.7500
500 4 0.8080
2000 6 0.8585
8000 6 0.8716
⭐ Ko'proq ma'lumot -> chuqurroq daraxtNima ko'rsatdi: 2.1, 2.4-bo'limlar.
Misol 2 — min_samples_leaf va boshqa cheklovlar
"""Qaysi chekov eng ishonchli (real numpy/sklearn)."""
import numpy as np
from sklearn.model_selection import StratifiedKFold, cross_val_score, train_test_split
from sklearn.tree import DecisionTreeClassifier
def yarat(seed: int = 11, n: int = 2500, shovqin: float = 0.15):
"""Qoidaga asoslangan ma'lumot: daraxt uchun tabiiy vazifa."""
rng = np.random.default_rng(seed)
X = rng.normal(0, 1, (n, 8))
qoida = (((X[:, 0] > 0.4) & (X[:, 1] < 0.0))
| ((X[:, 2] > 0.0) & (X[:, 3] > 0.5))
| (X[:, 4] < -1.2))
y = qoida.astype(int)
alm = rng.random(n) < shovqin # atayin buzilgan yorliqlar
y[alm] = 1 - y[alm]
return X, y
def main() -> None:
X, y = yarat()
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.3, random_state=0,
stratify=y)
cv = StratifiedKFold(5, shuffle=True, random_state=0)
def baho(**parametrlar):
m = DecisionTreeClassifier(random_state=0, **parametrlar)
cvb = cross_val_score(m, Xtr, ytr, cv=cv).mean()
m.fit(Xtr, ytr)
return m.get_n_leaves(), m.score(Xtr, ytr), cvb, m.score(Xte, yte)
print("=== 1. min_samples_leaf ===")
print(f" {'qiymat':>8} {'barglar':>9} {'o_quv':>8} {'CV':>8} {'test':>8}")
for v in [1, 5, 10, 25, 50, 100, 200]:
barg, oquv, cvb, test = baho(min_samples_leaf=v)
print(f" {v:>8} {barg:>9} {oquv:>8.4f} {cvb:>8.4f} {test:>8.4f}")
print("\n=== 2. max_leaf_nodes ===")
print(f" {'qiymat':>8} {'barglar':>9} {'o_quv':>8} {'CV':>8} {'test':>8}")
for v in [4, 8, 16, 32, 64, 256]:
barg, oquv, cvb, test = baho(max_leaf_nodes=v)
print(f" {v:>8} {barg:>9} {oquv:>8.4f} {cvb:>8.4f} {test:>8.4f}")
print("\n=== 3. min_impurity_decrease ===")
print(f" {'qiymat':>8} {'barglar':>9} {'o_quv':>8} {'CV':>8} {'test':>8}")
for v in [0.0, 0.0005, 0.001, 0.005, 0.01]:
barg, oquv, cvb, test = baho(min_impurity_decrease=v)
print(f" {v:>8} {barg:>9} {oquv:>8.4f} {cvb:>8.4f} {test:>8.4f}")
print("\n=== 4. max_depth yetarlimi ===")
print(" (max_depth=6, lekin min_samples_leaf turlicha)")
print(f" {'msl':>8} {'barglar':>9} {'eng kichik barg':>17} {'CV':>8}")
for v in [1, 5, 20, 50]:
m = DecisionTreeClassifier(max_depth=6, min_samples_leaf=v,
random_state=0).fit(Xtr, ytr)
barglar = m.tree_.n_node_samples[m.tree_.feature < 0]
cvb = cross_val_score(DecisionTreeClassifier(max_depth=6,
min_samples_leaf=v,
random_state=0),
Xtr, ytr, cv=cv).mean()
print(f" {v:>8} {m.get_n_leaves():>9} {int(barglar.min()):>17} "
f"{cvb:>8.4f}")
print(" ⭐ max_depth bargdagi namuna sonini KAFOLATLAMAYDI")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. min_samples_leaf ===
qiymat barglar o_quv CV test
1 281 1.0000 0.7240 0.7333
5 160 0.8977 0.7211 0.7600
10 107 0.8571 0.7686 0.8040
25 50 0.8400 0.8274 0.8813
50 27 0.8291 0.8257 0.8640
100 14 0.8234 0.8206 0.8560
200 7 0.7554 0.7160 0.7680
=== 2. max_leaf_nodes ===
qiymat barglar o_quv CV test
4 4 0.7166 0.7360 0.7013
8 8 0.8400 0.8349 0.8813
16 16 0.8514 0.8189 0.8600
32 32 0.8680 0.8166 0.8587
64 64 0.8926 0.7863 0.8387
256 256 0.9926 0.7251 0.7480
=== 3. min_impurity_decrease ===
qiymat barglar o_quv CV test
0.0 281 1.0000 0.7240 0.7333
0.0005 158 0.9514 0.7337 0.7920
0.001 40 0.8749 0.7777 0.8560
0.005 8 0.8400 0.8349 0.8813
0.01 6 0.8217 0.8240 0.8573
=== 4. max_depth yetarlimi ===
(max_depth=6, lekin min_samples_leaf turlicha)
msl barglar eng kichik barg CV
1 41 1 0.8120
5 42 5 0.7971
20 33 20 0.8349
50 21 50 0.8257
⭐ max_depth bargdagi namuna sonini KAFOLATLAMAYDINima ko'rsatdi: 2.2-bo'lim.
Misol 3 — Cost-complexity pruning
"""To'liq o'stirib, keyin kesish (real numpy/sklearn)."""
import numpy as np
from sklearn.model_selection import StratifiedKFold, cross_val_score, train_test_split
from sklearn.tree import DecisionTreeClassifier
def yarat(seed: int = 21, n: int = 2000, shovqin: float = 0.14):
"""Qoidaga asoslangan ma'lumot: daraxt uchun tabiiy vazifa."""
rng = np.random.default_rng(seed)
X = rng.normal(0, 1, (n, 8))
qoida = (((X[:, 0] > 0.4) & (X[:, 1] < 0.0))
| ((X[:, 2] > 0.0) & (X[:, 3] > 0.5))
| (X[:, 4] < -1.2))
y = qoida.astype(int)
alm = rng.random(n) < shovqin # atayin buzilgan yorliqlar
y[alm] = 1 - y[alm]
return X, y
def main() -> None:
X, y = yarat()
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.3, random_state=0,
stratify=y)
cv = StratifiedKFold(5, shuffle=True, random_state=0)
print("=== 1. Pruning yo'li ===")
yol = DecisionTreeClassifier(random_state=0).cost_complexity_pruning_path(Xtr, ytr)
alphalar = yol.ccp_alphas[:-1] # oxirgisi = faqat ildiz
print(f" mumkin bo'lgan alpha lar soni: {len(alphalar)}")
print(f" eng kichik {alphalar.min():.6f}, eng katta {alphalar.max():.6f}")
print("\n=== 2. Tanlangan alpha lar bo'yicha ===")
namunalar = np.unique(np.round(np.geomspace(max(alphalar.min(), 1e-5),
alphalar.max(), 8), 6))
print(f" {'alpha':>10} {'barglar':>9} {'o_quv':>8} {'CV':>8} {'test':>8}")
eng_cv, eng_a = -1.0, 0.0
for a in namunalar:
m = DecisionTreeClassifier(ccp_alpha=a, random_state=0).fit(Xtr, ytr)
cvb = cross_val_score(DecisionTreeClassifier(ccp_alpha=a, random_state=0),
Xtr, ytr, cv=cv).mean()
if cvb > eng_cv:
eng_cv, eng_a = cvb, a
print(f" {a:>10.6f} {m.get_n_leaves():>9} {m.score(Xtr, ytr):>8.4f} "
f"{cvb:>8.4f} {m.score(Xte, yte):>8.4f}")
print(f" eng yaxshi alpha: {eng_a:.6f} (CV {eng_cv:.4f})")
print("\n=== 3. Post-pruning va pre-pruning solishtiruvi ===")
variantlar = {
"cheklovsiz": {},
"max_depth=4": {"max_depth": 4},
"min_samples_leaf=50": {"min_samples_leaf": 50},
"ccp_alpha (tanlangan)": {"ccp_alpha": float(eng_a)},
}
print(f" {'variant':<24} {'barglar':>9} {'CV':>8} {'test':>8}")
for nom, p in variantlar.items():
m = DecisionTreeClassifier(random_state=0, **p).fit(Xtr, ytr)
cvb = cross_val_score(DecisionTreeClassifier(random_state=0, **p),
Xtr, ytr, cv=cv).mean()
print(f" {nom:<24} {m.get_n_leaves():>9} {cvb:>8.4f} "
f"{m.score(Xte, yte):>8.4f}")
print("\n=== 4. Alpha va daraxt hajmi bog'liqligi ===")
for a in [0.0, 0.0002, 0.001, 0.005, 0.02, 0.1]:
m = DecisionTreeClassifier(ccp_alpha=a, random_state=0).fit(Xtr, ytr)
print(f" alpha {a:>7.4f}: {m.get_n_leaves():>4} barg, "
f"chuqurlik {m.get_depth():>2}")
print(" ⭐ alpha oshgan sari daraxt kichrayadi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Pruning yo'li ===
mumkin bo'lgan alpha lar soni: 79
eng kichik 0.000000, eng katta 0.045333
=== 2. Tanlangan alpha lar bo'yicha ===
alpha barglar o_quv CV test
0.000010 211 1.0000 0.7514 0.7233
0.000033 211 1.0000 0.7514 0.7233
0.000111 211 1.0000 0.7514 0.7233
0.000369 211 1.0000 0.7514 0.7233
0.001229 85 0.9357 0.7729 0.7850
0.004090 9 0.8729 0.8564 0.8550
0.013617 6 0.8543 0.8479 0.8450
0.045333 2 0.6750 0.7314 0.6883
eng yaxshi alpha: 0.004090 (CV 0.8564)
=== 3. Post-pruning va pre-pruning solishtiruvi ===
variant barglar CV test
cheklovsiz 211 0.7514 0.7233
max_depth=4 13 0.8414 0.8333
min_samples_leaf=50 23 0.8479 0.8450
ccp_alpha (tanlangan) 9 0.8564 0.8550
=== 4. Alpha va daraxt hajmi bog'liqligi ===
alpha 0.0000: 211 barg, chuqurlik 18
alpha 0.0002: 211 barg, chuqurlik 18
alpha 0.0010: 131 barg, chuqurlik 16
alpha 0.0050: 8 barg, chuqurlik 5
alpha 0.0200: 6 barg, chuqurlik 4
alpha 0.1000: 1 barg, chuqurlik 0
⭐ alpha oshgan sari daraxt kichrayadiNima ko'rsatdi: 2.3-bo'lim.
Misol 4 — To'liq sozlash va shovqin darajasi
"""GridSearchCV va shovqinning optimal murakkablikka ta'siri (real numpy/sklearn)."""
import numpy as np
from sklearn.metrics import roc_auc_score
from sklearn.model_selection import GridSearchCV, StratifiedKFold, train_test_split
from sklearn.tree import DecisionTreeClassifier
def yarat(seed: int, n: int, shovqin: float):
"""Qoidaga asoslangan ma'lumot: daraxt uchun tabiiy vazifa."""
rng = np.random.default_rng(seed)
X = rng.normal(0, 1, (n, 8))
qoida = (((X[:, 0] > 0.4) & (X[:, 1] < 0.0))
| ((X[:, 2] > 0.0) & (X[:, 3] > 0.5))
| (X[:, 4] < -1.2))
y = qoida.astype(int)
alm = rng.random(n) < shovqin # atayin buzilgan yorliqlar
y[alm] = 1 - y[alm]
return X, y
def main() -> None:
cv = StratifiedKFold(5, shuffle=True, random_state=0)
X, y = yarat(6, 3000, 0.12)
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.3, random_state=0,
stratify=y)
print("=== 1. GridSearchCV ===")
setka = {"max_depth": [3, 4, 6, 8, 12, None],
"min_samples_leaf": [1, 10, 30, 80]}
q = GridSearchCV(DecisionTreeClassifier(random_state=0), setka, cv=cv,
scoring="roc_auc", n_jobs=1).fit(Xtr, ytr)
print(f" konfiguratsiyalar: {len(q.cv_results_['params'])}")
print(f" eng yaxshi: {q.best_params_}")
print(f" CV ROC AUC: {q.best_score_:.4f}")
print(f" test ROC AUC: "
f"{roc_auc_score(yte, q.predict_proba(Xte)[:, 1]):.4f}")
print("\n=== 2. Eng yaxshi 5 konfiguratsiya ===")
tartib = np.argsort(-q.cv_results_["mean_test_score"])[:5]
print(f" {'max_depth':>10} {'msl':>6} {'CV AUC':>9} {'std':>8}")
for i in tartib:
p = q.cv_results_["params"][i]
nom = "None" if p["max_depth"] is None else str(p["max_depth"])
print(f" {nom:>10} {p['min_samples_leaf']:>6} "
f"{q.cv_results_['mean_test_score'][i]:>9.4f} "
f"{q.cv_results_['std_test_score'][i]:>8.4f}")
print("\n=== 3. Shovqin darajasi va optimal murakkablik ===")
print(f" {'shovqin':>8} {'eng yaxshi depth':>18} {'msl':>6} {'CV AUC':>9}")
for shovqin in [0.0, 0.05, 0.15, 0.30]:
Xn, yn = yarat(6, 3000, shovqin)
qn = GridSearchCV(DecisionTreeClassifier(random_state=0), setka, cv=cv,
scoring="roc_auc").fit(Xn, yn)
nom = ("None" if qn.best_params_["max_depth"] is None
else str(qn.best_params_["max_depth"]))
print(f" {shovqin:>8.2f} {nom:>18} "
f"{qn.best_params_['min_samples_leaf']:>6} {qn.best_score_:>9.4f}")
print("\n=== 4. Sozlangan daraxt va ansambl ===")
from sklearn.ensemble import RandomForestClassifier
orm = RandomForestClassifier(n_estimators=300, random_state=0,
n_jobs=1).fit(Xtr, ytr)
print(f" sozlangan daraxt: test AUC "
f"{roc_auc_score(yte, q.predict_proba(Xte)[:, 1]):.4f}")
print(f" RandomForest (sozlanmagan): test AUC "
f"{roc_auc_score(yte, orm.predict_proba(Xte)[:, 1]):.4f}")
print(" ⭐ Sozlanmagan ansambl sozlangan daraxtdan kuchli 15.5-bob")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. GridSearchCV ===
konfiguratsiyalar: 24
eng yaxshi: {'max_depth': 8, 'min_samples_leaf': 80}
CV ROC AUC: 0.8708
test ROC AUC: 0.8844
=== 2. Eng yaxshi 5 konfiguratsiya ===
max_depth msl CV AUC std
8 80 0.8708 0.0180
12 80 0.8708 0.0180
None 80 0.8708 0.0180
None 10 0.8699 0.0144
12 10 0.8698 0.0119
=== 3. Shovqin darajasi va optimal murakkablik ===
shovqin eng yaxshi depth msl CV AUC
0.00 6 10 0.9981
0.05 8 10 0.9458
0.15 8 30 0.8362
0.30 4 80 0.6979
=== 4. Sozlangan daraxt va ansambl ===
sozlangan daraxt: test AUC 0.8844
RandomForest (sozlanmagan): test AUC 0.8877
⭐ Sozlanmagan ansambl sozlangan daraxtdan kuchli (15.5)Nima ko'rsatdi: 2.4, 2.6-bo'limlar.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
| "O'quv aniqligi 1.0 — yaxshi model" | Cheklov yo'qligi belgisi |
| "max_depth yetarli" | min_samples_leaf ishonchliroq |
| "min_samples_leaf=1 aniqroq" | Yodlash |
| "ccp_alpha ni ko'zdan tanlash mumkin" | CV kerak |
| "Chuqurroq daraxt har doim yomon" | Ko'p ma'lumotda yaxshi |
| "Shovqin murakkablikka ta'sir qilmaydi" | Shovqin -> sayozroq |
| "Pre va post-pruning bir xil" | Har xil mexanizm |
| "Daraxtni uzoq sozlash kerak" | Ansambl osonroq |
6. Keng tarqalgan xatolar va yechimlari
1. Standart parametrlar
DecisionTreeClassifier().fit(X, y) # ⚠️
DecisionTreeClassifier(max_depth=6, min_samples_leaf=20, random_state=0) # ✅2. O'quv aniqligi bo'yicha baholash
print(d.score(Xtr, ytr)) # ⚠️
print(cross_val_score(d, Xtr, ytr, cv=5).mean()) # ✅3. min_samples_leaf ni unutish
DecisionTreeClassifier(max_depth=10) # bargda 1 namuna bo'lishi mumkin # ⚠️
DecisionTreeClassifier(max_depth=10, min_samples_leaf=20) # ✅4. ccp_alpha ni CV siz tanlash
DecisionTreeClassifier(ccp_alpha=0.01) # qayerdan olindi? # ⚠️
# cost_complexity_pruning_path + GridSearchCV # ✅5. Testda sozlash
for d in [3, 5, 8]: ... m.score(Xte, yte) # test bilan tanlash # ⚠️
GridSearchCV(..., cv=5).fit(Xtr, ytr) # test faqat oxirida # ✅6. Nomutanosib sinflarda accuracy
GridSearchCV(..., scoring="accuracy") # 95% sinf bo'lsa # ⚠️
GridSearchCV(..., scoring="average_precision") # ✅7. Bitta daraxtni haddan uzoq sozlash
# 500 konfiguratsiyali grid, bitta daraxt uchun # ⚠️
RandomForestClassifier(n_estimators=300) # sozlanmasdan kuchliroq # ✅7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 12.4-dars (o'tilgan): Overfitting
- 12.3-dars (o'tilgan): Validatsiya
- 15.3-dars: Daraxt beqarorligi
- 15.5-dars: Random Forest giperparametrlari
- 15.9-dars: Boosting sozlash
8. Eng yaxshi amaliyotlar
min_samples_leaf ni albatta qo'ying.
max_depth bilan birga ishlating.
CV bo'yicha tanlang.
scoring ni vazifaga moslang.
ccp_alpha ni yo'l orqali toping.
Shovqinni hisobga oling.
Testni oxirida ishlating.
Ansamblga vaqtida o'ting.
9. Amaliy topshiriq
Vazifa 1: Bashorat qiling
1. # cheklovsiz daraxtning o'quv aniqligi?
2. # eng ishonchli chekov?
3. # max_depth nimani kafolatlamaydi?
4. # min_samples_leaf float bersa?
5. # ccp_alpha nima qiladi?
6. # alpha oshsa daraxt qanday bo'ladi?
7. # o'quv egri chizig'ida CV qanday harakat qiladi?
8. # shovqin ko'p bo'lsa chuqurlik?
9. # ko'p ma'lumot bo'lsa chuqurlik?
10. # max_features qayerda muhim?
11. # sozlash qaysi to'plamda?
12. # nomutanosib sinflarda scoring?Javoblar
- 1.0000
- min_samples_leaf
- Bargdagi namunalar sonini
- Ulush sifatida
- Post-pruning jarimasi
- Kichrayadi
- Oshadi, maksimum, tushadi
- Sayozroq
- Chuqurroq
- Random Forest (ansambl)
- O'quv (CV bilan)
- roc_auc / average_precision
Vazifa 2: Xatolarni tuzating
1. DecisionTreeClassifier().fit(X, y)
2. print("aniqlik:", d.score(Xtr, ytr))
3. DecisionTreeClassifier(max_depth=15)
4. DecisionTreeClassifier(ccp_alpha=0.01) # taxminan
5. for d in [3, 5, 8]: m.fit(Xtr, ytr); print(m.score(Xte, yte))Javoblar
1. DecisionTreeClassifier(max_depth=6, min_samples_leaf=20, random_state=0)
2. print(cross_val_score(d, Xtr, ytr, cv=5).mean())
3. DecisionTreeClassifier(max_depth=15, min_samples_leaf=20)
4. # cost_complexity_pruning_path + GridSearchCV
5. GridSearchCV(d, {"max_depth": [3, 5, 8]}, cv=5).fit(Xtr, ytr)Vazifa 3: Overfitting
Modellang:
- Cheklovsiz daraxt
- Chuqurlik egri chizig'i
- Bayes chegarasi
- Ma'lumot hajmi
Vazifa 4: Cheklovlar
Modellang:
- min_samples_leaf
- max_leaf_nodes
- min_impurity_decrease
- max_depth cheklovi
Vazifa 5: Pruning
Modellang:
- Pruning yo'li
- Alpha tanlash
- Pre va post
- Hajm bog'liqligi
Vazifa 6: Sozlash
Modellang:
- GridSearchCV
- Eng yaxshi konfiguratsiyalar
- Shovqin ta'siri
- Ansambl bilan solishtirish
Vazifa 7: O'ylash
Post-pruning (ccp_alpha) nazariy adabiyotda pre-pruning dan ustun deb ko'rsatiladi, lekin amalda deyarli hamma max_depth va min_samples_leaf ishlatadi. Nega?
Javob
Qisqa javob: post-pruning haqiqatan ham sifatliroq daraxt beradi, lekin uning afzalligi kichik (odatda 1-2%), narxi esa katta (to'liq daraxtni o'stirish + yo'lni hisoblash + CV) — va zamonaviy amaliyotda bitta daraxt o'rniga ansambl ishlatilgani uchun bu farq umuman ahamiyatsiz bo'lib qoladi.
1. Nazariy ustunlik nimada
| Yondashuv | Qaror asosi |
|---|---|
| Pre-pruning | Oldindan belgilangan chegara |
| Post-pruning | To'liq daraxtni ko'rib, xato/murakkablik muvozanati |
Pre-pruning **"ufq muammosi"**ga uchraydi: hozirgi bo'linish foydasiz ko'rinishi mumkin, lekin undan keyingi bo'linish juda foydali bo'lishi mumkin (XOR ga o'xshash naqshlar). Ochko'z to'xtash bunday holatni boy beradi.
2. Amaliy narx
- To'liq daraxtni o'stirish katta ma'lumotda qimmat
cost_complexity_pruning_pathyuzlab alpha qaytaradi- Har alpha uchun CV kerak -> yuzlab model
max_depthbo'yicha grid esa 5-6 qiymat
3. Asosiy sabab: ansambllar
- Random Forest da daraxtlar atayin to'liq o'stiriladi (15.5)
- Boosting da daraxtlar atayin sayoz (15.8)
- Ikkala holatda ham pruning kerak emas
- Bitta daraxt esa faqat talqin uchun ishlatiladi — u yerda
max_depth=3shunchaki qulayroq
4. Qachon post-pruning arziydi
- Bitta daraxt yakuniy model bo'lsa (talqin talabi qat'iy)
- Ma'lumot kichik (o'stirish arzon)
- Qoidalar ro'yxati chiqarish kerak
5. Xulosa
- Nazariy ustunlik bor, lekin kichik
- Hisoblash narxi yuqori
- Ansambllar masalani boshqa yo'l bilan hal qiladi
- Bitta daraxt kerak bo'lsa — post-pruning ni ko'rib chiqing
Nimani mustahkamlaydi: 2.3, 2.7-bo'limlar.
Xulosa
Bu darsda daraxt o'sishini nazorat qilishni o'rgandik.
Eng muhim uch fikr:
Cheklovsiz daraxt yodlaydi.
DecisionTreeClassifier()standart holatda hech qanday cheklovsiz o'sadi va o'quv aniqligi 1.0000 bo'ladi — bu modelning yaxshiligi emas, cheklov yo'qligining belgisi. Shovqinli ma'lumotda test aniqligi keskin pasayadi.min_samples_leaf — eng ishonchli chekov. U har bargda yetarlicha namuna bo'lishini kafolatlaydi, ya'ni barg bashorati statistik ma'noga ega bo'ladi.
max_depthesa faqat yo'l uzunligini cheklaydi va bargdagi namunalar sonini kafolatlamaydi — shuning uchun ikkalasini birga ishlating.Tanlov faqat CV bo'yicha. O'quv aniqligi chuqurlik bilan monoton o'sadi va overfitting ni hech qachon ko'rsatmaydi.
ccp_alpha(post-pruning)cost_complexity_pruning_pathorqali topiladi va CV bilan tanlanadi. Shovqin ko'p bo'lsa sayozroq, ma'lumot ko'p bo'lsa chuqurroq daraxt afzal. Va eng muhimi: sozlanmagan ansambl ko'pincha uzoq sozlangan bitta daraxtdan kuchliroq.
Keyingi darsda daraxt beqarorligini o'rganamiz: nega kichik o'zgarish tuzilmani butunlay o'zgartiradi va bu ansambllarga qanday yo'l ochadi.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!