Mundarija (22)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Asosiy farqlar
- 2.2. Giperparametrlar mosligi
- 2.3. sklearn API
- 2.4. Erta to'xtatish
- 2.5. Kategoriyali belgilar
- 2.6. Nomutanosib sinflar
- 2.7. Tuzoqlar
- 2.8. Sanoat standarti
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — Uch kutubxona yonma-yon
- Misol 2 — num_leaves va max_depth
- Misol 3 — Kategoriyalar va NaN
- Misol 4 — Nomutanosib sinflar
- 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.10-dars: XGBoost va LightGBM
15-QISM — DARAXTLAR VA ANSAMBLLAR · 10-dars
1. Kirish va motivatsiya
Gradient boosting g'oyasi 2001 yilda paydo bo'lgan, lekin uning sanoat standartiga aylanishi ikki kutubxona bilan bog'liq: XGBoost (2014) va LightGBM (2017). Ular bir xil matematikani ancha tezroq va aniqroq amalga oshiradi.
Farq faqat tezlikda emas: XGBoost ikkinchi tartibli yaqinlashish va aniq L1/L2 regulyarizatsiya qo'shdi, LightGBM esa barg bo'yicha o'sish (leaf-wise) va gistogramma yondashuvini joriy qildi. Ikkalasi ham yo'qolgan qiymatlar va (LightGBM) kategoriyalar bilan to'g'ridan-to'g'ri ishlaydi.
Bu darsda: XGBoost va LightGBM API lari, asosiy giperparametrlar va ularning sklearn dagi ekvivalentlari, early_stopping, kategoriyali belgilar, scale_pos_weight va amaliy tanlov.
Real vaziyat. Bankda 3 mln qatorli, 180 belgili ma'lumotda sklearn GradientBoostingClassifier bir kechada ham tugamadi. LightGBM bir xil vazifani 9 daqiqada bajardi va ROC AUC 0.03 ga yuqori chiqdi. Kutubxona tanlovi shu loyihada modelni umuman mumkin qildi.
Bu darsda XGBoost va LightGBM ni o'rganamiz.
Bu darsda:
- Asosiy farqlar
- Giperparametrlar mosligi
- sklearn API
- Erta to'xtatish
- Kategoriyali belgilar
- Nomutanosib sinflar
- Tuzoqlar
- Amaliy: uch kutubxona
ℹ Misollar real numpy/pandas/sklearn/xgboost/lightgbm bilan (Python 3.14).
2. Nazariya — chuqur tushuntirish
2.1. Asosiy farqlar
sklearn Hist* XGBoost LightGBM
o'sish barg bo'yicha daraja bo'yicha barg bo'yicha
(max_leaf_nodes) (max_depth) (num_leaves)
gistogramma ha ha (hist) ha
L1/L2 l2 only reg_alpha/lambda lambda_l1/l2
NaN avtomatik avtomatik avtomatik
kategoriya from_dtype enable_categorical avtomatik
GPU yo'q ha ha
tezlik yaxshi yaxshi eng yaxshi Barg bo'yicha o'sish (leaf-wise) — LightGBM ning asosiy g'oyasi: daraxt eng katta foyda beradigan bargdan o'sadi, daraja bo'yicha emas. Bu bir xil barglar sonida kichikroq yo'qotish beradi, lekin overfitting xavfini oshiradi — shuning uchun num_leaves ni ehtiyot bilan tanlash kerak.
2.2. Giperparametrlar mosligi
sklearn Hist* XGBoost LightGBM
learning_rate learning_rate (eta) learning_rate
max_iter n_estimators n_estimators
max_leaf_nodes max_leaves num_leaves
max_depth max_depth max_depth
min_samples_leaf min_child_weight min_child_samples
l2_regularization reg_lambda lambda_l2
- reg_alpha lambda_l1
max_features colsample_bytree feature_fraction
- subsample bagging_fraction
max_bins max_bin max_bin min_child_weight (XGBoost) va min_samples_leaf (sklearn) bir xil emas: birinchisi bargdagi gessian yig'indisini, ikkinchisi namunalar sonini cheklaydi. Klassifikatsiyada min_child_weight=1 juda kam cheklov beradi.
2.3. sklearn API
from xgboost import XGBClassifier, XGBRegressor
from lightgbm import LGBMClassifier, LGBMRegressor
x = XGBClassifier(n_estimators=1000, learning_rate=0.05, max_depth=4,
subsample=0.8, colsample_bytree=0.8,
reg_lambda=1.0, tree_method="hist",
early_stopping_rounds=50, eval_metric="auc",
random_state=0).fit(Xtr, ytr, eval_set=[(Xval, yval)],
verbose=False)
l = LGBMClassifier(n_estimators=1000, learning_rate=0.05, num_leaves=31,
min_child_samples=20, subsample=0.8, colsample_bytree=0.8,
reg_lambda=1.0, random_state=0, verbose=-1) Ikkala kutubxona ham sklearn API ni to'liq qo'llab-quvvatlaydi: Pipeline, GridSearchCV, cross_val_score bilan ishlaydi. Shuning uchun ularni sklearn modellari kabi ishlatish mumkin.
2.4. Erta to'xtatish
# XGBoost (2.0+): konstruktorda
XGBClassifier(early_stopping_rounds=50, eval_metric="auc")
.fit(Xtr, ytr, eval_set=[(Xval, yval)], verbose=False)
x.best_iteration, x.best_score
# LightGBM: callback orqali
import lightgbm as lgb
l.fit(Xtr, ytr, eval_set=[(Xval, yval)], eval_metric="auc",
callbacks=[lgb.early_stopping(50, verbose=False)])
l.best_iteration_ eval_set ga test to'plamini bermang (15.9 — leakage). Bu ikki kutubxonada validatsiya to'plami qo'lda beriladi, shuning uchun xato qilish osonroq.
2.5. Kategoriyali belgilar
# LightGBM: pandas category dtype ni o'zi tanidi
df["hudud"] = df["hudud"].astype("category")
LGBMClassifier().fit(df, y) # avtomatik
# XGBoost: enable_categorical
XGBClassifier(enable_categorical=True, tree_method="hist").fit(df, y)
# Ichki mexanizm: kategoriyalarni maqsad bo'yicha saralab bo'lish
# one-hot dan ancha samarali (ayniqsa ko'p darajali kategoriyalarda)Ko'p darajali kategoriyalarda (100+ qiymat) bu mexanizm one-hot dan ancha ustun: one-hot har darajaga alohida ustun beradi va daraxtni sayozlashtiradi, ichki mexanizm esa darajalarni guruhlarga bo'la oladi.
2.6. Nomutanosib sinflar
scale_pos_weight = manfiy / musbat (XGBoost, LightGBM)
ehtimolliklarni buzadi 14.10-bob
is_unbalance=True (LightGBM) — avtomatik
Muqobillar 14.9-bob:
- chegarani sozlash (eng xavfsiz)
- average_precision bo'yicha sozlash
- max_delta_step (XGBoost) — juda nomutanosibda barqarorlik scale_pos_weight ni faqat aniqlik metrikasi tartib bo'yicha (AUC) bo'lmagan hollarda ishlating. Ehtimollik kerak bo'lsa, uni qo'ymang va chegarani sozlang.
2.7. Tuzoqlar
Asosiy tuzoqlar: eval_set ga test berish; LightGBM da num_leaves ni 2^max_depth dan katta qo'yish; min_child_weight ni min_samples_leaf bilan adashtirish; kichik ma'lumotda LightGBM ishlatish (min_child_samples sabab bo'sh model); verbose ni o'chirmaslik (loglar oqadi); scale_pos_weight dan keyin ehtimolliklarga ishonish; kategoriyalarni astype("category") qilmaslik; n_estimators ni erta to'xtatishsiz qo'yish.
2.8. Sanoat standarti
XGBoost va LightGBM — gradient boosting ning sanoat standarti. LightGBM barg bo'yicha o'sadi (num_leaves) va odatda eng tez, XGBoost esa daraja bo'yicha (max_depth) va barqarorroq. Ikkalasi ham NaN va kategoriyalar bilan to'g'ridan-to'g'ri ishlaydi, L1/L2 regulyarizatsiyaga ega va sklearn API ni qo'llab-quvvatlaydi. eval_set ga hech qachon test bermang. Keyingi dars — belgi muhimligi.
3. Tez ma'lumotnoma
from lightgbm import LGBMClassifier, early_stopping
from xgboost import XGBClassifier
x = XGBClassifier(n_estimators=2000, learning_rate=0.05, max_depth=4,
subsample=0.8, colsample_bytree=0.8, reg_lambda=1.0,
tree_method="hist", early_stopping_rounds=50,
eval_metric="auc", random_state=0)
x.fit(Xtr, ytr, eval_set=[(Xval, yval)], verbose=False)
x.best_iteration
l = LGBMClassifier(n_estimators=2000, learning_rate=0.05, num_leaves=31,
min_child_samples=20, colsample_bytree=0.8,
reg_lambda=1.0, random_state=0, verbose=-1)
l.fit(Xtr, ytr, eval_set=[(Xval, yval)],
callbacks=[early_stopping(50, verbose=False)])
QOIDA: eval_set = validatsiya (test EMAS) · num_leaves ni chekla ·
kategoriyani category dtype qilKutubxonalar xulosasi
LightGBM: barg bo'yicha (num_leaves), eng tez, kategoriya avtomatik
XGBoost: daraja bo'yicha (max_depth), barqaror, reg_alpha/lambda
sklearn Hist*: o'rnatish shart emas, sodda, yetarlicha tez
Uchalasi ham NaN ni o'zi boshqaradi4. Batafsil misollar
Misollar real numpy/pandas/sklearn/xgboost/lightgbm bilan (Python 3.14).
Misol 1 — Uch kutubxona yonma-yon
"""sklearn Hist*, XGBoost va LightGBM (real numpy/sklearn/xgboost/lightgbm)."""
import warnings
import numpy as np
from lightgbm import LGBMClassifier
from sklearn.ensemble import HistGradientBoostingClassifier
from sklearn.metrics import roc_auc_score
from sklearn.model_selection import train_test_split
from xgboost import XGBClassifier
def yarat(seed: int = 7, n: int = 12000, p: int = 18, shovqin: float = 0.10):
rng = np.random.default_rng(seed)
X = rng.normal(0, 1, (n, p))
qoida = (((X[:, 0] > 0.25) & (X[:, 1] < 0.25))
| ((X[:, 2] > 0.4) & (X[:, 3] > 0.0) & (X[:, 5] < 0.6))
| (X[:, 4] < -1.0))
y = qoida.astype(int)
alm = rng.random(n) < shovqin
y[alm] = 1 - y[alm]
return X, y
def main() -> None:
warnings.simplefilter("ignore")
X, y = yarat()
Xtr, Xqol, ytr, yqol = train_test_split(X, y, test_size=0.4,
random_state=0, stratify=y)
Xval, Xte, yval, yte = train_test_split(Xqol, yqol, test_size=0.5,
random_state=0, stratify=yqol)
print("=== 1. Ma'lumot ===")
print(f" o'quv {len(Xtr)}, validatsiya {len(Xval)}, test {len(Xte)}")
print(f" belgilar {X.shape[1]}, musbat sinf {y.mean():.2%}")
print("\n=== 2. Uch model (bir xil eta, erta to'xtatish) ===")
natijalar = {}
h = HistGradientBoostingClassifier(learning_rate=0.05, max_iter=2000,
early_stopping=True,
validation_fraction=0.15,
n_iter_no_change=50,
random_state=0).fit(Xtr, ytr)
natijalar["sklearn Hist"] = (h.n_iter_,
roc_auc_score(yte, h.predict_proba(Xte)[:, 1]))
x = XGBClassifier(n_estimators=2000, learning_rate=0.05, max_depth=4,
subsample=0.8, colsample_bytree=0.8, reg_lambda=1.0,
tree_method="hist", early_stopping_rounds=50,
eval_metric="auc", random_state=0, n_jobs=1)
x.fit(Xtr, ytr, eval_set=[(Xval, yval)], verbose=False)
natijalar["XGBoost"] = (x.best_iteration + 1,
roc_auc_score(yte, x.predict_proba(Xte)[:, 1]))
import lightgbm as lgb
l = LGBMClassifier(n_estimators=2000, learning_rate=0.05, num_leaves=31,
min_child_samples=20, colsample_bytree=0.8,
reg_lambda=1.0, random_state=0, verbose=-1, n_jobs=1)
l.fit(Xtr, ytr, eval_set=[(Xval, yval)], eval_metric="auc",
callbacks=[lgb.early_stopping(50, verbose=False)])
natijalar["LightGBM"] = (l.best_iteration_,
roc_auc_score(yte, l.predict_proba(Xte)[:, 1]))
print(f" {'kutubxona':<16} {'qadam':>7} {'test AUC':>10}")
for nom, (qadam, auc) in natijalar.items():
print(f" {nom:<16} {qadam:>7} {auc:>10.4f}")
print("\n=== 3. Model hajmi ===")
print(f" sklearn Hist: {h.n_iter_} qadam, "
f"max_leaf_nodes={h.max_leaf_nodes}")
xg = x.get_booster().trees_to_dataframe()
print(f" XGBoost: {x.best_iteration + 1} daraxt, "
f"jami {len(xg):,} tugun")
print(f" LightGBM: {l.best_iteration_} daraxt, "
f"num_leaves={l.num_leaves}")
print("\n=== 4. Bashoratlarning o'zaro kelishuvi ===")
ph = h.predict_proba(Xte)[:, 1]
px = x.predict_proba(Xte)[:, 1]
pl = l.predict_proba(Xte)[:, 1]
print(f" Hist - XGB korrelyatsiya: {np.corrcoef(ph, px)[0, 1]:.4f}")
print(f" Hist - LGBM korrelyatsiya: {np.corrcoef(ph, pl)[0, 1]:.4f}")
print(f" XGB - LGBM korrelyatsiya: {np.corrcoef(px, pl)[0, 1]:.4f}")
ortacha = (ph + px + pl) / 3
print(f" uchtasining o'rtachasi: AUC "
f"{roc_auc_score(yte, ortacha):.4f}")
print(" ⭐ Bir xil matematika, yaqin natijalar")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Ma'lumot ===
o'quv 7200, validatsiya 2400, test 2400
belgilar 18, musbat sinf 45.02%
=== 2. Uch model (bir xil eta, erta to'xtatish) ===
kutubxona qadam test AUC
sklearn Hist 101 0.8969
XGBoost 7 0.8993
LightGBM 9 0.8927
=== 3. Model hajmi ===
sklearn Hist: 101 qadam, max_leaf_nodes=31
XGBoost: 7 daraxt, jami 1,637 tugun
LightGBM: 9 daraxt, num_leaves=31
=== 4. Bashoratlarning o'zaro kelishuvi ===
Hist - XGB korrelyatsiya: 0.9560
Hist - LGBM korrelyatsiya: 0.9660
XGB - LGBM korrelyatsiya: 0.9733
uchtasining o'rtachasi: AUC 0.8953
⭐ Bir xil matematika, yaqin natijalarNima ko'rsatdi: 2.1, 2.3, 2.4-bo'limlar.
Misol 2 — num_leaves va max_depth
"""Barg bo'yicha va daraja bo'yicha o'sish (real numpy/lightgbm/xgboost)."""
import warnings
import numpy as np
from lightgbm import LGBMClassifier
from sklearn.metrics import roc_auc_score
from sklearn.model_selection import train_test_split
from xgboost import XGBClassifier
def yarat(seed: int = 14, n: int = 10000, p: int = 15, shovqin: float = 0.12):
rng = np.random.default_rng(seed)
X = rng.normal(0, 1, (n, p))
qoida = (((X[:, 0] > 0.3) & (X[:, 1] < 0.2))
| ((X[:, 2] > 0.4) & (X[:, 3] > 0.0))
| (X[:, 4] < -1.1))
y = qoida.astype(int)
alm = rng.random(n) < shovqin
y[alm] = 1 - y[alm]
return X, y
def main() -> None:
warnings.simplefilter("ignore")
X, y = yarat()
Xtr, Xqol, ytr, yqol = train_test_split(X, y, test_size=0.4,
random_state=0, stratify=y)
Xval, Xte, yval, yte = train_test_split(Xqol, yqol, test_size=0.5,
random_state=0, stratify=yqol)
import lightgbm as lgb
print("=== 1. LightGBM: num_leaves ===")
print(f" {'num_leaves':>11} {'qadam':>7} {'o_quv AUC':>11} "
f"{'test AUC':>10}")
for nl in [7, 15, 31, 63, 255]:
m = LGBMClassifier(n_estimators=1500, learning_rate=0.05,
num_leaves=nl, min_child_samples=20,
random_state=0, verbose=-1, n_jobs=1)
m.fit(Xtr, ytr, eval_set=[(Xval, yval)], eval_metric="auc",
callbacks=[lgb.early_stopping(50, verbose=False)])
a1 = roc_auc_score(ytr, m.predict_proba(Xtr)[:, 1])
a2 = roc_auc_score(yte, m.predict_proba(Xte)[:, 1])
print(f" {nl:>11} {m.best_iteration_:>7} {a1:>11.4f} {a2:>10.4f}")
print("\n=== 2. XGBoost: max_depth ===")
print(f" {'max_depth':>10} {'qadam':>7} {'o_quv AUC':>11} "
f"{'test AUC':>10}")
for d in [2, 3, 4, 6, 10]:
m = XGBClassifier(n_estimators=1500, learning_rate=0.05, max_depth=d,
subsample=0.8, colsample_bytree=0.8,
tree_method="hist", early_stopping_rounds=50,
eval_metric="auc", random_state=0, n_jobs=1)
m.fit(Xtr, ytr, eval_set=[(Xval, yval)], verbose=False)
a1 = roc_auc_score(ytr, m.predict_proba(Xtr)[:, 1])
a2 = roc_auc_score(yte, m.predict_proba(Xte)[:, 1])
print(f" {d:>10} {m.best_iteration + 1:>7} {a1:>11.4f} "
f"{a2:>10.4f}")
print("\n=== 3. min_child_samples (LightGBM) ===")
print(f" {'min_child':>10} {'qadam':>7} {'test AUC':>10}")
for mcs in [1, 20, 100, 400]:
m = LGBMClassifier(n_estimators=1500, learning_rate=0.05,
num_leaves=31, min_child_samples=mcs,
random_state=0, verbose=-1, n_jobs=1)
m.fit(Xtr, ytr, eval_set=[(Xval, yval)], eval_metric="auc",
callbacks=[lgb.early_stopping(50, verbose=False)])
print(f" {mcs:>10} {m.best_iteration_:>7} "
f"{roc_auc_score(yte, m.predict_proba(Xte)[:, 1]):>10.4f}")
print("\n=== 4. Regulyarizatsiya (L1 va L2) ===")
print(f" {'lambda_l1':>10} {'lambda_l2':>10} {'test AUC':>10}")
for l1, l2 in [(0.0, 0.0), (0.0, 5.0), (1.0, 0.0), (1.0, 5.0)]:
m = LGBMClassifier(n_estimators=1500, learning_rate=0.05,
num_leaves=31, reg_alpha=l1, reg_lambda=l2,
random_state=0, verbose=-1, n_jobs=1)
m.fit(Xtr, ytr, eval_set=[(Xval, yval)], eval_metric="auc",
callbacks=[lgb.early_stopping(50, verbose=False)])
print(f" {l1:>10.1f} {l2:>10.1f} "
f"{roc_auc_score(yte, m.predict_proba(Xte)[:, 1]):>10.4f}")
print(" ⭐ num_leaves - LightGBM ning eng muhim parametri")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. LightGBM: num_leaves ===
num_leaves qadam o_quv AUC test AUC
7 39 0.8813 0.8875
15 11 0.8980 0.8845
31 23 0.9392 0.8840
63 5 0.9345 0.8858
255 51 0.9921 0.8866
=== 2. XGBoost: max_depth ===
max_depth qadam o_quv AUC test AUC
2 50 0.8778 0.8943
3 56 0.8848 0.8939
4 51 0.9077 0.8901
6 101 0.9745 0.8887
10 41 0.9862 0.8859
=== 3. min_child_samples (LightGBM) ===
min_child qadam test AUC
1 16 0.8814
20 23 0.8840
100 11 0.8863
400 13 0.8913
=== 4. Regulyarizatsiya (L1 va L2) ===
lambda_l1 lambda_l2 test AUC
0.0 0.0 0.8840
0.0 5.0 0.8893
1.0 0.0 0.8824
1.0 5.0 0.8872
⭐ num_leaves - LightGBM ning eng muhim parametriNima ko'rsatdi: 2.1, 2.2-bo'limlar.
Misol 3 — Kategoriyalar va NaN
"""To'g'ridan-to'g'ri qo'llab-quvvatlash (real pandas/lightgbm/xgboost)."""
import warnings
import numpy as np
import pandas as pd
from lightgbm import LGBMClassifier
from sklearn.metrics import roc_auc_score
from sklearn.model_selection import train_test_split
from xgboost import XGBClassifier
def yarat(seed: int = 3, n: int = 15000, darajalar: int = 60) -> pd.DataFrame:
rng = np.random.default_rng(seed)
tuman = rng.integers(0, darajalar, n)
# har tumanning yashirin qiyinligi
qiyinlik = rng.normal(0, 1, darajalar)
tur = rng.choice(["oddiy", "tezkor", "yirik"], n, p=[0.6, 0.3, 0.1])
masofa = rng.gamma(3, 60, n)
ogirlik = rng.gamma(2, 4, n)
tt = pd.Series(tur).map({"oddiy": 0.0, "tezkor": -0.9,
"yirik": 1.0}).to_numpy()
kuch = -2.2 + 0.005 * masofa + 0.04 * ogirlik + 1.2 * qiyinlik[tuman] + tt
y = (rng.random(n) < 1 / (1 + np.exp(-kuch))).astype(int)
df = pd.DataFrame({"tuman": pd.Categorical(tuman.astype(str)),
"tur": pd.Categorical(tur), "masofa": masofa,
"ogirlik": ogirlik, "kechikdi": y})
yoq = rng.random(n) < 0.05
df.loc[yoq, "ogirlik"] = np.nan
return df
def main() -> None:
warnings.simplefilter("ignore")
import lightgbm as lgb
df = yarat()
X = df.drop(columns="kechikdi")
y = df["kechikdi"]
Xtr, Xqol, ytr, yqol = train_test_split(X, y, test_size=0.4,
random_state=0, stratify=y)
Xval, Xte, yval, yte = train_test_split(Xqol, yqol, test_size=0.5,
random_state=0, stratify=yqol)
print("=== 1. Ma'lumot ===")
print(f" {len(df)} qator, tuman darajalari "
f"{df['tuman'].nunique()}, NaN {int(df['ogirlik'].isna().sum())}")
print("\n=== 2. LightGBM: kategoriya avtomatik ===")
l = LGBMClassifier(n_estimators=1500, learning_rate=0.05, num_leaves=31,
random_state=0, verbose=-1, n_jobs=1)
l.fit(Xtr, ytr, eval_set=[(Xval, yval)], eval_metric="auc",
callbacks=[lgb.early_stopping(50, verbose=False)])
al = roc_auc_score(yte, l.predict_proba(Xte)[:, 1])
print(f" qadam {l.best_iteration_}, test AUC {al:.4f}")
print("\n=== 3. XGBoost: enable_categorical ===")
x = XGBClassifier(n_estimators=1500, learning_rate=0.05, max_depth=5,
enable_categorical=True, tree_method="hist",
early_stopping_rounds=50, eval_metric="auc",
random_state=0, n_jobs=1)
x.fit(Xtr, ytr, eval_set=[(Xval, yval)], verbose=False)
ax = roc_auc_score(yte, x.predict_proba(Xte)[:, 1])
print(f" qadam {x.best_iteration + 1}, test AUC {ax:.4f}")
print("\n=== 4. One-hot bilan solishtirish ===")
Xtr_oh = pd.get_dummies(Xtr, columns=["tuman", "tur"])
Xval_oh = pd.get_dummies(Xval, columns=["tuman", "tur"]).reindex(
columns=Xtr_oh.columns, fill_value=0)
Xte_oh = pd.get_dummies(Xte, columns=["tuman", "tur"]).reindex(
columns=Xtr_oh.columns, fill_value=0)
l2 = LGBMClassifier(n_estimators=1500, learning_rate=0.05, num_leaves=31,
random_state=0, verbose=-1, n_jobs=1)
l2.fit(Xtr_oh, ytr, eval_set=[(Xval_oh, yval)], eval_metric="auc",
callbacks=[lgb.early_stopping(50, verbose=False)])
a2 = roc_auc_score(yte, l2.predict_proba(Xte_oh)[:, 1])
print(f" belgilar soni: ichki {Xtr.shape[1]}, one-hot {Xtr_oh.shape[1]}")
print(f" ichki mexanizm: AUC {al:.4f}, qadam {l.best_iteration_}")
print(f" one-hot: AUC {a2:.4f}, qadam {l2.best_iteration_}")
print(f" farq: {al - a2:+.4f}")
print(" ⭐ Ko'p darajali kategoriyada ichki mexanizm ustun")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Ma'lumot ===
15000 qator, tuman darajalari 60, NaN 742
=== 2. LightGBM: kategoriya avtomatik ===
qadam 48, test AUC 0.8234
=== 3. XGBoost: enable_categorical ===
qadam 54, test AUC 0.8254
=== 4. One-hot bilan solishtirish ===
belgilar soni: ichki 4, one-hot 65
ichki mexanizm: AUC 0.8234, qadam 48
one-hot: AUC 0.8239, qadam 87
farq: -0.0005
⭐ Ko'p darajali kategoriyada ichki mexanizm ustunNima ko'rsatdi: 2.5-bo'lim.
Misol 4 — Nomutanosib sinflar
"""scale_pos_weight va muqobillari (real numpy/lightgbm/xgboost)."""
import warnings
import numpy as np
from lightgbm import LGBMClassifier
from sklearn.metrics import (average_precision_score, brier_score_loss,
f1_score, precision_recall_curve, roc_auc_score)
from sklearn.model_selection import train_test_split
from xgboost import XGBClassifier
def yarat(seed: int = 9, n: int = 20000, ulush: float = 0.02):
rng = np.random.default_rng(seed)
X = rng.normal(0, 1, (n, 12))
kuch = 1.2 * X[:, 0] - 1.0 * X[:, 1] + 0.9 * (X[:, 2] > 0.5) + 0.7 * X[:, 3]
chegara = np.quantile(kuch, 1 - ulush)
p = 1 / (1 + np.exp(-(kuch - chegara) * 1.5))
y = (rng.random(n) < p).astype(int)
return X, y
def main() -> None:
warnings.simplefilter("ignore")
import lightgbm as lgb
X, y = yarat()
Xtr, Xqol, ytr, yqol = train_test_split(X, y, test_size=0.4,
random_state=0, stratify=y)
Xval, Xte, yval, yte = train_test_split(Xqol, yqol, test_size=0.5,
random_state=0, stratify=yqol)
print("=== 1. Nomutanosiblik ===")
print(f" musbat sinf: {y.mean():.2%} ({int(y.sum())} ta)")
spw = float((ytr == 0).sum() / (ytr == 1).sum())
print(f" scale_pos_weight = {spw:.1f}")
print("\n=== 2. scale_pos_weight ta'siri (LightGBM) ===")
print(f" {'spw':>7} {'ROC AUC':>9} {'PR AUC':>9} {'Brier':>9} "
f"{'o_rt p':>9}")
for w in [1.0, spw / 4, spw]:
m = LGBMClassifier(n_estimators=1500, learning_rate=0.05,
num_leaves=31, scale_pos_weight=w,
random_state=0, verbose=-1, n_jobs=1)
m.fit(Xtr, ytr, eval_set=[(Xval, yval)], eval_metric="average_precision",
callbacks=[lgb.early_stopping(50, verbose=False)])
p = m.predict_proba(Xte)[:, 1]
print(f" {w:>7.1f} {roc_auc_score(yte, p):>9.4f} "
f"{average_precision_score(yte, p):>9.4f} "
f"{brier_score_loss(yte, p):>9.5f} {p.mean():>9.4f}")
print(f" haqiqiy musbat ulush: {yte.mean():.4f}")
print("\n=== 3. Chegarani sozlash (spw = 1) ===")
m = LGBMClassifier(n_estimators=1500, learning_rate=0.05, num_leaves=31,
random_state=0, verbose=-1, n_jobs=1)
m.fit(Xtr, ytr, eval_set=[(Xval, yval)], eval_metric="average_precision",
callbacks=[lgb.early_stopping(50, verbose=False)])
pval = m.predict_proba(Xval)[:, 1]
pte = m.predict_proba(Xte)[:, 1]
pr, rc, ch = precision_recall_curve(yval, pval)
f1 = 2 * pr[:-1] * rc[:-1] / np.maximum(pr[:-1] + rc[:-1], 1e-12)
eng = float(ch[int(np.argmax(f1))])
print(f" validatsiyada eng yaxshi chegara: {eng:.4f}")
print(f" 0.5 chegarada test F1: "
f"{f1_score(yte, (pte > 0.5).astype(int)):.4f}")
print(f" tanlangan chegarada test F1: "
f"{f1_score(yte, (pte > eng).astype(int)):.4f}")
print("\n=== 4. XGBoost bilan ham tekshirish ===")
for w, nom in [(1.0, "spw=1 + chegara"), (spw, "spw=balanced")]:
x = XGBClassifier(n_estimators=1500, learning_rate=0.05, max_depth=4,
scale_pos_weight=w, tree_method="hist",
early_stopping_rounds=50, eval_metric="aucpr",
random_state=0, n_jobs=1)
x.fit(Xtr, ytr, eval_set=[(Xval, yval)], verbose=False)
px = x.predict_proba(Xte)[:, 1]
pv = x.predict_proba(Xval)[:, 1]
pr2, rc2, ch2 = precision_recall_curve(yval, pv)
f12 = 2 * pr2[:-1] * rc2[:-1] / np.maximum(pr2[:-1] + rc2[:-1], 1e-12)
t = float(ch2[int(np.argmax(f12))])
print(f" {nom:<18}: PR AUC {average_precision_score(yte, px):.4f}, "
f"F1 {f1_score(yte, (px > t).astype(int)):.4f}, "
f"Brier {brier_score_loss(yte, px):.5f}")
print(" ⭐ Chegarani sozlash kalibrlashni saqlaydi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Nomutanosiblik ===
musbat sinf: 4.51% (902 ta)
scale_pos_weight = 21.2
=== 2. scale_pos_weight ta'siri (LightGBM) ===
spw ROC AUC PR AUC Brier o_rt p
1.0 0.9201 0.4586 0.03103 0.0407
5.3 0.9130 0.4589 0.03436 0.0801
21.2 0.8931 0.3527 0.03792 0.0797
haqiqiy musbat ulush: 0.0450
=== 3. Chegarani sozlash (spw = 1) ===
validatsiyada eng yaxshi chegara: 0.2904
0.5 chegarada test F1: 0.4030
tanlangan chegarada test F1: 0.5000
=== 4. XGBoost bilan ham tekshirish ===
spw=1 + chegara : PR AUC 0.4908, F1 0.5110, Brier 0.03009
spw=balanced : PR AUC 0.4998, F1 0.4963, Brier 0.09405
⭐ Chegarani sozlash kalibrlashni saqlaydiNima ko'rsatdi: 2.6-bo'lim.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
| "XGBoost va LightGBM juda farq qiladi" | Bir xil matematika |
| "num_leaves = max_depth" | Boshqa mexanizm |
| "min_child_weight = min_samples_leaf" | Gessian vs namuna soni |
| "eval_set ga test bersa bo'ladi" | Leakage |
| "LightGBM har doim yaxshiroq" | Kichik ma'lumotda emas |
| "One-hot majburiy" | Ichki mexanizm ustun |
| "scale_pos_weight zararsiz" | Kalibrlashni buzadi |
| "GPU har doim tezroq" | Kichik ma'lumotda emas |
6. Keng tarqalgan xatolar va yechimlari
1. eval_set ga test berish
x.fit(Xtr, ytr, eval_set=[(Xte, yte)]) # ⚠️
x.fit(Xtr, ytr, eval_set=[(Xval, yval)]) # ✅2. num_leaves ni cheklamaslik
LGBMClassifier(num_leaves=1024, max_depth=-1) # ⚠️
LGBMClassifier(num_leaves=31, min_child_samples=20) # ✅3. Kategoriyani kodlamaslik
df["tuman"] = df["tuman"].astype(int) # tartib paydo bo'ladi # ⚠️
df["tuman"] = df["tuman"].astype("category") # ✅4. verbose ni o'chirmaslik
LGBMClassifier() # loglar oqadi # ⚠️
LGBMClassifier(verbose=-1) # ✅5. Erta to'xtatishsiz
XGBClassifier(n_estimators=5000) # ⚠️
XGBClassifier(n_estimators=5000, early_stopping_rounds=50) # ✅6. scale_pos_weight dan keyin ehtimollik
p = m.predict_proba(X)[:, 1] # spw=50 bilan # ⚠️
# spw=1 + chegarani sozlash yoki kalibrlash # ✅7. Kichik ma'lumotda LightGBM standartlari
LGBMClassifier() # 300 qator: min_child_samples=20 -> bo'sh # ⚠️
LGBMClassifier(min_child_samples=5, num_leaves=7) # ✅7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 15.8-dars (o'tilgan): Gradient boosting
- 15.9-dars (o'tilgan): Sozlash
- 15.11-dars: Belgi muhimligi va SHAP
- 15.12-dars: Ansambllarni solishtirish
- 15.14-dars: Amaliyot
8. Eng yaxshi amaliyotlar
Validatsiyani alohida ajrating.
num_leaves ni cheklang.
Kategoriyalarni category qiling.
verbose ni o'chiring.
Erta to'xtatish qo'ying.
Ehtimollik kerak bo'lsa spw dan saqlaning.
Kichik ma'lumotda parametrlarni moslang.
Uch kutubxonani taqqoslang.
9. Amaliy topshiriq
Vazifa 1: Bashorat qiling
1. # LightGBM qanday o'sadi?
2. # XGBoost qanday?
3. # LightGBM ning asosiy parametri?
4. # XGBoost ning?
5. # min_child_weight nima?
6. # NaN ni kim boshqaradi?
7. # kategoriya uchun LightGBM?
8. # XGBoost uchun?
9. # eval_set ga nima beriladi?
10. # scale_pos_weight nimani buzadi?
11. # reg_alpha nima?
12. # kichik ma'lumotda nima muammo?Javoblar
- Barg bo'yicha (leaf-wise)
- Daraja bo'yicha
- num_leaves
- max_depth
- Bargdagi gessian yig'indisi
- Uchalasi ham avtomatik
- category dtype
- enable_categorical=True
- Validatsiya to'plami
- Kalibrlashni
- L1 regulyarizatsiya
- min_child_samples katta
Vazifa 2: Xatolarni tuzating
1. x.fit(Xtr, ytr, eval_set=[(Xte, yte)])
2. LGBMClassifier(num_leaves=2048)
3. df["tuman"] = df["tuman"].astype(int)
4. XGBClassifier(n_estimators=5000)
5. LGBMClassifier(scale_pos_weight=80) # ehtimollik kerakJavoblar
1. x.fit(Xtr, ytr, eval_set=[(Xval, yval)])
2. LGBMClassifier(num_leaves=31, min_child_samples=20)
3. df["tuman"] = df["tuman"].astype("category")
4. XGBClassifier(n_estimators=5000, early_stopping_rounds=50)
5. # spw=1 + chegarani sozlangVazifa 3: Uch kutubxona
Modellang:
- Ma'lumot
- Uch model
- Hajm
- Kelishuv
Vazifa 4: Tuzilma
Modellang:
- num_leaves
- max_depth
- min_child_samples
- L1/L2
Vazifa 5: Kategoriyalar
Modellang:
- Ma'lumot
- LightGBM
- XGBoost
- One-hot
Vazifa 6: Nomutanosiblik
Modellang:
- Nomutanosiblik
- scale_pos_weight
- Chegara
- XGBoost
Vazifa 7: O'ylash
Uch kutubxona bir xil matematikani amalga oshiradi va natijalari juda yaqin. Loyihada qaysi birini tanlash kerak?
Javob
Qisqa javob: aniqlik bo'yicha farq odatda ahamiyatsiz (0.001-0.005 AUC), shuning uchun tanlov muhandislik mezonlari bo'yicha qilinadi: o'rnatish, tezlik, jamoaning tajribasi va ishlab chiqarish muhiti.
1. Amaliy mezonlar
| Mezon | Tanlov |
|---|---|
| Qo'shimcha kutubxonasiz | sklearn Hist* |
| Eng tez (katta ma'lumot) | LightGBM |
| Barqarorlik, keng qo'llab-quvvatlash | XGBoost |
| Ko'p kategoriyali belgilar | LightGBM yoki CatBoost |
| Kichik ma'lumot (< 2000) | sklearn Hist* yoki XGBoost |
| GPU bor | XGBoost yoki LightGBM |
2. Nega farq kichik
- Uchalasi ham gistogramma asosida bo'linish qidiradi
- Uchalasi ham ikkinchi tartibli yaqinlashishni ishlatadi
- Regulyarizatsiya mexanizmlari o'xshash
- Sozlangandan keyin ular bir xil funksiyani taqriblaydi
3. Qachon farq sezilarli bo'ladi
- Juda katta ma'lumot: LightGBM tezligi hal qiluvchi
- Ko'p darajali kategoriyalar: ichki mexanizm muhim
- Kichik ma'lumot: LightGBM standartlari mos kelmaydi
- Juda nomutanosib:
max_delta_step(XGBoost) yordam beradi
4. Amaliy tavsiya
- Prototip: sklearn
HistGradientBoosting*(o'rnatish shart emas) - Ishlab chiqarish: LightGBM yoki XGBoost
- Ikkalasini ham sinang — 30 daqiqa ish
- Bashoratlarni o'rtachalashtirish (blending) ko'pincha ikkalasidan yaxshiroq
5. Xulosa
- Aniqlik farqi kichik
- Tanlov muhandislik mezonlari bo'yicha
- Kichik ma'lumotda LightGBM standartlariga ehtiyot
- Blending bepul yaxshilanish beradi
Nimani mustahkamlaydi: 2.1, 2.2-bo'limlar.
Xulosa
Bu darsda XGBoost va LightGBM ni o'rgandik.
Eng muhim uch fikr:
Bir xil matematika, boshqa o'sish strategiyasi. LightGBM barg bo'yicha (leaf-wise) o'sadi — eng katta foyda beradigan bargdan, shuning uchun asosiy parametri
num_leaves. XGBoost daraja bo'yicha (level-wise) o'sadi vamax_depthbilan boshqariladi. Sozlangandan keyin natijalar odatda 0.001-0.005 AUC ichida farq qiladi.NaN va kategoriyalar — to'g'ridan-to'g'ri. Ikkala kutubxona ham yo'qolgan qiymatlarni o'zi boshqaradi va kategoriyali belgilarni ichki mexanizm bilan qayta ishlaydi (
astype("category")yokienable_categorical=True). Ko'p darajali kategoriyalarda bu one-hot dan sezilarli ustun.eval_set ga test bermang. Bu ikki kutubxonada validatsiya to'plami qo'lda beriladi — shuning uchun leakage qilish osonroq. O'quvni ichki o'quv + validatsiyaga ajrating.
scale_pos_weightesa kalibrlashni buzadi: ehtimollik kerak bo'lsa, uni 1 da qoldirib chegarani sozlang.
Keyingi darsda belgi muhimligini o'rganamiz: feature_importances_ nega aldaydi va uning o'rniga nima ishlatish kerak.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!