Feature engineering va selection
Sahna: "yangi xususiyat qo'shing" — qanday?
10-bobdagi qaror jadvalida birinchi qator shunday edi:
Xatolar bitta guruhda to'plangan -> yangi xususiyat qo'shing
Yaxshi. Lekin qanday xususiyat? Qaysi biri yordam beradi?
Va 0-bobda men bitta urinish qilganman: maydon_har_xona qo'shdim va natija +0.0056 o'zgardi — ya'ni deyarli hech narsa.
Bu bob shu savolga javob beradi, va javobning yarmi ko'ngilsiz: xususiyat muhandisligi ko'pincha ishlamaydi. Lekin ishlaganda — eng katta foyda beradi.
Beshta usul
import pandas as pd import numpy as np from sklearn.model_selection import train_test_split, cross_val_score from sklearn.pipeline import Pipeline from sklearn.compose import ColumnTransformer from sklearn.preprocessing import StandardScaler, OneHotEncoder from sklearn.impute import SimpleImputer from sklearn.linear_model import LogisticRegression df = pd.read_csv(DATA / "uy_ijara.csv") son = ["xonalar", "maydon_m2", "qavat", "qavatlar_soni", "metro_km", "mebel", "qurilgan_yil"] matn = ["tuman"] X, y = df[son + matn], df["ijaraga_berildi_30k"] def quvur(son_list, matn_list=matn, model=None): return Pipeline([ ("t", ColumnTransformer([ ("son", Pipeline([("i", SimpleImputer(strategy="median")), ("sc", StandardScaler())]), son_list), ("matn", OneHotEncoder(handle_unknown="ignore"), matn_list), ])), ("m", model or LogisticRegression(max_iter=3000)), ]) baza_ball = cross_val_score(quvur(son), X, y, cv=5, scoring="f1") print(f"BOSHLANG'ICH (7 xususiyat): F1 = {baza_ball.mean():.4f} ±{baza_ball.std():.4f}") print() show(pd.DataFrame([ {"Usul": "1. Nisbat va ayirma", "Misol": "narx/maydon, maydon/xonalar"}, {"Usul": "2. Sana parchalash", "Misol": "yil, oy, hafta kuni, bayram kunimi"}, {"Usul": "3. Guruhlash (binning)", "Misol": "yosh -> 'yosh/o`rta/katta'"}, {"Usul": "4. O'zaro ta'sir", "Misol": "mebel VA metroga yaqin bo'lsa"}, {"Usul": "5. Guruh statistikasi", "Misol": "tumanning o'rtacha narxi"}, ]))
BOSHLANG'ICH (7 xususiyat): F1 = 0.7273 ±0.0118
| Usul | Misol |
|---|---|
| 1. Nisbat va ayirma | narx/maydon, maydon/xonalar |
| 2. Sana parchalash | yil, oy, hafta kuni, bayram kunimi |
| 3. Guruhlash (binning) | yosh -> 'yosh/o`rta/katta' |
| 4. O'zaro ta'sir | mebel VA metroga yaqin bo'lsa |
| 5. Guruh statistikasi | tumanning o'rtacha narxi |
1-usul: nisbat va ayirma
Eng ko'p ishlatiladigan usul. Domen bilimi kerak.
def nisbatlar(d): d = d.copy() d["maydon_har_xona"] = d.maydon_m2 / d.xonalar d["qavat_ulushi"] = d.qavat / d.qavatlar_soni d["yoshi"] = 2026 - d.qurilgan_yil return d yangi1 = son + ["maydon_har_xona", "qavat_ulushi", "yoshi"] b1 = cross_val_score(quvur(yangi1), nisbatlar(X), y, cv=5, scoring="f1") print(f"Boshlang'ich : {baza_ball.mean():.4f} ±{baza_ball.std():.4f}") print(f"+ 3 nisbat : {b1.mean():.4f} ±{b1.std():.4f}") print(f"O'zgarish : {b1.mean()-baza_ball.mean():+.4f} (tarqalish ±{max(b1.std(), baza_ball.std()):.4f})")
Boshlang'ich : 0.7273 ±0.0118 + 3 nisbat : 0.7278 ±0.0115 O'zgarish : +0.0004 (tarqalish ±0.0118)
Mavjud ustunlardan hisoblangan nisbat kam foyda beradi
maydon_har_xona = maydon_m2 / xonalar — model allaqachon ikkisini ham ko'rgan. Nisbat ularning yangi kombinatsiyasi, lekin yangi ma'lumot emas.
Chiziqli model nisbatni o'zi hisoblolmaydi (u faqat qo'shish va ko'paytirishni biladi), shuning uchun ba'zan yordam beradi. Daraxt esa nisbatni taqriban o'zi topadi — shuning uchun daraxtlarga bunday xususiyat deyarli foyda bermaydi.
Haqiqiy foyda yangi manba dan keladi: e'lon qancha vaqt saytda turgani, rasmlar soni, egasining javob tezligi.
2-usul: sanadan xususiyat
Bizning faylda sana yo'q, shuning uchun 43-bobdagi savdo ma'lumotini olamiz.
sv = pd.read_csv(DATA / "iflos_savdo.csv") sana = pd.to_datetime(sv.order_date, format="mixed", dayfirst=True, errors="coerce") tmp = pd.DataFrame({"sana": sana}).dropna() tmp["yil"] = tmp.sana.dt.year tmp["oy"] = tmp.sana.dt.month tmp["hafta_kuni"] = tmp.sana.dt.dayofweek tmp["chorak"] = tmp.sana.dt.quarter tmp["oy_kuni"] = tmp.sana.dt.day tmp["dam_olish_kuni"] = (tmp.sana.dt.dayofweek >= 5).astype(int) tmp["oy_boshi"] = (tmp.sana.dt.day <= 5).astype(int) show(tmp.head(6)) print() print("Bitta `sana` ustunidan 7 ta xususiyat chiqdi.")
Bitta `sana` ustunidan 7 ta xususiyat chiqdi.
| sana | yil | oy | hafta_kuni | chorak | oy_kuni | dam_olish_kuni | oy_boshi |
|---|---|---|---|---|---|---|---|
| 2025-05-26 00:00:00 | 2 025 | 5 | 0 | 2 | 26 | 0 | 0 |
| 2025-02-26 00:00:00 | 2 025 | 2 | 2 | 1 | 26 | 0 | 0 |
| 2025-03-01 00:00:00 | 2 025 | 3 | 5 | 1 | 1 | 1 | 1 |
| 2025-01-03 00:00:00 | 2 025 | 1 | 4 | 1 | 3 | 0 | 1 |
| 2025-02-11 00:00:00 | 2 025 | 2 | 1 | 1 | 11 | 0 | 0 |
| 2025-01-08 00:00:00 | 2 025 | 1 | 2 | 1 | 8 | 0 | 0 |
Sanani SON sifatida bermang
sana.astype(int) — bu timestamp beradi (1970 dan beri sekundlar). Model uni shunchaki o'sib boruvchi son deb ko'radi.
Natijada model "vaqt o'tgani sari natija oshadi" degan chiziqli bog'lanishni o'rganadi — va kelajakda ekstrapolyatsiya qilib yiqiladi.
Sanani parchalang: oy, hafta kuni, bayram. Bu davriy naqshlarni ushlaydi.
print("Hafta kuni bo'yicha bekor qilish ulushi — davriy naqsh bormi:") sv2 = sv.assign(sana=sana, bekor=(sv.status == "cancelled").astype(int)).dropna(subset=["sana"]) sv2["hafta_kuni"] = sv2.sana.dt.dayofweek kunlar = ["Dush", "Sesh", "Chor", "Pay", "Juma", "Shan", "Yak"] g = sv2.groupby("hafta_kuni").bekor.agg(["size", "mean"]) g.index = [kunlar[i] for i in g.index] g["mean"] = g["mean"].round(4) show(g.reset_index().rename(columns={"index": "kun", "size": "buyurtmalar", "mean": "bekor_ulushi"}))
Hafta kuni bo'yicha bekor qilish ulushi — davriy naqsh bormi:
| kun | buyurtmalar | bekor_ulushi |
|---|---|---|
| Dush | 885 | 0.042 |
| Sesh | 793 | 0.034 |
| Chor | 842 | 0.038 |
| Pay | 808 | 0.027 |
| Juma | 961 | 0.032 |
| Shan | 1 057 | 0.043 |
| Yak | 834 | 0.024 |
3-usul: guruhlash (binning)
def guruhlar(d): d = d.copy() d["maydon_guruh"] = pd.cut(d.maydon_m2, bins=[0, 40, 60, 90, 1000], labels=[0, 1, 2, 3]).astype(float) d["metro_guruh"] = pd.cut(d.metro_km, bins=[0, 1, 2.5, 5, 100], labels=[0, 1, 2, 3]).astype(float) return d yangi3 = son + ["maydon_guruh", "metro_guruh"] b3 = cross_val_score(quvur(yangi3), guruhlar(X), y, cv=5, scoring="f1") print(f"Boshlang'ich : {baza_ball.mean():.4f}") print(f"+ 2 guruh : {b3.mean():.4f} ({b3.mean()-baza_ball.mean():+.4f})")
Boshlang'ich : 0.7273 + 2 guruh : 0.7273 (-0.0000)
Binning chiziqli modelga chiziqsiz chegara beradi: "40 m2 dan kichik" alohida toifa bo'ladi.
Lekin narxi bor: ma'lumot yo'qoladi. 39 m2 va 41 m2 har xil guruhga tushadi, 41 va 59 esa bir guruhda.
4-usul: o'zaro ta'sir (interaction)
def ozaro(d): d = d.copy() d["mebel_x_metro"] = d.mebel * (d.metro_km < 2).astype(int) d["katta_va_markaz"] = ((d.maydon_m2 > 70) & (d.metro_km < 2)).astype(int) return d yangi4 = son + ["mebel_x_metro", "katta_va_markaz"] b4 = cross_val_score(quvur(yangi4), ozaro(X), y, cv=5, scoring="f1") print(f"Boshlang'ich : {baza_ball.mean():.4f}") print(f"+ 2 o'zaro ta'sir: {b4.mean():.4f} ({b4.mean()-baza_ball.mean():+.4f})") print() print("Daraxt bunday kombinatsiyani O'ZI topadi (17-bob), chiziqli model esa TOPMAYDI.")
Boshlang'ich : 0.7273 + 2 o'zaro ta'sir: 0.7265 (-0.0008) Daraxt bunday kombinatsiyani O'ZI topadi (17-bob), chiziqli model esa TOPMAYDI.
5-usul: guruh statistikasi — va uning tuzog'i
Eng kuchli usul: "bu kvartira o'z tumanidagi o'rtachaga nisbatan qanday?"
Lekin bu — leakage uchun eng xavfli joy.
# Target encoding: KARDINALLIK hamma narsani hal qiladi def te_ball(X_qoshimcha): q = Pipeline([("i", SimpleImputer(strategy="median")), ("sc", StandardScaler()), ("m", LogisticRegression(max_iter=3000))]) return cross_val_score(q, X_qoshimcha, y, cv=5, scoring="f1").mean() r2 = np.random.default_rng(0) faqat_son = df[son] # 1) past kardinallik: tuman — 8 guruh te_8 = faqat_son.assign(te=df.tuman.map(df.groupby("tuman").ijaraga_berildi_30k.mean())) # 2) yuqori kardinallik: 400 sun'iy guruh guruh_400 = r2.integers(0, 400, len(df)) te_400 = faqat_son.assign(te=pd.Series(y.values).groupby(guruh_400).transform("mean").values) # 3) chegara holat: har qator o'z guruhida te_1200 = faqat_son.assign(te=y.values.astype(float)) print(f"{'holat':<34} {'guruhda qator':>14} {'CV F1':>9}") print("-" * 60) print(f"{'baza (target encoding YO`Q)':<34} {'-':>14} {te_ball(faqat_son):>9.4f}") print(f"{'8 guruh (tuman)':<34} {len(df)//8:>14} {te_ball(te_8):>9.4f}") print(f"{'400 guruh':<34} {len(df)//400:>14} {te_ball(te_400):>9.4f}") print(f"{'1200 guruh (har qator o`zi)':<34} {1:>14} {te_ball(te_1200):>9.4f}")
holat guruhda qator CV F1 ------------------------------------------------------------ baza (target encoding YO`Q) - 0.7219 8 guruh (tuman) 150 0.7251 400 guruh 3 0.8032 1200 guruh (har qator o`zi) 1 1.0000
Mana bu jadval target encoding ni to'g'ri tushuntiradi.
Men bu bo'limni "target encoding butun ma'lumotda hisoblansa natija shubhali yaxshilanadi" deb yozgan edim va tuman ni misol qilgandim. O'lchadim — yaxshilanish bo'lmadi (0.7219 va 0.7251, farq ahamiyatsiz).
Sabab kardinallikda. tuman da 8 guruh bor, har birida ~150 qator. Bitta qatorning javobi 150 qatorli o'rtachaga deyarli ta'sir qilmaydi — shuning uchun leakage kuchsiz.
Guruhlar ko'payib, har birida qator kamayganda esa:
- 400 guruh (~3 qator) -> F1 0.8032 ga ko'tarildi. Mana leakage.
- 1200 guruh (1 qator) -> F1 1.0000. Har qator o'z javobini xususiyat sifatida ko'rdi.
Target encoding xavfi kardinallikka proporsional
Qoida: guruhda qator kamaysa, leakage kuchayadi.
- Guruhda yuzlab qator (tuman, viloyat) -> leakage kuchsiz, lekin baribir Pipeline ichida hisoblang
- Guruhda bir necha qator (mahsulot kodi, foydalanuvchi ID) -> xavfli
- Guruhda bitta qator -> bu target ning o'zi, xususiyat emas
Shuning uchun yuqori kardinallikdagi ustunlar uchun out-of-fold target encoding ishlatiladi: har qatorning kodlangan qiymati uni o'z ichiga olmagan fold lardan hisoblanadi.
Va eng muhimi: men bu yerda adashdim, chunki bitta holatni (8 guruh) sinab, undan umumiy xulosa chiqarmoqchi edim. Bitta o'lchov qoida bermaydi — parametrni o'zgartirib bir necha nuqtada o'lchang.
from sklearn.base import BaseEstimator, TransformerMixin class GuruhStatistikasi(BaseEstimator, TransformerMixin): """Guruh o'rtachasini FAQAT fit() ko'rgan ma'lumotdan hisoblaydi.""" def __init__(self, guruh_ustun="tuman", maqsad_ustun="narx_usd"): self.guruh_ustun = guruh_ustun self.maqsad_ustun = maqsad_ustun def fit(self, X, y=None): self.xarita_ = X.groupby(self.guruh_ustun)[self.maqsad_ustun].mean() self.umumiy_ = X[self.maqsad_ustun].mean() return self def transform(self, X): d = X.copy() d["guruh_ortacha"] = d[self.guruh_ustun].map(self.xarita_).fillna(self.umumiy_) d["guruhdan_farq"] = d[self.maqsad_ustun] - d["guruh_ortacha"] return d q_toza = Pipeline([ ("stat", GuruhStatistikasi()), ("t", ColumnTransformer([ ("son", Pipeline([("i", SimpleImputer(strategy="median")), ("sc", StandardScaler())]), son + ["guruh_ortacha", "guruhdan_farq"]), ("matn", OneHotEncoder(handle_unknown="ignore"), matn), ])), ("m", LogisticRegression(max_iter=3000)), ]) X_narx = df[son + matn + ["narx_usd"]] b5_toza = cross_val_score(q_toza, X_narx, y, cv=5, scoring="f1") print(f"Boshlang'ich : {baza_ball.mean():.4f}") print(f"+ guruh stat (Pipeline ichida): {b5_toza.mean():.4f} ±{b5_toza.std():.4f}") print() print("Bu raqamga ISHONISH mumkin — statistika har fold da qaytadan hisoblanadi.")
Boshlang'ich : 0.7273 + guruh stat (Pipeline ichida): 0.7400 ±0.0191 Bu raqamga ISHONISH mumkin — statistika har fold da qaytadan hisoblanadi.
Hammasi birga: halol hisobot
natijalar = [ ("Boshlang'ich (7 xususiyat)", baza_ball), ("+ nisbatlar", b1), ("+ guruhlash (binning)", b3), ("+ o'zaro ta'sir", b4), ("+ guruh stat (Pipeline ichida)", b5_toza), ] qatorlar = [] for nom, b in natijalar: qatorlar.append({"Variant": nom, "CV F1": round(b.mean(), 4), "±": round(b.std(), 4), "boshlang'ichdan": round(b.mean() - baza_ball.mean(), 4)}) show(pd.DataFrame(qatorlar)) print() tarqalish = max(b.std() for _, b in natijalar) eng = max(natijalar, key=lambda x: x[1].mean()) print(f"Eng baland: {eng[0]} ({eng[1].mean():.4f})") print(f"Eng katta tarqalish: ±{tarqalish:.4f}") print(f"Hukm: {'farq tarqalishdan KATTA' if eng[1].mean()-baza_ball.mean() > tarqalish else 'farq tarqalish ICHIDA — xususiyatlar sezilarli foyda bermadi'}")
Eng baland: + guruh stat (Pipeline ichida) (0.7400) Eng katta tarqalish: ±0.0191 Hukm: farq tarqalish ICHIDA — xususiyatlar sezilarli foyda bermadi
| Variant | CV F1 | ± | boshlang'ichdan |
|---|---|---|---|
| Boshlang'ich (7 xususiyat) | 0.727 | 0.012 | 0 |
| + nisbatlar | 0.728 | 0.011 | 0 |
| + guruhlash (binning) | 0.727 | 0.01 | -0 |
| + o'zaro ta'sir | 0.727 | 0.013 | -0.001 |
| + guruh stat (Pipeline ichida) | 0.74 | 0.019 | 0.013 |
Xususiyat muhandisligi — ko'pincha ishlamaydi
Yuqoridagi jadval halol natija. Bizning ma'lumotda qo'shilgan xususiyatlar sezilarli foyda bermadi.
Bu normal. Kaggle da yetakchilar ham o'nlab xususiyat sinab, bir-ikkitasini qoldiradi.
Shuning uchun tartib muhim: 1. Bitta xususiyat qo'shing 2. CV bilan o'lchang 3. Tarqalish bilan solishtiring (9-bob) 4. Foyda bermasa tashlang — "balki keyin kerak bo'lar" deb qoldirmang
Har bir keraksiz ustun o'qitishni sekinlashtiradi va overfitting xavfini oshiradi.
Xususiyat tanlash: uch oila
Ko'p xususiyat bo'lsa, keraksizini qanday topamiz?
r = np.random.default_rng(42) sh = pd.DataFrame(r.normal(size=(len(X), 40)), columns=[f"shovqin_{i}" for i in range(40)], index=X.index) X_kop = pd.concat([X[son], sh], axis=1) print(f"Xususiyatlar: {len(son)} haqiqiy + 40 shovqin = {X_kop.shape[1]}") print() show(pd.DataFrame([ {"Oila": "Filter", "Qanday ishlaydi": "Statistika bilan baholaydi, modelsiz", "sklearn": "SelectKBest, VarianceThreshold", "Tezlik": "Juda tez"}, {"Oila": "Wrapper", "Qanday ishlaydi": "Modelni qayta-qayta o'qitib sinaydi", "sklearn": "RFE, RFECV", "Tezlik": "Sekin"}, {"Oila": "Embedded", "Qanday ishlaydi": "Model o'qitish paytida o'zi tanlaydi", "sklearn": "Lasso, daraxt muhimligi", "Tezlik": "Tez (bepul)"}, ]))
Xususiyatlar: 7 haqiqiy + 40 shovqin = 47
| Oila | Qanday ishlaydi | sklearn | Tezlik |
|---|---|---|---|
| Filter | Statistika bilan baholaydi, modelsiz | SelectKBest, VarianceThreshold | Juda tez |
| Wrapper | Modelni qayta-qayta o'qitib sinaydi | RFE, RFECV | Sekin |
| Embedded | Model o'qitish paytida o'zi tanlaydi | Lasso, daraxt muhimligi | Tez (bepul) |
from sklearn.feature_selection import SelectKBest, f_classif, RFE from sklearn.ensemble import RandomForestClassifier import time def oddiy_quvur(sel=None, model=None): # DIQQAT: imputer BIRINCHI bo'lishi kerak — SelectKBest NaN qabul qilmaydi qadamlar = [("i", SimpleImputer(strategy="median")), ("sc", StandardScaler())] if sel is not None: qadamlar.append(("sel", sel)) qadamlar.append(("m", model or LogisticRegression(max_iter=3000))) return Pipeline(qadamlar) print(f"{'usul':<34} {'CV F1':>9} {'±':>8} {'vaqt':>8}") print("-" * 62) for nom, sel in [ ("Tanlovsiz (47 xususiyat)", None), ("Filter: SelectKBest(k=7)", SelectKBest(f_classif, k=7)), ("Wrapper: RFE(n=7)", RFE(LogisticRegression(max_iter=2000), n_features_to_select=7)), ]: t0 = time.perf_counter() b = cross_val_score(oddiy_quvur(sel), X_kop, y, cv=5, scoring="f1") dt = time.perf_counter() - t0 print(f"{nom:<34} {b.mean():>9.4f} {b.std():>8.4f} {dt:>7.1f}s")
usul CV F1 ± vaqt -------------------------------------------------------------- Tanlovsiz (47 xususiyat) 0.7021 0.0156 0.0s Filter: SelectKBest(k=7) 0.7272 0.0140 0.0s Wrapper: RFE(n=7) 0.7130 0.0129 0.3s
# tanlov HAQIQIY xususiyatlarni topdimi? Xk_toza = SimpleImputer(strategy="median").fit_transform(X_kop) sel = SelectKBest(f_classif, k=7).fit(StandardScaler().fit_transform(Xk_toza), y) tanlangan = X_kop.columns[sel.get_support()].tolist() haqiqiy = [t for t in tanlangan if not t.startswith("shovqin")] print(f"SelectKBest 7 ta tanladi: {tanlangan}") print(f" shundan haqiqiy: {len(haqiqiy)} / 7") print() rfe = RFE(LogisticRegression(max_iter=2000), n_features_to_select=7).fit( StandardScaler().fit_transform(Xk_toza), y) t_rfe = X_kop.columns[rfe.get_support()].tolist() print(f"RFE 7 ta tanladi: {t_rfe}") print(f" shundan haqiqiy: {len([t for t in t_rfe if not t.startswith('shovqin')])} / 7")
SelectKBest 7 ta tanladi: ['xonalar', 'maydon_m2', 'qurilgan_yil', 'shovqin_5', 'shovqin_8', 'shovqin_26', 'shovqin_28'] shundan haqiqiy: 3 / 7 RFE 7 ta tanladi: ['xonalar', 'maydon_m2', 'qavat', 'qavatlar_soni', 'shovqin_8', 'shovqin_13', 'shovqin_26'] shundan haqiqiy: 4 / 7
Xususiyat tanlash Pipeline ICHIDA bo'lishi kerak
Eng ko'p uchraydigan leakage shakli:
sel = SelectKBest(k=10).fit(X, y) # BUTUN ma'lumotda — y ni ko'rdi! X_tanlangan = sel.transform(X) cross_val_score(model, X_tanlangan, y, cv=5) # natija YOLG'ON
Tanlov y ni ko'rib ustun tanladi, keyin CV o'sha tanlovni sinaydi. Natija optimistik.
To'g'ri yo'l — yuqoridagi kodda: Pipeline([("sel", SelectKBest(...)), ("m", model)]). Shunda tanlov har fold da qaytadan bajariladi.
Pipeline da QADAMLAR TARTIBI muhim
Bu blokni birinchi yozganimda SimpleImputer ni qo'ymagandim, va build shunday xato bilan to'xtadi:
ValueError: Input X contains NaN. SelectKBest does not accept missing values encoded as NaN natively.
Sababi: qurilgan_yil ustunida 8 ta bo'sh qiymat bor (0-bob), va SelectKBest ularni qabul qilmaydi.
To'g'ri tartib: to'ldirish -> shkalalash -> tanlash -> model. Har bir qadam o'zidan oldingisining chiqishini kutadi.
Qoida: yangi qadam qo'shganda o'zingizdan so'rang — "bu qadam NaN ni eplaydimi?" Daraxtlar eplaydi, qolgan ko'pchilik eplamaydi.
Bugun nima o'rgandik
show(pd.DataFrame([ {"Usul": "Nisbat va ayirma", "Kimga foydali": "Chiziqli modelga", "Diqqat": "Daraxt o'zi topadi"}, {"Usul": "Sanani parchalash", "Kimga foydali": "Hammaga", "Diqqat": "Sanani son qilib bermang"}, {"Usul": "Binning", "Kimga foydali": "Chiziqli modelga", "Diqqat": "Ma'lumot yo'qoladi"}, {"Usul": "O'zaro ta'sir", "Kimga foydali": "Chiziqli modelga", "Diqqat": "Daraxt o'zi topadi"}, {"Usul": "Guruh statistikasi", "Kimga foydali": "Hammaga — eng kuchli", "Diqqat": "LEAKAGE xavfi eng yuqori"}, {"Usul": "Filter tanlov", "Kimga foydali": "Tez skrining", "Diqqat": "Modelni hisobga olmaydi"}, {"Usul": "Wrapper (RFE)", "Kimga foydali": "Aniq tanlov", "Diqqat": "Sekin"}, {"Usul": "Embedded (Lasso)", "Kimga foydali": "Bepul (16-bob)", "Diqqat": "alpha ni topish kerak"}, ]))
| Usul | Kimga foydali | Diqqat |
|---|---|---|
| Nisbat va ayirma | Chiziqli modelga | Daraxt o'zi topadi |
| Sanani parchalash | Hammaga | Sanani son qilib bermang |
| Binning | Chiziqli modelga | Ma'lumot yo'qoladi |
| O'zaro ta'sir | Chiziqli modelga | Daraxt o'zi topadi |
| Guruh statistikasi | Hammaga — eng kuchli | LEAKAGE xavfi eng yuqori |
| Filter tanlov | Tez skrining | Modelni hisobga olmaydi |
| Wrapper (RFE) | Aniq tanlov | Sekin |
| Embedded (Lasso) | Bepul (16-bob) | alpha ni topish kerak |
Asosiy qoida: bitta o'zgarish, o'lchash, tarqalish bilan solishtirish. Va foyda bermasa — tashlash.
Keyingi bobda: modelning sozlamalarini qanday tanlaymiz?
Bu bobni bepul o'qidingiz.
Kitob o'rgatadi, lekin sizning kodingiz nega ishlamaganini ayta olmaydi. Kursda uy vazifangiz tekshiriladi.