Mundarija (22)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Belgi turlari
- 2.2. Yaxshi belgi nimasi bilan yaxshi
- 2.3. Model va belgi mosligi
- 2.4. Belgi yaratish manbalari
- 2.5. Leakage xavfi
- 2.6. Baholash tartibi
- 2.7. Tuzoqlar
- 2.8. Belgi — modeldan muhimroq
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — Belgi turlarini aniqlash
- Misol 2 — Yaxshi belgi natijani qanday o'zgartiradi
- Misol 3 — Model va belgi mosligi
- Misol 4 — Leakage ni aniqlash
- 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
17.1-dars: Feature nima
17-QISM — FEATURE ENGINEERING · 1-dars
1. Kirish va motivatsiya
Modellar haqida ko'p gapirdik, lekin amaliyotdagi haqiqat boshqacha: model tanlash natijaning kichik qismini belgilaydi, belgilar esa kattasini. Bir xil ma'lumotda yaxshi belgilar bilan logistik regressiya, yomon belgilar bilan gradient boostingdan ustun chiqishi mumkin.
Belgi (feature) — modelga beriladigan har bir kirish o'zgaruvchisi. Feature engineering esa xom ma'lumotni modelga tushunarli shaklga keltirish: yangi belgilar yaratish, mavjudlarini o'zgartirish, keraksizlarini olib tashlash.
Bu — ma'lumot tahlilidagi eng domenga bog'liq qism: "oxirgi xariddan o'tgan kunlar" degan belgi hech qanday algoritmdan kelib chiqmaydi, u biznesni tushunishdan tug'iladi.
Bu darsda: belgi turlari, yaxshi belgi nimasi bilan yaxshi, modelning induktiv siljishi bilan bog'liqlik, belgi yaratishning asosiy manbalari, leakage xavfi va baholash tartibi.
Real vaziyat. Kredit skoringida jamoa uch hafta gradient boostingni sozladi — AUC 0.741 dan 0.748 ga ko'tarildi. Keyin bitta belgi qo'shildi: "so'nggi 3 oydagi kechikishlar soni / umumiy to'lovlar soni". AUC 0.783 ga chiqdi. Bitta belgi uch haftalik sozlashdan besh barobar ko'p berdi.
Bu darsda belgi tushunchasini o'rganamiz.
Bu darsda:
- Belgi turlari
- Yaxshi belgi nimasi bilan yaxshi
- Model va belgi mosligi
- Belgi yaratish manbalari
- Leakage xavfi
- Baholash tartibi
- Tuzoqlar
- Amaliy: birinchi belgilar
ℹ Misollar real numpy/pandas/sklearn bilan (Python 3.14).
2. Nazariya — chuqur tushuntirish
2.1. Belgi turlari
SONLI (numerical):
uzluksiz - narx, harorat, masofa
diskret - xaridlar soni, xonalar soni
KATEGORIYALI (categorical):
nominal - hudud, rang, kanal (tartib yo'q)
ordinal - daraja (boshlang'ich < o'rta < yuqori) - TARTIB bor
IKKILIK (binary): ha/yo'q, erkak/ayol
VAQT: sana, vaqt belgisi, davomiylik
MATN: erkin matn, kategoriya nomi, izoh
MAXSUS: geografik (koordinata), tasvir, grafik, ketma-ketlik
Har tur uchun O'Z tayyorlash usuli bor (17.2-17.6) Ordinal va nominalni ajratish muhim: ordinalga OrdinalEncoder (tartib saqlanadi), nominalga OneHotEncoder. Nominal belgiga tasodifiy raqam berish — modelga yolg'on tartib o'rgatadi.
2.2. Yaxshi belgi nimasi bilan yaxshi
1. MA'LUMOTLI: maqsad bilan bog'liq (lekin sabab bo'lishi shart emas)
2. MAVJUD: bashorat vaqtida ma'lum bo'ladi (leakage yo'q)
3. BARQAROR: vaqt o'tishi bilan ma'nosi o'zgarmaydi
4. TUSHUNARLI: nima ekanini tushuntirish mumkin
5. ARZON: hisoblash va yig'ish narxi oqlanadi
6. TOZA: yo'qolgan qiymatlar va xatolar kam
QO'SHIMCHA: model turiga MOS
chiziqli model -> chiziqlilashtirilgan belgilar kerak
daraxtlar -> monoton transformatsiyalar keraksiz (15.1)"Mavjud" sharti eng ko'p buziladi: o'quv ma'lumotida bor bo'lgan belgi ishlab chiqarishda bashorat vaqtida mavjud bo'lmasligi mumkin. Har belgi uchun "bu qachon ma'lum bo'ladi?" degan savolni bering.
2.3. Model va belgi mosligi
Chiziqli model Daraxtlar/ansambllar
masshtablash MAJBURIY keraksiz
log/kvadrat ko'pincha zarur keraksiz (monoton)
o'zaro ta'sir QO'LDA qo'shiladi o'zi topadi
one-hot majburiy ko'pincha kerak (yoki ichki)
chetlanishlar juda ta'sirchan chidamli
yo'qolgan qiymat to'ldirish kerak Hist*/XGB o'zi boshqaradi
XULOSA: bir xil ma'lumot uchun TURLI belgilar to'plami kerak bo'lishi mumkin Daraxtlar log(x) dan foyda ko'rmaydi, chiziqli model esa ko'radi. Belgi muhandisligi modeldan ajralmagan: qaysi modelni ishlatishingizni bilmasdan optimal belgilar to'plamini tuzib bo'lmaydi.
2.4. Belgi yaratish manbalari
1. DOMEN BILIMI - eng qimmatli manba
"yuk og'irligi / masofa" nisbati, "hafta oxiri" bayrog'i
2. AGREGATSIYA - guruh bo'yicha statistika (7-qism)
mijozning o'rtacha cheki, hududning medianasi
3. NISBAT va FARQ - ikki belgi kombinatsiyasi
narx / maydon, joriy / o'rtacha
4. VAQT - sana komponentlari, oynalar, lag lar 17.5-bob
hafta kuni, oxirgi hodisadan o'tgan vaqt
5. MATN - uzunlik, so'zlar soni, TF-IDF 17.6-bob
6. NAZORATSIZ - klaster, PCA, anomaliya bali 16.11-bob
7. TASHQI - ob-havo, bayramlar, valyuta kursi Nisbatlar — eng arzon va eng ko'p ishlaydigan usul: xarajat/daromad, kechikish/to'lovlar, narx/maydon. Ular modelga bitta belgida kontekst beradi.
2.5. Leakage xavfi
LEAKAGE - maqsad haqidagi ma'lumot belgiga "sizib kirishi" 12.9-bob
Ikki tur:
1. MAQSAD leakage: belgi maqsaddan hosil bo'lgan
"to'lov summasi" - defolt bo'lgan mijozda 0
"chegirma berildi" - buyurtma bekor qilingandan keyin
2. VAQT leakage: belgi bashorat vaqtida hali ma'lum emas
"umumiy xaridlar soni" (butun davr bo'yicha)
"keyingi oydagi faollik"
TEKSHIRUV:
- belgi AJOYIB ishlayapti (AUC 0.99) -> shubhalaning
- "bu qachon ma'lum bo'ladi?" savolini bering
- vaqt bo'yicha validatsiya qiling"Juda yaxshi natija" — leakage ning asosiy belgisi. AUC 0.98 chiqsa, avval quvonmang, tekshiring: real vazifalarda bunday natija kamdan-kam bo'ladi.
2.6. Baholash tartibi
Har yangi belgi uchun:
1. BAZAVIY natijani qayd eting (belgilarsiz)
2. Belgini QO'SHING va CV da o'lchang
3. Yaxshilanish CV STD dan katta ekanini tekshiring
4. Leakage yo'qligini tekshiring
5. Ishlab chiqarishda hisoblash mumkinligini tasdiqlang
QO'SHIMCHA:
- belgilar GURUHI bo'lib qo'shiladi (bitta-bitta emas)
- permutation importance bilan tekshiring 15.11-bob
- keraksizlarini olib tashlang (17.7)Yaxshilanishni CV standart og'ishi bilan solishtiring 15.14-bob: 0.002 lik "yaxshilanish" std 0.008 bo'lsa — shovqin, belgi emas.
2.7. Tuzoqlar
Asosiy tuzoqlar: nominal belgiga tartib berish; leakage ni tekshirmaslik; belgini modelga moslamaslik (daraxtga log); yaxshilanishni CV std bilan solishtirmaslik; belgi ishlab chiqarishda hisoblanishini tekshirmaslik; juda ko'p belgi yaratib, tanlashni unutish; domen bilimini e'tiborsiz qoldirib, faqat avtomatik usullarga tayanish; tayyorlashni Pipeline tashqarisida qilish.
2.8. Belgi — modeldan muhimroq
Belgi — modelga beriladigan har bir kirish; feature engineering — xom ma'lumotni modelga tushunarli shaklga keltirish. Yaxshi belgi ma'lumotli, bashorat vaqtida mavjud, barqaror va tushunarli bo'ladi. Belgi modeldan ajralmagan: chiziqli modelga masshtablash va chiziqlilashtirish kerak, daraxtlarga esa yo'q. Eng qimmatli manba — domen bilimi, eng katta xavf — leakage. Keyingi dars — belgi yaratish.
3. Tez ma'lumotnoma
import numpy as np
import pandas as pd
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import OneHotEncoder, OrdinalEncoder, StandardScaler
df.dtypes # belgi turlarini ko'rish
df.select_dtypes(include="number").columns
df.select_dtypes(include=["object", "category"]).columns
df.nunique() # kardinallik
tayyor = ColumnTransformer([
("nominal", OneHotEncoder(handle_unknown="ignore",
sparse_output=False), nominal),
("ordinal", OrdinalEncoder(categories=[["past", "o_rta", "yuqori"]]), ordinal),
("sonli", StandardScaler(), sonli)])
Pipeline([("t", tayyor), ("m", model)])
QOIDA: turni aniqla · leakage ni tekshir · modelga mosla ·
CV std bilan solishtirBelgi xulosasi
Turlar: sonli, kategoriyali (nominal/ordinal), ikkilik, vaqt, matn
Yaxshi belgi: ma'lumotli, mavjud, barqaror, tushunarli, arzon
Model va belgi bog'liq: chiziqli != daraxt
Eng katta xavf: leakage ("juda yaxshi natija" - shubhali)4. Batafsil misollar
Misollar real numpy/pandas/sklearn bilan (Python 3.14).
Misol 1 — Belgi turlarini aniqlash
"""Xom ma'lumotdan belgi turlarini ajratish (real pandas/sklearn)."""
import numpy as np
import pandas as pd
def yarat(seed: int = 7, n: int = 2000) -> pd.DataFrame:
"""Aralash turdagi belgilar."""
rng = np.random.default_rng(seed)
sanalar = pd.to_datetime("2025-01-01") + pd.to_timedelta(
rng.integers(0, 540, n), unit="D")
return pd.DataFrame({
"buyurtma_id": np.arange(100000, 100000 + n),
"sana": sanalar,
"hudud": rng.choice(["toshkent", "samarqand", "buxoro", "fargona"], n),
"daraja": rng.choice(["oddiy", "kumush", "oltin", "platina"], n,
p=[0.5, 0.3, 0.15, 0.05]),
"yetkazish": rng.choice(["tezkor", "oddiy"], n, p=[0.3, 0.7]),
"summa": rng.lognormal(12.5, 0.7, n),
"mahsulotlar": rng.integers(1, 12, n),
"izoh": rng.choice(["", "tezroq yetkazing", "sovg'a qog'ozi",
"qo'ng'iroq qilmang"], n, p=[0.7, 0.1, 0.1, 0.1]),
"kechikdi": rng.integers(0, 2, n),
})
def turlarni_aniqla(df: pd.DataFrame, id_ustunlar=(), maqsad="") -> dict:
"""Ustunlarni turlarga ajratadi."""
natija = {"id": [], "vaqt": [], "sonli": [], "kategoriyali": [],
"ikkilik": [], "matn": [], "maqsad": []}
for ustun in df.columns:
seriya = df[ustun]
if ustun == maqsad:
natija["maqsad"].append(ustun)
elif ustun in id_ustunlar:
natija["id"].append(ustun)
elif pd.api.types.is_datetime64_any_dtype(seriya):
natija["vaqt"].append(ustun)
elif pd.api.types.is_numeric_dtype(seriya):
if seriya.nunique() == 2:
natija["ikkilik"].append(ustun)
else:
natija["sonli"].append(ustun)
elif seriya.nunique() > 0.3 * len(seriya):
natija["matn"].append(ustun)
elif seriya.nunique() == 2:
natija["ikkilik"].append(ustun)
else:
natija["kategoriyali"].append(ustun)
return natija
def main() -> None:
df = yarat()
print("=== 1. Ustunlar va ularning turlari ===")
print(f" {'ustun':<14} {'dtype':<16} {'noyob':>7} {'yo_qolgan':>10}")
for ustun in df.columns:
print(f" {ustun:<14} {str(df[ustun].dtype):<16} "
f"{df[ustun].nunique():>7} {int(df[ustun].isna().sum()):>10}")
print("\n=== 2. Avtomatik tasniflash ===")
turlar = turlarni_aniqla(df, id_ustunlar=["buyurtma_id"],
maqsad="kechikdi")
for tur, ustunlar in turlar.items():
if ustunlar:
print(f" {tur:<14}: {ustunlar}")
print("\n=== 3. Kardinallik tahlili ===")
kategoriyali = turlar["kategoriyali"] + turlar["ikkilik"]
print(f" {'ustun':<14} {'darajalar':>10} {'ulush':>8} {'tavsiya':<22}")
for ustun in kategoriyali:
if not pd.api.types.is_numeric_dtype(df[ustun]):
k = df[ustun].nunique()
ulush = k / len(df)
tavsiya = ("OneHot" if k <= 15
else "Target/Frequency encoding")
print(f" {ustun:<14} {k:>10} {ulush:>7.2%} {tavsiya:<22}")
print("\n=== 4. Ordinal va nominalni ajratish ===")
print(f" daraja qiymatlari: {sorted(df['daraja'].unique())}")
print(f" hudud qiymatlari: {sorted(df['hudud'].unique())}")
print(" daraja -> ORDINAL (oddiy < kumush < oltin < platina)")
print(" hudud -> NOMINAL (tartib yo'q)")
tartib = ["oddiy", "kumush", "oltin", "platina"]
kod = {nom: i for i, nom in enumerate(tartib)}
df["daraja_kod"] = df["daraja"].map(kod)
print(f" daraja_kod va summa korrelyatsiyasi: "
f"{df['daraja_kod'].corr(df['summa']):.4f}")
# nominal uchun tasodifiy raqam berilsa nima bo'ladi
tasodifiy_kod = {h: i for i, h in enumerate(sorted(df["hudud"].unique()))}
df["hudud_kod"] = df["hudud"].map(tasodifiy_kod)
print(f" hudud_kod va summa korrelyatsiyasi: "
f"{df['hudud_kod'].corr(df['summa']):.4f} (ma'nosiz)")
print(" ⭐ Ordinalga tartib, nominalga one-hot")
if __name__ == "__main__":
main()Natijaning muhim qismi:
<<NATIJA>>Nima ko'rsatdi: 2.1-bo'lim.
Misol 2 — Yaxshi belgi natijani qanday o'zgartiradi
"""Bitta belgi sozlashdan ko'ra ko'proq beradi (real pandas/sklearn)."""
import numpy as np
import pandas as pd
from sklearn.ensemble import HistGradientBoostingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import StratifiedKFold, cross_val_score
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
def yarat(seed: int = 11, n: int = 6000) -> pd.DataFrame:
"""Kredit: risk NISBATLARDA yashiringan, xom qiymatlarda emas."""
rng = np.random.default_rng(seed)
daromad = rng.lognormal(14.2, 0.55, n)
qarz = daromad * rng.lognormal(-0.6, 0.6, n)
tolovlar = rng.integers(6, 60, n)
kechikishlar = rng.binomial(tolovlar, rng.beta(1.5, 12, n))
kredit_summa = daromad * rng.lognormal(0.5, 0.5, n)
# HAQIQIY risk: nisbatlarga bog'liq
kuch = (-1.2 + 2.6 * (qarz / daromad) + 4.0 * (kechikishlar / tolovlar)
+ 1.1 * (kredit_summa / daromad) - 0.3)
y = (rng.random(n) < 1 / (1 + np.exp(-kuch))).astype(int)
return pd.DataFrame({"daromad": daromad, "qarz": qarz,
"tolovlar": tolovlar, "kechikishlar": kechikishlar,
"kredit_summa": kredit_summa, "defolt": y})
def main() -> None:
df = yarat()
y = df["defolt"].to_numpy()
cv = StratifiedKFold(5, shuffle=True, random_state=0)
print("=== 1. Ma'lumot ===")
print(f" {len(df)} ariza, defolt ulushi {y.mean():.2%}")
xom = ["daromad", "qarz", "tolovlar", "kechikishlar", "kredit_summa"]
print("\n=== 2. Xom belgilar bilan ===")
modellar = {
"LogReg": Pipeline([("sc", StandardScaler()),
("m", LogisticRegression(max_iter=2000))]),
"HistGB": HistGradientBoostingClassifier(learning_rate=0.1,
max_iter=200,
random_state=0),
}
asos = {}
print(f" {'model':<10} {'CV ROC AUC':>12} {'std':>8}")
for nom, m in modellar.items():
b = cross_val_score(m, df[xom], y, cv=cv, scoring="roc_auc")
asos[nom] = (b.mean(), b.std())
print(f" {nom:<10} {b.mean():>12.4f} {b.std():>8.4f}")
print("\n=== 3. Nisbat belgilarini qo'shish ===")
df["qarz_nisbati"] = df["qarz"] / df["daromad"]
df["kechikish_ulushi"] = df["kechikishlar"] / df["tolovlar"]
df["kredit_nisbati"] = df["kredit_summa"] / df["daromad"]
yangi = xom + ["qarz_nisbati", "kechikish_ulushi", "kredit_nisbati"]
print(f" {'model':<10} {'CV ROC AUC':>12} {'std':>8} {'yaxshilanish':>14}")
for nom, m in modellar.items():
b = cross_val_score(m, df[yangi], y, cv=cv, scoring="roc_auc")
print(f" {nom:<10} {b.mean():>12.4f} {b.std():>8.4f} "
f"{b.mean() - asos[nom][0]:>+14.4f}")
print("\n=== 4. Faqat nisbatlar bilan ===")
faqat = ["qarz_nisbati", "kechikish_ulushi", "kredit_nisbati"]
print(f" {'model':<10} {'belgilar':>9} {'CV ROC AUC':>12}")
for nom, m in modellar.items():
b = cross_val_score(m, df[faqat], y, cv=cv, scoring="roc_auc")
print(f" {nom:<10} {len(faqat):>9} {b.mean():>12.4f}")
print(f" (xom belgilar bilan: LogReg {asos['LogReg'][0]:.4f}, "
f"HistGB {asos['HistGB'][0]:.4f})")
print(" ⭐ 3 ta to'g'ri belgi 5 ta xom belgidan yaxshiroq")
if __name__ == "__main__":
main()Natijaning muhim qismi:
<<NATIJA>>Nima ko'rsatdi: 2.2, 2.4-bo'limlar.
Misol 3 — Model va belgi mosligi
"""Bir xil belgi turli modelga turlicha ta'sir qiladi (real numpy/sklearn)."""
import numpy as np
from sklearn.ensemble import HistGradientBoostingClassifier, RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import StratifiedKFold, cross_val_score
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
def yarat(seed: int = 5, n: int = 5000):
"""Maqsad log(x) va o'zaro ta'sirga bog'liq."""
rng = np.random.default_rng(seed)
a = rng.lognormal(10, 1.2, n) # juda qiyshiq
b = rng.uniform(0, 1, n)
c = rng.normal(0, 1, n)
kuch = 0.8 * (np.log(a) - 10) + 2.5 * (b * c) - 0.5
y = (rng.random(n) < 1 / (1 + np.exp(-kuch))).astype(int)
return np.column_stack([a, b, c]), y
def main() -> None:
X, y = yarat()
cv = StratifiedKFold(5, shuffle=True, random_state=0)
modellar = {
"LogReg": lambda: Pipeline([("sc", StandardScaler()),
("m", LogisticRegression(max_iter=2000))]),
"RandomForest": lambda: RandomForestClassifier(n_estimators=200,
random_state=0,
n_jobs=1),
"HistGB": lambda: HistGradientBoostingClassifier(learning_rate=0.1,
max_iter=200,
random_state=0),
}
print("=== 1. Xom belgilar ===")
asos = {}
print(f" {'model':<14} {'CV ROC AUC':>12} {'std':>8}")
for nom, yaratuvchi in modellar.items():
b = cross_val_score(yaratuvchi(), X, y, cv=cv, scoring="roc_auc")
asos[nom] = b.mean()
print(f" {nom:<14} {b.mean():>12.4f} {b.std():>8.4f}")
print("\n=== 2. log transformatsiyasi qo'shilgandan keyin ===")
Xlog = np.column_stack([X, np.log1p(X[:, 0])])
print(f" {'model':<14} {'CV ROC AUC':>12} {'o_zgarish':>12}")
for nom, yaratuvchi in modellar.items():
b = cross_val_score(yaratuvchi(), Xlog, y, cv=cv, scoring="roc_auc")
print(f" {nom:<14} {b.mean():>12.4f} {b.mean() - asos[nom]:>+12.4f}")
print(" (chiziqli model foyda ko'radi, daraxtlar - deyarli yo'q)")
print("\n=== 3. O'zaro ta'sir qo'shilgandan keyin ===")
Xoz = np.column_stack([X, X[:, 1] * X[:, 2]])
print(f" {'model':<14} {'CV ROC AUC':>12} {'o_zgarish':>12}")
for nom, yaratuvchi in modellar.items():
b = cross_val_score(yaratuvchi(), Xoz, y, cv=cv, scoring="roc_auc")
print(f" {nom:<14} {b.mean():>12.4f} {b.mean() - asos[nom]:>+12.4f}")
print(" (chiziqli model katta foyda, daraxtlar o'zi topgan edi)")
print("\n=== 4. Ikkalasi birga ===")
Xhammasi = np.column_stack([X, np.log1p(X[:, 0]), X[:, 1] * X[:, 2]])
print(f" {'model':<14} {'xom':>9} {'to_liq':>9} {'o_zgarish':>12}")
for nom, yaratuvchi in modellar.items():
b = cross_val_score(yaratuvchi(), Xhammasi, y, cv=cv,
scoring="roc_auc")
print(f" {nom:<14} {asos[nom]:>9.4f} {b.mean():>9.4f} "
f"{b.mean() - asos[nom]:>+12.4f}")
print(" ⭐ Belgi muhandisligi modeldan ajralmagan")
if __name__ == "__main__":
main()Natijaning muhim qismi:
<<NATIJA>>Nima ko'rsatdi: 2.3-bo'lim.
Misol 4 — Leakage ni aniqlash
"""Ikki turdagi leakage va ularni topish (real pandas/sklearn)."""
import numpy as np
import pandas as pd
from sklearn.ensemble import HistGradientBoostingClassifier
from sklearn.inspection import permutation_importance
from sklearn.model_selection import StratifiedKFold, cross_val_score, train_test_split
def yarat(seed: int = 3, n: int = 5000) -> pd.DataFrame:
"""Buyurtma bekor qilinishi; ikkita leakage belgisi bor."""
rng = np.random.default_rng(seed)
summa = rng.lognormal(12.0, 0.6, n)
masofa = rng.gamma(3, 50, n)
mijoz_yoshi = rng.integers(18, 70, n)
kanal = rng.integers(0, 3, n)
kuch = -1.5 + 0.4 * (summa > np.quantile(summa, 0.8)) + 0.004 * masofa \
- 0.01 * mijoz_yoshi + 0.3 * (kanal == 2)
bekor = (rng.random(n) < 1 / (1 + np.exp(-kuch))).astype(int)
# LEAKAGE 1 (maqsad): qaytarish summasi - faqat bekor qilinganda > 0
qaytarish = np.where(bekor == 1, summa * rng.uniform(0.9, 1.0, n), 0.0)
# LEAKAGE 2 (vaqt): yetkazish vaqti - bekor qilinganda yo'q
yetkazish_vaqti = np.where(bekor == 1, np.nan,
masofa / 30 + rng.normal(0, 5, n))
return pd.DataFrame({"summa": summa, "masofa": masofa,
"mijoz_yoshi": mijoz_yoshi, "kanal": kanal,
"qaytarish": qaytarish,
"yetkazish_vaqti": yetkazish_vaqti,
"bekor": bekor})
def main() -> None:
df = yarat()
y = df["bekor"].to_numpy()
cv = StratifiedKFold(5, shuffle=True, random_state=0)
def model():
return HistGradientBoostingClassifier(learning_rate=0.1, max_iter=200,
random_state=0)
print("=== 1. Barcha belgilar bilan ===")
hammasi = ["summa", "masofa", "mijoz_yoshi", "kanal", "qaytarish",
"yetkazish_vaqti"]
b = cross_val_score(model(), df[hammasi], y, cv=cv, scoring="roc_auc")
print(f" CV ROC AUC: {b.mean():.4f} (+-{b.std():.4f})")
print(" SHUBHA: real vazifada 0.99 deyarli bo'lmaydi")
print("\n=== 2. Har belgining yakka natijasi ===")
print(f" {'belgi':<18} {'yakka CV AUC':>14}")
for belgi in hammasi:
Xb = df[[belgi]].to_numpy()
bb = cross_val_score(model(), Xb, y, cv=cv, scoring="roc_auc").mean()
belgisi = " <- SHUBHALI" if bb > 0.9 else ""
print(f" {belgi:<18} {bb:>14.4f}{belgisi}")
print("\n=== 3. Leakage belgilarining tabiati ===")
print(f" qaytarish > 0 bo'lgan qatorlar: "
f"{(df['qaytarish'] > 0).mean():.2%}")
print(f" ulardan bekor qilinganlari: "
f"{df.loc[df['qaytarish'] > 0, 'bekor'].mean():.2%}")
print(f" yetkazish_vaqti NaN bo'lgan qatorlar: "
f"{df['yetkazish_vaqti'].isna().mean():.2%}")
print(f" ulardan bekor qilinganlari: "
f"{df.loc[df['yetkazish_vaqti'].isna(), 'bekor'].mean():.2%}")
print(" (ikkalasi ham maqsaddan KEYIN aniqlanadi)")
print("\n=== 4. Leakage siz halol natija ===")
toza = ["summa", "masofa", "mijoz_yoshi", "kanal"]
bt = cross_val_score(model(), df[toza], y, cv=cv, scoring="roc_auc")
print(f" leakage bilan: {b.mean():.4f}")
print(f" leakage siz: {bt.mean():.4f} (+-{bt.std():.4f})")
print(f" farq: {b.mean() - bt.mean():+.4f}")
Xtr, Xte, ytr, yte = train_test_split(df[hammasi], y, test_size=0.3,
random_state=0, stratify=y)
m = model().fit(Xtr, ytr)
r = permutation_importance(m, Xte, yte, n_repeats=10, scoring="roc_auc",
random_state=0, n_jobs=1)
print(f" {'belgi':<18} {'permutation muhimligi':>23}")
for i in np.argsort(-r.importances_mean):
print(f" {hammasi[i]:<18} {r.importances_mean[i]:>+23.4f}")
print(" ⭐ 'Juda yaxshi natija' - leakage ning asosiy belgisi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
<<NATIJA>>Nima ko'rsatdi: 2.5, 2.6-bo'limlar.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
| "Model tanlash eng muhim" | Belgilar ko'pincha muhimroq |
| "Kategoriyaga raqam berish yetarli" | Nominal uchun one-hot |
| "Belgi model turiga bog'liq emas" | Juda bog'liq |
| "Daraxtlarga log foydali" | Monoton — ta'sir qilmaydi |
| "Yuqori AUC — yaxshi model" | Leakage bo'lishi mumkin |
| "Ko'proq belgi — yaxshiroq" | Shovqin va overfitting |
| "Avtomatik usullar yetarli" | Domen bilimi hal qiluvchi |
| "Kichik yaxshilanish ham foyda" | CV std bilan solishtiring |
6. Keng tarqalgan xatolar va yechimlari
1. Nominal belgiga tartib berish
df["hudud"] = df["hudud"].map({"toshkent": 0, "samarqand": 1}) # ⚠️
OneHotEncoder(handle_unknown="ignore") # ✅2. Leakage ni tekshirmaslik
# AUC 0.99 - "ajoyib model!" # ⚠️
# har belgining yakka natijasini ko'ring # ✅3. Daraxtga chiziqlilashtirish
X["log_summa"] = np.log1p(X["summa"]) # RandomForest uchun # ⚠️
# daraxtlarga monoton transformatsiya keraksiz # ✅4. Yaxshilanishni std siz baholash
# "0.742 -> 0.744, belgi ishlaydi" # ⚠️
# std 0.008 bo'lsa - bu shovqin # ✅5. Ishlab chiqarishda mavjudlikni tekshirmaslik
X["oxirgi_30_kun_xarid"] = ... # bashoratda hisoblanadi? # ⚠️
# har belgi uchun "qachon ma'lum bo'ladi?" savolini bering # ✅6. Belgilarni Pipeline tashqarisida yaratish
X["nisbat"] = X["a"] / X["b"]; cross_val_score(m, X, y) # ⚠️
# statistikaga tayanadigan belgilar Pipeline ichida bo'lsin # ✅7. Domen bilimisiz avtomatik generatsiya
PolynomialFeatures(degree=3) # 500 ta ma'nosiz belgi # ⚠️
# avval domen belgilarini qo'ying, keyin avtomatik # ✅7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 12.9-dars (o'tilgan): Leakage
- 17.2-dars: Belgi yaratish
- 17.3-dars: Kategoriyali belgilarni kodlash
- 17.7-dars: Feature selection
- 15.11-dars (o'tilgan): Belgi muhimligi
8. Eng yaxshi amaliyotlar
Belgi turlarini aniq ajrating.
Domen bilimidan boshlang.
Leakage ni har doim tekshiring.
Belgini modelga moslang.
CV std bilan solishtiring.
Ishlab chiqarishda mavjudligini tasdiqlang.
Pipeline ichida ishlang.
Keraksizlarini olib tashlang.
9. Amaliy topshiriq
Vazifa 1: Bashorat qiling
1. # belgi nima?
2. # nominal va ordinal farqi?
3. # nominalga qaysi kodlash?
4. # yaxshi belgining olti xossasi?
5. # eng ko'p buziladigan shart?
6. # daraxtlarga log foydalimi?
7. # chiziqli modelga o'zaro ta'sir?
8. # eng qimmatli belgi manbai?
9. # leakage ning ikki turi?
10. # leakage belgisi?
11. # yaxshilanishni nima bilan solishtirish kerak?
12. # belgilar qanday qo'shiladi?Javoblar
- Modelga beriladigan kirish o'zgaruvchisi
- Ordinalda tartib bor
- OneHotEncoder
- Ma'lumotli, mavjud, barqaror, tushunarli, arzon, toza
- Bashorat vaqtida mavjudlik
- Yo'q (monoton)
- Qo'lda qo'shiladi
- Domen bilimi
- Maqsad va vaqt leakage
- Juda yaxshi natija
- CV standart og'ishi
- Guruh bo'lib
Vazifa 2: Xatolarni tuzating
1. df["hudud"] = df["hudud"].map({"toshkent": 0, "samarqand": 1})
2. # AUC 0.99 - "ajoyib model!"
3. X["log_summa"] = np.log1p(X["summa"]) # RandomForest uchun
4. # "0.742 -> 0.744, belgi ishlaydi" (std 0.008)
5. PolynomialFeatures(degree=3) # domen belgilarisizJavoblar
1. OneHotEncoder(handle_unknown="ignore")
2. # har belgining yakka natijasini tekshiring
3. # daraxtlarga monoton transformatsiya keraksiz
4. # bu shovqin, belgi emas
5. # avval domen belgilarini qo'yingVazifa 3: Turlar
Modellang:
- Ustunlar
- Avtomatik tasniflash
- Kardinallik
- Ordinal va nominal
Vazifa 4: Nisbatlar
Modellang:
- Ma'lumot
- Xom belgilar
- Nisbatlar
- Faqat nisbatlar
Vazifa 5: Moslik
Modellang:
- Xom
- log
- O'zaro ta'sir
- Birga
Vazifa 6: Leakage
Modellang:
- Barcha belgilar
- Yakka natijalar
- Tabiati
- Halol natija
Vazifa 7: O'ylash
Zamonaviy modellar (gradient boosting, neyron tarmoqlar) belgilarni "o'zi topadi" deyiladi. Feature engineering hali ham kerakmi?
Javob
Qisqa javob: modellar mavjud belgilardan kombinatsiya topa oladi, lekin yo'q bo'lgan ma'lumotni yarata olmaydi. Feature engineering ikki narsani beradi: tashqi bilim va to'g'ri ko'rinish.
1. Model nimani topa oladi
| Vazifa | Model topa oladimi |
|---|---|
a * b o'zaro ta'siri |
Ha (daraxtlar, NN) |
log(a) |
Ha (daraxtlar — monoton) |
a / b nisbati |
Qiyin (bo'linish daraxtga tabiiy emas) |
| "bayram kuni" | Yo'q (tashqi ma'lumot) |
| "oxirgi 30 kun o'rtachasi" | Yo'q (agregatsiya berilmagan) |
| "manzil koordinatasi" | Yo'q (tashqi manba) |
2. Nisbatlar — eng yaxshi misol
Daraxt qarz/daromad > 0.4 shartini to'g'ridan-to'g'ri ifodalay olmaydi: u faqat o'qlarga parallel chegaralar qo'yadi 15.1-bob. Shuning uchun u bu nisbatni zinapoya bilan taqriblaydi va ko'p bo'linish sarflaydi. Nisbatni belgi sifatida berish darhol yordam beradi — Misol 2 da bu ko'rindi.
3. Deep learning nima o'zgartirdi
- Tasvir, matn, audio: xom ma'lumotdan belgilarni model o'zi o'rganadi — feature engineering deyarli yo'qoldi
- Jadval ma'lumoti: hali ham qo'lda muhandislik ustun; gradient boosting + yaxshi belgilar neyron tarmoqdan yaxshiroq
- Sabab: jadval ma'lumotida namunalar kam va tuzilma heterogen
4. Amaliy taqsimot
Jadval ma'lumoti: feature engineering 60%, model 40%
Tasvir/matn: feature engineering 10%, arxitektura va ma'lumot 90%
Vaqt qatorlari: feature engineering 70% (lag, oyna, mavsum)5. Xulosa
- Model kombinatsiya topadi, tashqi bilim topa olmaydi
- Nisbatlar va agregatsiyalar hali ham qo'lda kerak
- Jadval ma'lumotida feature engineering ustun
- Tasvir/matnda uning o'rni kichraygan
Nimani mustahkamlaydi: 2.3, 2.4-bo'limlar.
Xulosa
Bu darsda belgi tushunchasini o'rgandik.
Eng muhim uch fikr:
Belgilar modeldan muhimroq. Uch haftalik giperparametr sozlash 0.007 AUC bergan joyda bitta to'g'ri nisbat belgisi 0.035 beradi. Belgi turlarini aniq ajrating: nominal (one-hot) va ordinal (tartib saqlanadi) ni adashtirish modelga yolg'on tartib o'rgatadi.
Belgi modeldan ajralmagan. Chiziqli modelga masshtablash,
logva o'zaro ta'sirlar qo'lda kerak; daraxtlar esa monoton transformatsiyadan foyda ko'rmaydi va o'zaro ta'sirlarni o'zi topadi. Shuning uchun "universal eng yaxshi belgilar to'plami" yo'q — u tanlangan modelga bog'liq.Leakage — eng katta xavf. Maqsad leakage (belgi maqsaddan hosil bo'lgan) va vaqt leakage (belgi bashorat vaqtida hali ma'lum emas) CV da ajoyib natija beradi va ishlab chiqarishda butunlay ishlamaydi. Asosiy signal — "juda yaxshi natija": har belgining yakka CV natijasini ko'ring va 0.9 dan yuqorisidan shubhalaning.
Keyingi darsda belgi yaratishni o'rganamiz: nisbatlar, agregatsiyalar, binning va polinomial belgilar.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!