Mundarija (22)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. MDI va uning tuzoqlari
- 2.2. Permutation importance
- 2.3. Drop-column
- 2.4. SHAP qiymatlari
- 2.5. Korrelyatsiyali belgilar
- 2.6. Sababiylik emas
- 2.7. Tuzoqlar
- 2.8. Qaysi usulni qachon
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — MDI ning kardinallik tuzog'i
- Misol 2 — Korrelyatsiyali belgilar
- Misol 3 — Drop-column va partial dependence
- Misol 4 — Muhimlik sababiylik emas
- 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.11-dars: Belgi muhimligi
15-QISM — DARAXTLAR VA ANSAMBLLAR · 11-dars
1. Kirish va motivatsiya
model.feature_importances_ — ansambl bilan ishlashda eng ko'p ishlatiladigan va eng ko'p noto'g'ri talqin qilinadigan atribut. U chiroyli diagramma beradi, hisobotga oson kiradi va ko'pincha aldaydi.
Uch muammo bor: (1) u kardinallikka moyil — ko'p noyob qiymatli belgilar sun'iy yuqori ball oladi; (2) u korrelyatsiyali belgilar orasida muhimlikni tasodifiy taqsimlaydi; (3) u o'quv ma'lumotida hisoblanadi, ya'ni overfitting ni aks ettiradi.
Bu darsda: nopoklikka asoslangan muhimlik (MDI) va uning tuzoqlari, permutation importance, drop-column usuli, SHAP qiymatlari, korrelyatsiyali belgilar bilan ishlash va muhimlikni sababiylik bilan adashtirmaslik.
Real vaziyat. Kredit modelida feature_importances_ bo'yicha eng muhim belgi "mijoz ID raqami" chiqdi. ID tasodifiy son edi va hech qanday ma'no tashimasdi — lekin u noyob bo'lgani uchun daraxt undan cheksiz bo'linish topa olardi. Permutation importance shu belgining muhimligini 0 ko'rsatdi.
Bu darsda belgi muhimligini o'rganamiz.
Bu darsda:
- MDI va uning tuzoqlari
- Permutation importance
- Drop-column
- SHAP qiymatlari
- Korrelyatsiyali belgilar
- Sababiylik emas
- Tuzoqlar
- Amaliy: to'liq tahlil
ℹ Misollar real numpy/pandas/sklearn bilan (Python 3.14).
2. Nazariya — chuqur tushuntirish
2.1. MDI va uning tuzoqlari
MDI (Mean Decrease in Impurity) = feature_importances_
har belgi uchun: u bergan nopoklik kamayishlarining
og'irlikli yig'indisi (barcha daraxtlar bo'yicha)
UCH TUZOQ:
1. KARDINALLIK moyilligi — ko'p noyob qiymatli belgi ustun
(ID, vaqt belgisi, uzluksiz belgi > kategoriya)
2. O'QUV ma'lumotida hisoblanadi — overfitting aks etadi
3. KORRELYATSIYALI belgilar orasida tasodifiy taqsimlanadi
sklearn hujjati ham ogohlantiradi: permutation importance ni tavsiya qiladiKardinallik moyilligi eng xavfli tuzoq: tasodifiy uzluksiz belgi (yoki ID) daraxtda ko'p bo'linish imkonini beradi va shuning uchun MDI yuqori chiqadi — garchi u hech qanday bashorat kuchiga ega bo'lmasa ham.
2.2. Permutation importance
G'oya: belgini ARALASHTIRSAK, sifat qanchaga tushadi?
1. Asosiy ball hisoblanadi (validatsiya/test to'plamida)
2. Bitta belgi ustuni tasodifiy aralashtiriladi
3. Ball qayta hisoblanadi
4. muhimlik = asosiy - aralashtirilgan
5. n_repeats marta takrorlanadi -> o'rtacha va std
sklearn:
from sklearn.inspection import permutation_importance
r = permutation_importance(model, Xte, yte, n_repeats=20,
scoring="roc_auc", random_state=0)
r.importances_mean, r.importances_stdPermutation importance ni albatta test yoki validatsiya to'plamida hisoblang. O'quv to'plamida u MDI bilan bir xil muammoga uchraydi: model o'quv ma'lumotini yodlagan bo'lsa, har belgi "muhim" ko'rinadi.
2.3. Drop-column
Eng halol, lekin eng qimmat usul:
har belgi uchun: uni OLIB TASHLAB, modelni QAYTA o'qitish
muhimlik = to'liq model balli - belgisiz model balli
+ haqiqiy hissani o'lchaydi
- p ta qayta o'qitish kerak
- korrelyatsiyali belgilarda ikkalasi ham "muhimsiz" chiqadi
Amalda: faqat kam belgili yoki muhim qarorlardaKorrelyatsiyali belgilarda barcha uch usul ham muammoga uchraydi: drop-column da bir belgi olib tashlansa, ikkinchisi uning o'rnini bosadi va ball tushmaydi — ya'ni ikkalasi ham "muhimsiz" ko'rinadi.
2.4. SHAP qiymatlari
SHAP (SHapley Additive exPlanations) — o'yin nazariyasidan
har BASHORAT uchun har belgining hissasi:
f(x) = asosiy_qiymat + sum(shap_qiymat_i)
+ lokal (bitta bashorat) va global (o'rtacha |SHAP|) tushuntirish
+ daraxtlar uchun aniq va tez algoritm (TreeSHAP)
+ yo'nalish ko'rinadi (musbat/manfiy ta'sir)
- alohida kutubxona (shap)
- korrelyatsiyali belgilarda talqin murakkab
sklearn muqobili: partial_dependence, PartialDependenceDisplaySHAP ning asosiy afzalligi — lokal tushuntirish: "nega aynan bu mijozga rad javobi berildi?" degan savolga son bilan javob beradi. Bu moliyaviy va tibbiy qo'llanmalarda ko'pincha huquqiy talab.
2.5. Korrelyatsiyali belgilar
Muammo: a va b korrelyatsiyasi 0.95
MDI: muhimlik ikkiga bo'linadi (ikkalasi ham "o'rtacha")
Permutation: a ni aralashtirsak, model b dan foydalanadi
-> ikkalasi ham "muhimsiz" chiqadi
YECHIMLAR:
1. Ierarxik klasterlash bilan guruhlash, guruhni birga aralashtirish
2. Korrelyatsiyali guruhdan bittasini qoldirish
3. Guruh darajasida muhimlik hisoblash
4. Conditional permutation importance
sklearn misoli: scipy.cluster.hierarchy bilan Spearman asosidaGuruh bo'yicha aralashtirish — eng amaliy yechim: korrelyatsiyali belgilarni klasterlarga ajratib, klasterni birgalikda aralashtirasiz. Shunda guruhning haqiqiy hissasi ko'rinadi.
2.6. Sababiylik emas
Muhimlik BASHORAT uchun foydalilikni o'lchaydi, SABABNI emas
Misol: "kasalxonada yotgan kunlar soni" o'lim ehtimolini yaxshi bashorat qiladi
-> lekin kunlarni kamaytirish o'limni kamaytirmaydi
Sababiy xulosa uchun kerak:
- eksperiment (A/B test)
- sababiy modellar (DAG, instrumental o'zgaruvchilar)
- domen bilimi
"Bu belgi muhim -> uni o'zgartiraylik" - ENG KENG TARQALGAN XATOBu — eng muhim ogohlantirish: muhimlik diagrammasi asosida biznes qarori qabul qilish (masalan "bu ko'rsatkichni oshiramiz") sababiylikni nazarda tutadi, model esa uni bermaydi.
2.7. Tuzoqlar
Asosiy tuzoqlar: feature_importances_ ni hisobotga to'g'ridan-to'g'ri qo'yish; permutation ni o'quv to'plamida hisoblash; n_repeats ni juda kichik qo'yish; korrelyatsiyali belgilarni tekshirmaslik; muhimlikni sababiy talqin qilish; ID/vaqt belgilarini modelda qoldirish; muhimlikka qarab belgi tanlashda (feature selection) leakage qilish; turli usullar bir xil javob berishini kutish.
2.8. Qaysi usulni qachon
feature_importances_ (MDI) tez, lekin kardinallikka moyil, o'quv ma'lumotida hisoblanadi va korrelyatsiyada chalg'itadi. Permutation importance ni test to'plamida hisoblang — u ancha ishonchli. Drop-column eng halol, lekin qimmat. SHAP lokal tushuntirish beradi. Korrelyatsiyali belgilarni guruhlab aralashtiring. Va eng muhimi: muhimlik — bashorat foydaliligi, sababiylik emas. Keyingi dars — ansambllarni solishtirish.
3. Tez ma'lumotnoma
from sklearn.inspection import permutation_importance, partial_dependence
model.feature_importances_ # MDI - ehtiyot bo'ling
r = permutation_importance(model, Xte, yte, n_repeats=20,
scoring="roc_auc", random_state=0, n_jobs=-1)
tartib = np.argsort(-r.importances_mean)
for i in tartib[:10]:
print(nomlar[i], r.importances_mean[i], r.importances_std[i])
# korrelyatsiyali guruhlar
from scipy.cluster.hierarchy import fcluster, linkage
from scipy.stats import spearmanr
korr = spearmanr(X).correlation
guruh = fcluster(linkage(1 - np.abs(korr), "average"), 0.3, "distance")
QOIDA: permutation ni TEST da · guruhlab aralashtir ·
sababiy talqin qilmaMuhimlik xulosasi
MDI: tez, kardinallikka moyil, o'quvda, korrelyatsiyada chalg'itadi
Permutation: test da hisobla, n_repeats >= 10
Drop-column: eng halol, p ta qayta o'qitish
SHAP: lokal + global, yo'nalish ko'rinadi
Muhimlik != sababiylik4. Batafsil misollar
Misollar real numpy/pandas/sklearn bilan (Python 3.14).
Misol 1 — MDI ning kardinallik tuzog'i
"""Tasodifiy ID nega "eng muhim" chiqadi (real numpy/pandas/sklearn)."""
import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.inspection import permutation_importance
from sklearn.model_selection import train_test_split
def yarat(seed: int = 5, n: int = 4000) -> pd.DataFrame:
rng = np.random.default_rng(seed)
haqiqiy1 = rng.normal(0, 1, n)
haqiqiy2 = rng.normal(0, 1, n)
ikkilik = rng.integers(0, 2, n).astype(float) # 2 daraja
uch_daraja = rng.integers(0, 3, n).astype(float) # 3 daraja
tasodifiy_id = rng.permutation(n).astype(float) # n daraja, ma'nosiz
tasodifiy_son = rng.normal(0, 1, n) # uzluksiz, ma'nosiz
kuch = 1.5 * haqiqiy1 - 1.2 * haqiqiy2 + 0.8 * ikkilik
y = (rng.random(n) < 1 / (1 + np.exp(-kuch))).astype(int)
return pd.DataFrame({"haqiqiy1": haqiqiy1, "haqiqiy2": haqiqiy2,
"ikkilik": ikkilik, "uch_daraja": uch_daraja,
"tasodifiy_id": tasodifiy_id,
"tasodifiy_son": tasodifiy_son, "y": y})
def main() -> None:
df = yarat()
nomlar = [c for c in df.columns if c != "y"]
X, y = df[nomlar], df["y"]
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.3, random_state=0,
stratify=y)
o = RandomForestClassifier(n_estimators=300, random_state=0,
n_jobs=1).fit(Xtr, ytr)
print("=== 1. Belgilarning noyob qiymatlari ===")
for nom in nomlar:
print(f" {nom:<15}: {X[nom].nunique():>5} noyob qiymat")
print("\n=== 2. MDI (feature_importances_) ===")
mdi = o.feature_importances_
for i in np.argsort(-mdi):
print(f" {nomlar[i]:<15}: {mdi[i]:.4f}")
print(f" (haqiqiy signal faqat: haqiqiy1, haqiqiy2, ikkilik)")
print("\n=== 3. Permutation importance (test to'plamida) ===")
r = permutation_importance(o, Xte, yte, n_repeats=20, scoring="roc_auc",
random_state=0, n_jobs=1)
for i in np.argsort(-r.importances_mean):
print(f" {nomlar[i]:<15}: {r.importances_mean[i]:>+8.4f} "
f"(std {r.importances_std[i]:.4f})")
print("\n=== 4. Permutation: o'quv va test farqi ===")
r_tr = permutation_importance(o, Xtr, ytr, n_repeats=10,
scoring="roc_auc", random_state=0, n_jobs=1)
print(f" {'belgi':<15} {'MDI':>8} {'perm(o_quv)':>13} "
f"{'perm(test)':>12}")
for i in range(len(nomlar)):
print(f" {nomlar[i]:<15} {mdi[i]:>8.4f} "
f"{r_tr.importances_mean[i]:>+13.4f} "
f"{r.importances_mean[i]:>+12.4f}")
print(" ⭐ MDI ma'nosiz belgini yuqori baholaydi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Belgilarning noyob qiymatlari ===
haqiqiy1 : 4000 noyob qiymat
haqiqiy2 : 4000 noyob qiymat
ikkilik : 2 noyob qiymat
uch_daraja : 3 noyob qiymat
tasodifiy_id : 4000 noyob qiymat
tasodifiy_son : 4000 noyob qiymat
=== 2. MDI (feature_importances_) ===
haqiqiy1 : 0.3624
haqiqiy2 : 0.2930
tasodifiy_id : 0.1498
tasodifiy_son : 0.1460
uch_daraja : 0.0302
ikkilik : 0.0186
(haqiqiy signal faqat: haqiqiy1, haqiqiy2, ikkilik)
=== 3. Permutation importance (test to'plamida) ===
haqiqiy1 : +0.2055 (std 0.0146)
haqiqiy2 : +0.1301 (std 0.0105)
ikkilik : +0.0092 (std 0.0028)
tasodifiy_son : +0.0030 (std 0.0022)
uch_daraja : +0.0005 (std 0.0018)
tasodifiy_id : -0.0021 (std 0.0028)
=== 4. Permutation: o'quv va test farqi ===
belgi MDI perm(o_quv) perm(test)
haqiqiy1 0.3624 +0.2792 +0.2055
haqiqiy2 0.2930 +0.2110 +0.1301
ikkilik 0.0186 +0.0291 +0.0092
uch_daraja 0.0302 +0.0048 +0.0005
tasodifiy_id 0.1498 +0.0285 -0.0021
tasodifiy_son 0.1460 +0.0231 +0.0030
⭐ MDI ma'nosiz belgini yuqori baholaydiNima ko'rsatdi: 2.1, 2.2-bo'limlar.
Misol 2 — Korrelyatsiyali belgilar
"""Muhimlik nega "yo'qoladi" va uni qanday tiklash (real numpy/scipy/sklearn)."""
import numpy as np
from scipy.cluster.hierarchy import fcluster, linkage
from scipy.spatial.distance import squareform
from scipy.stats import spearmanr
from sklearn.ensemble import RandomForestClassifier
from sklearn.inspection import permutation_importance
from sklearn.metrics import roc_auc_score
from sklearn.model_selection import train_test_split
def yarat(seed: int = 8, n: int = 4000):
rng = np.random.default_rng(seed)
asos = rng.normal(0, 1, n)
# uchta korrelyatsiyali nusxa
a1 = asos + rng.normal(0, 0.25, n)
a2 = asos + rng.normal(0, 0.25, n)
a3 = asos + rng.normal(0, 0.25, n)
mustaqil = rng.normal(0, 1, n)
shovqin = rng.normal(0, 1, (n, 3))
X = np.column_stack([a1, a2, a3, mustaqil, shovqin])
kuch = 1.6 * asos + 1.2 * mustaqil
y = (rng.random(n) < 1 / (1 + np.exp(-kuch))).astype(int)
nomlar = ["nusxa1", "nusxa2", "nusxa3", "mustaqil", "shovqin1",
"shovqin2", "shovqin3"]
return X, y, nomlar
def main() -> None:
X, y, nomlar = yarat()
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.3, random_state=0,
stratify=y)
o = RandomForestClassifier(n_estimators=300, random_state=0,
n_jobs=1).fit(Xtr, ytr)
print("=== 1. Korrelyatsiya ===")
print(f" nusxa1 - nusxa2: {np.corrcoef(X[:, 0], X[:, 1])[0, 1]:.4f}")
print(f" nusxa1 - mustaqil: {np.corrcoef(X[:, 0], X[:, 3])[0, 1]:.4f}")
print("\n=== 2. MDI va permutation ===")
mdi = o.feature_importances_
r = permutation_importance(o, Xte, yte, n_repeats=20, scoring="roc_auc",
random_state=0, n_jobs=1)
print(f" {'belgi':<12} {'MDI':>8} {'permutation':>13}")
for i in range(len(nomlar)):
print(f" {nomlar[i]:<12} {mdi[i]:>8.4f} "
f"{r.importances_mean[i]:>+13.4f}")
print(" (uchta nusxa birgalikda mustaqildan kuchli, lekin alohida past)")
print("\n=== 3. Ierarxik klasterlash ===")
korr = spearmanr(X).correlation
masofa = 1 - np.abs(korr)
np.fill_diagonal(masofa, 0.0)
masofa = (masofa + masofa.T) / 2
Z = linkage(squareform(masofa, checks=False), "average")
guruhlar = fcluster(Z, 0.3, criterion="distance")
for g in np.unique(guruhlar):
azolar = [nomlar[i] for i in range(len(nomlar)) if guruhlar[i] == g]
print(f" guruh {g}: {azolar}")
print("\n=== 4. Guruh bo'yicha aralashtirish ===")
asosiy = roc_auc_score(yte, o.predict_proba(Xte)[:, 1])
rng = np.random.default_rng(0)
print(f" asosiy AUC: {asosiy:.4f}")
print(f" {'guruh':<28} {'muhimlik':>10}")
for g in np.unique(guruhlar):
indekslar = [i for i in range(len(nomlar)) if guruhlar[i] == g]
ballar = []
for _ in range(15):
Xa = Xte.copy()
aralash = rng.permutation(len(Xa))
Xa[:, indekslar] = Xa[aralash][:, indekslar] # BIRGA aralashtirish
ballar.append(roc_auc_score(yte, o.predict_proba(Xa)[:, 1]))
nom = ",".join(nomlar[i] for i in indekslar)
print(f" {nom:<28} {asosiy - np.mean(ballar):>+10.4f}")
print(" ⭐ Guruhlab aralashtirish haqiqiy hissani ko'rsatadi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Korrelyatsiya ===
nusxa1 - nusxa2: 0.9445
nusxa1 - mustaqil: -0.0070
=== 2. MDI va permutation ===
belgi MDI permutation
nusxa1 0.1753 +0.0476
nusxa2 0.1575 +0.0224
nusxa3 0.1739 +0.0233
mustaqil 0.2170 +0.1210
shovqin1 0.0938 +0.0000
shovqin2 0.0924 -0.0010
shovqin3 0.0901 -0.0008
(uchta nusxa birgalikda mustaqildan kuchli, lekin alohida past)
=== 3. Ierarxik klasterlash ===
guruh 1: ['nusxa1', 'nusxa2', 'nusxa3']
guruh 2: ['shovqin1']
guruh 3: ['mustaqil']
guruh 4: ['shovqin3']
guruh 5: ['shovqin2']
=== 4. Guruh bo'yicha aralashtirish ===
asosiy AUC: 0.8442
guruh muhimlik
nusxa1,nusxa2,nusxa3 +0.2476
shovqin1 -0.0005
mustaqil +0.1217
shovqin3 -0.0004
shovqin2 -0.0027
⭐ Guruhlab aralashtirish haqiqiy hissani ko'rsatadiNima ko'rsatdi: 2.5-bo'lim.
Misol 3 — Drop-column va partial dependence
"""Eng halol usul va ta'sir yo'nalishi (real numpy/sklearn)."""
import numpy as np
from sklearn.ensemble import HistGradientBoostingClassifier
from sklearn.inspection import partial_dependence, permutation_importance
from sklearn.metrics import roc_auc_score
from sklearn.model_selection import train_test_split
def yarat(seed: int = 13, n: int = 5000):
rng = np.random.default_rng(seed)
X = rng.normal(0, 1, (n, 6))
kuch = (1.5 * X[:, 0] - 1.2 * X[:, 1]
+ 1.0 * ((X[:, 2] > 0.5) & (X[:, 3] > 0))
+ 0.4 * X[:, 4])
y = (rng.random(n) < 1 / (1 + np.exp(-kuch))).astype(int)
nomlar = ["kuchli+", "kuchli-", "ozaro_a", "ozaro_b", "zaif", "shovqin"]
return X, y, nomlar
def main() -> None:
X, y, nomlar = yarat()
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.3, random_state=0,
stratify=y)
def oqit(Xa, Xb):
m = HistGradientBoostingClassifier(learning_rate=0.1, max_iter=300,
early_stopping=True,
validation_fraction=0.15,
n_iter_no_change=20,
random_state=0).fit(Xa, ytr)
return m, roc_auc_score(yte, m.predict_proba(Xb)[:, 1])
print("=== 1. To'liq model ===")
model, toliq = oqit(Xtr, Xte)
print(f" test AUC: {toliq:.4f}")
print("\n=== 2. Drop-column muhimligi ===")
print(f" {'olib tashlangan':<18} {'AUC':>9} {'yo_qotish':>11}")
drop = {}
for i, nom in enumerate(nomlar):
qolgan = [j for j in range(len(nomlar)) if j != i]
_, a = oqit(Xtr[:, qolgan], Xte[:, qolgan])
drop[nom] = toliq - a
print(f" {nom:<18} {a:>9.4f} {toliq - a:>+11.4f}")
print("\n=== 3. Uch usul yonma-yon ===")
r = permutation_importance(model, Xte, yte, n_repeats=20,
scoring="roc_auc", random_state=0, n_jobs=1)
print(f" {'belgi':<12} {'permutation':>13} {'drop-column':>13}")
for i, nom in enumerate(nomlar):
print(f" {nom:<12} {r.importances_mean[i]:>+13.4f} "
f"{drop[nom]:>+13.4f}")
print("\n=== 4. Ta'sir yo'nalishi (partial dependence) ===")
for i in [0, 1, 4]:
pd_natija = partial_dependence(model, Xte, [i], grid_resolution=5,
kind="average")
qiymatlar = pd_natija["grid_values"][0]
ortacha = pd_natija["average"][0]
print(f" {nomlar[i]:<10}: x = {np.round(qiymatlar, 2).tolist()}")
print(f" {'':<10} f = {np.round(ortacha, 3).tolist()}")
print(" ⭐ Muhimlik kattaligini, PD yo'nalishini ko'rsatadi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. To'liq model ===
test AUC: 0.8300
=== 2. Drop-column muhimligi ===
olib tashlangan AUC yo_qotish
kuchli+ 0.6880 +0.1420
kuchli- 0.7632 +0.0668
ozaro_a 0.8287 +0.0013
ozaro_b 0.8208 +0.0092
zaif 0.8211 +0.0089
shovqin 0.8349 -0.0049
=== 3. Uch usul yonma-yon ===
belgi permutation drop-column
kuchli+ +0.1986 +0.1420
kuchli- +0.1228 +0.0668
ozaro_a +0.0073 +0.0013
ozaro_b +0.0108 +0.0092
zaif +0.0146 +0.0089
shovqin -0.0001 -0.0049
=== 4. Ta'sir yo'nalishi (partial dependence) ===
kuchli+ : x = [-1.65, -0.82, 0.01, 0.84, 1.67]
f = [-2.309, -1.149, 0.066, 1.621, 1.819]
kuchli- : x = [-1.75, -0.92, -0.09, 0.74, 1.57]
f = [1.906, 1.247, 0.097, -0.694, -2.284]
zaif : x = [-1.62, -0.8, 0.01, 0.83, 1.65]
f = [-0.358, -0.175, 0.094, 0.486, 0.586]
⭐ Muhimlik kattaligini, PD yo'nalishini ko'rsatadiNima ko'rsatdi: 2.3, 2.4-bo'limlar.
Misol 4 — Muhimlik sababiylik emas
"""Bashorat kuchi va sababiy ta'sir farqi (real numpy/sklearn)."""
import numpy as np
from sklearn.ensemble import RandomForestRegressor
from sklearn.inspection import permutation_importance
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score
from sklearn.model_selection import train_test_split
def yarat(seed: int = 17, n: int = 5000):
"""Sababiy tuzilma: davolash -> tuzalish; kunlar <- og'irlik -> tuzalish."""
rng = np.random.default_rng(seed)
ogirlik = rng.normal(0, 1, n) # kasallik og'irligi (yashirin)
davolash = (rng.random(n) < 0.5).astype(float)
# kunlar og'irlikning NATIJASI, sababi emas
kunlar = 5 + 3 * ogirlik - 1.0 * davolash + rng.normal(0, 0.8, n)
tuzalish = (10 - 2.5 * ogirlik + 3.0 * davolash + rng.normal(0, 1.0, n))
X = np.column_stack([davolash, kunlar, rng.normal(0, 1, (n, 2))])
nomlar = ["davolash", "kunlar", "shovqin1", "shovqin2"]
return X, tuzalish, nomlar, ogirlik
def main() -> None:
X, y, nomlar, ogirlik = yarat()
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.3, random_state=0)
o = RandomForestRegressor(n_estimators=300, max_features=0.5,
random_state=0, n_jobs=1).fit(Xtr, ytr)
print("=== 1. Model sifati ===")
print(f" test R^2: {r2_score(yte, o.predict(Xte)):.4f}")
print("\n=== 2. Muhimlik ===")
r = permutation_importance(o, Xte, yte, n_repeats=20, scoring="r2",
random_state=0, n_jobs=1)
print(f" {'belgi':<12} {'MDI':>8} {'permutation':>13}")
for i in np.argsort(-r.importances_mean):
print(f" {nomlar[i]:<12} {o.feature_importances_[i]:>8.4f} "
f"{r.importances_mean[i]:>+13.4f}")
print(" (kunlar eng muhim ko'rinadi)")
print("\n=== 3. Sababiy haqiqat ===")
print(" Haqiqiy tuzilma:")
print(" og'irlik -> kunlar (og'irlik kunlarni oshiradi)")
print(" og'irlik -> tuzalish (og'irlik tuzalishni kamaytiradi)")
print(" davolash -> tuzalish (+3.0)")
print(" davolash -> kunlar (-1.0)")
print(" Ya'ni kunlar tuzalishga TA'SIR QILMAYDI - ikkalasi ham")
print(" og'irlikning natijasi (umumiy sabab)")
print("\n=== 4. Aralashuv (intervention) simulyatsiyasi ===")
# kunlarni sun'iy kamaytirish tuzalishni o'zgartiradimi?
Xa = Xte.copy()
Xa[:, 1] -= 2.0 # "kunlarni 2 ga kamaytiramiz"
print(f" model bashorati (kunlar -2): "
f"{o.predict(Xa).mean():.4f} (asl {o.predict(Xte).mean():.4f})")
print(f" model o'zgarish kutmoqda: "
f"{o.predict(Xa).mean() - o.predict(Xte).mean():+.4f}")
print(" Lekin haqiqiy mexanizmda kunlar tuzalishga ta'sir qilmaydi:")
print(" haqiqiy o'zgarish = 0.0000")
# to'g'ri sababiy baho: og'irlikni nazoratga olish
Xc = np.column_stack([X[:, 0], ogirlik])
ch = LinearRegression().fit(Xc, y)
print(f" davolashning sababiy ta'siri (og'irlik nazoratda): "
f"{ch.coef_[0]:+.4f} (haqiqiy +3.0000)")
chs = LinearRegression().fit(X[:, [0]], y)
print(f" og'irliksiz baho: {chs.coef_[0]:+.4f}")
print(" ⭐ Muhimlik bashorat uchun, sababiylik uchun emas")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Model sifati ===
test R^2: 0.8349
=== 2. Muhimlik ===
belgi MDI permutation
kunlar 0.7140 +1.2293
davolash 0.1749 +0.2539
shovqin2 0.0559 -0.0006
shovqin1 0.0552 -0.0038
(kunlar eng muhim ko'rinadi)
=== 3. Sababiy haqiqat ===
Haqiqiy tuzilma:
og'irlik -> kunlar (og'irlik kunlarni oshiradi)
og'irlik -> tuzalish (og'irlik tuzalishni kamaytiradi)
davolash -> tuzalish (+3.0)
davolash -> kunlar (-1.0)
Ya'ni kunlar tuzalishga TA'SIR QILMAYDI - ikkalasi ham
og'irlikning natijasi (umumiy sabab)
=== 4. Aralashuv (intervention) simulyatsiyasi ===
model bashorati (kunlar -2): 13.0663 (asl 11.5513)
model o'zgarish kutmoqda: +1.5150
Lekin haqiqiy mexanizmda kunlar tuzalishga ta'sir qilmaydi:
haqiqiy o'zgarish = 0.0000
davolashning sababiy ta'siri (og'irlik nazoratda): +3.0096 (haqiqiy +3.0000)
og'irliksiz baho: +3.0667
⭐ Muhimlik bashorat uchun, sababiylik uchun emasNima ko'rsatdi: 2.6-bo'lim.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
| "feature_importances_ ishonchli" | Kardinallikka moyil |
| "MDI va permutation bir xil" | Ko'pincha farq qiladi |
| "Permutation ni o'quvda hisoblash mumkin" | Test da |
| "Korrelyatsiya muhimlikka ta'sir qilmaydi" | Kuchli ta'sir |
| "Muhim belgi — sabab" | Faqat bashorat |
| "Drop-column har doim to'g'ri" | Korrelyatsiyada emas |
| "SHAP sababiylikni beradi" | Yo'q |
| "n_repeats=1 yetarli" | 10-30 kerak |
6. Keng tarqalgan xatolar va yechimlari
1. MDI ni hisobotga qo'yish
plt.barh(nomlar, model.feature_importances_) # ⚠️
r = permutation_importance(model, Xte, yte, n_repeats=20) # ✅2. O'quvda permutation
permutation_importance(model, Xtr, ytr) # ⚠️
permutation_importance(model, Xte, yte) # ✅3. Korrelyatsiyani tekshirmaslik
# to'g'ridan-to'g'ri muhimlik ro'yxati # ⚠️
# avval spearmanr + klasterlash, keyin guruh bo'yicha # ✅4. Sababiy talqin
# "kunlarni kamaytiramiz - natija yaxshilanadi" # ⚠️
# eksperiment yoki sababiy model kerak # ✅5. ID ni modelda qoldirish
X = df.drop(columns="target") # id ham qoldi # ⚠️
X = df.drop(columns=["target", "mijoz_id"]) # ✅6. Kam takrorlash
permutation_importance(model, Xte, yte, n_repeats=2) # ⚠️
permutation_importance(model, Xte, yte, n_repeats=20) # ✅7. Muhimlik bo'yicha belgi tanlashda leakage
# butun ma'lumotda muhimlik -> belgi tanlash -> CV # ⚠️
# belgi tanlashni Pipeline ichiga qo'ying 12.9-bob # ✅7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 15.5-dars (o'tilgan): Random Forest
- 15.3-dars (o'tilgan): Beqarorlik
- 13.3-dars (o'tilgan): Koeffitsiyentlarni talqin
- 15.12-dars: Ansambllarni solishtirish
- 15.13-dars: Ishlab chiqarish
8. Eng yaxshi amaliyotlar
Permutation ni test da hisoblang.
n_repeats >= 10 qo'ying.
Korrelyatsiyani guruhlang.
MDI ni faqat ichki ko'rikda ishlating.
ID va vaqt belgilarini olib tashlang.
Yo'nalishni PD/SHAP bilan ko'ring.
Sababiy xulosa qilmang.
Bir necha usulni taqqoslang.
9. Amaliy topshiriq
Vazifa 1: Bashorat qiling
1. # MDI to'liq nomi?
2. # MDI ning birinchi tuzog'i?
3. # ikkinchisi?
4. # uchinchisi?
5. # permutation qanday ishlaydi?
6. # qaysi to'plamda?
7. # n_repeats odatiy?
8. # drop-column kamchiligi?
9. # SHAP nimadan kelib chiqqan?
10. # korrelyatsiyada yechim?
11. # muhimlik sababiylikmi?
12. # ID ni nima qilish kerak?Javoblar
- Mean Decrease in Impurity
- Kardinallik moyilligi
- O'quv ma'lumotida
- Korrelyatsiyada tasodifiy taqsimlanish
- Belgini aralashtirib ball tushishini o'lchaydi
- Test / validatsiya
- 10-30
- p ta qayta o'qitish
- O'yin nazariyasi (Shapley)
- Guruhlab aralashtirish
- Yo'q
- Olib tashlash
Vazifa 2: Xatolarni tuzating
1. plt.barh(nomlar, model.feature_importances_)
2. permutation_importance(model, Xtr, ytr)
3. permutation_importance(model, Xte, yte, n_repeats=2)
4. X = df.drop(columns="target") # mijoz_id qoldi
5. # "eng muhim belgini o'zgartirsak natija yaxshilanadi"Javoblar
1. r = permutation_importance(model, Xte, yte, n_repeats=20)
2. permutation_importance(model, Xte, yte)
3. permutation_importance(model, Xte, yte, n_repeats=20)
4. X = df.drop(columns=["target", "mijoz_id"])
5. # eksperiment yoki sababiy model kerakVazifa 3: Kardinallik
Modellang:
- Noyob qiymatlar
- MDI
- Permutation
- O'quv va test
Vazifa 4: Korrelyatsiya
Modellang:
- Korrelyatsiya
- Ikki usul
- Klasterlash
- Guruh bo'yicha
Vazifa 5: Drop-column
Modellang:
- To'liq model
- Drop-column
- Uch usul
- Partial dependence
Vazifa 6: Sababiylik
Modellang:
- Model sifati
- Muhimlik
- Haqiqiy tuzilma
- Aralashuv
Vazifa 7: O'ylash
Belgi muhimligi bo'yicha belgilarni tanlash (feature selection) keng tarqalgan amaliyot. Bu qanchalik to'g'ri?
Javob
Qisqa javob: ishlaydi, lekin ikki shart bilan: (1) tanlov CV ichida qilinishi kerak, aks holda leakage bo'ladi; (2) korrelyatsiyali belgilarni guruhlab ko'rish kerak, aks holda muhim guruh butunlay yo'qotiladi.
1. Leakage xavfi
NOTO'G'RI: butun ma'lumotda muhimlik -> 20 ta belgi tanlash -> CV
CV bahosi OPTIMISTIK (tanlov butun ma'lumotni ko'rgan)
TO'G'RI: Pipeline([("tanlov", SelectFromModel(...)), ("model", ...)])
har foldda tanlov QAYTA qilinadi2. Korrelyatsiya muammosi
- Uch korrelyatsiyali nusxa: har birining muhimligi past
- Chegara bo'yicha kesilsa — uchalasi ham olib tashlanadi
- Natijada muhim signal yo'qoladi
- Yechim: klasterlash, har guruhdan bittasini qoldirish
3. Qachon belgi tanlash foydali
| Maqsad | Foyda |
|---|---|
| Tezlik / xotira | Katta |
| Talqin qilish | Katta |
| Ma'lumot yig'ish narxi | Katta |
| Aniqlik | Odatda kichik yoki manfiy |
Daraxtlar allaqachon ichki belgi tanlashni bajaradi — shuning uchun ansambl aniqligi kamdan-kam oshadi.
4. Amaliy tartib
- Aniq keraksizlarni olib tashlang (ID, konstanta, duplikat)
- Korrelyatsiyali guruhlarni aniqlang
- Har guruhdan vakil qoldiring
- Qolganini
SelectFromModelbilan Pipeline ichida - Natijani to'liq model bilan taqqoslang
5. Xulosa
- Tanlovni Pipeline ichiga qo'ying
- Korrelyatsiyani guruhlab ko'ring
- Aniqlik uchun emas, tezlik va talqin uchun
- Har doim to'liq model bilan taqqoslang
Nimani mustahkamlaydi: 2.2, 2.5-bo'limlar.
Xulosa
Bu darsda belgi muhimligini o'rgandik.
Eng muhim uch fikr:
feature_importances_(MDI) aldaydi. U kardinallikka moyil (ID va uzluksiz belgilar sun'iy yuqori ball oladi), o'quv ma'lumotida hisoblanadi va korrelyatsiyali belgilar orasida muhimlikni tasodifiy taqsimlaydi. Uni faqat tezkor ichki ko'rik uchun ishlating, hisobotga qo'ymang.Permutation importance — test to'plamida. Belgini aralashtirib, sifat qanchaga tushishini o'lchaydi.
n_repeatsni 10-30 qo'ying va albatta test yoki validatsiya to'plamida hisoblang. Korrelyatsiyali belgilarni Spearman + ierarxik klasterlash bilan guruhlab, guruhni birgalikda aralashtiring.Muhimlik sababiylik emas. "Kasalxonada yotgan kunlar" o'limni yaxshi bashorat qiladi, lekin kunlarni kamaytirish o'limni kamaytirmaydi — ikkalasi ham kasallik og'irligining natijasi. Muhimlik diagrammasi asosida "bu ko'rsatkichni o'zgartiramiz" degan qaror qabul qilish — eng keng tarqalgan xato. Sababiy xulosa uchun eksperiment yoki sababiy model kerak.
Keyingi darsda ansambllarni solishtirishni o'rganamiz: voting, stacking va qaysi ansamblni qachon tanlash.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!