12-bo‘lim

Qaror daraxti va Random Forest

Daraxtlar qanday qaror qabul qiladi, Gini va entropiya, ansambl usullari va belgilar muhimligi.

🕑 16 daqiqa o‘qish 📄 1 024 so‘z 👁 5 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Qaror daraxti nima?
  2. Birinchi daraxt
  3. Daraxtni ko'rish
  4. Bo'linish qanday tanlanadi?
  5. Qayta o'qitish - daraxtlarning asosiy muammosi
  6. Cheklovlar
  7. Belgilar muhimligi
  8. Random Forest
  9. Muhim parametrlar
  10. OOB baholash
  11. Gradient Boosting
  12. Regressiya uchun
  13. Xulosa

Qaror daraxti - inson mantiqiga eng yaqin algoritm. U ketma-ket savollar berib javobga keladi, xuddi shifokor kabi.

Qaror daraxti nima? #

Kredit berish qarori Daromad > 5 mln? 1000 namuna yo'q ha Qarzi bormi? 420 namuna Ish staji > 2 yil? 580 namuna RAD ETISH 190 · toza: 96% TEKSHIRISH 230 · toza: 58% TEKSHIRISH 160 · toza: 64% TASDIQLASH 420 · toza: 91% Ildiz → ichki tugunlar → barglar Har bir bo'linish ma'lumotni "tozaroq" ikki guruhga ajratadi
Daraxtni bank xodimi ham tushunadi - bu uning katta afzalligi

Birinchi daraxt #

Python
from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt

iris = load_iris()
X, y = iris.data, iris.target

X_o, X_s, y_o, y_s = train_test_split(
    X, y, test_size=0.3, random_state=42, stratify=y
)

daraxt = DecisionTreeClassifier(max_depth=3, random_state=42)
daraxt.fit(X_o, y_o)

print(f"O'qitish: {daraxt.score(X_o, y_o):.3f}")
print(f"Sinov:    {daraxt.score(X_s, y_s):.3f}")
Natija
O'qitish: 0.981
Sinov:    0.978
Masshtablash kerak emas

Daraxt faqat "bu qiymat chegaradan kattami?" deb so'raydi. Belgilar qanday birlikda o'lchanganining ahamiyati yo'q.

Bu daraxtlarning katta amaliy afzalligi.

Daraxtni ko'rish #

Python
plt.figure(figsize=(16, 9))
plot_tree(
    daraxt,
    feature_names=iris.feature_names,
    class_names=iris.target_names,
    filled=True,
    rounded=True,
    fontsize=10,
)
plt.show()
Python
from sklearn.tree import export_text

print(export_text(daraxt, feature_names=iris.feature_names))
Natija
|--- petal length (cm) <= 2.45
|   |--- class: setosa
|--- petal length (cm) >  2.45
|   |--- petal width (cm) <= 1.75
|   |   |--- petal length (cm) <= 4.95
|   |   |   |--- class: versicolor
|   |   |--- petal length (cm) >  4.95
|   |   |   |--- class: virginica
|   |--- petal width (cm) >  1.75
|   |   |--- class: virginica
Bu qoidalarni kodga ko'chirish mumkin
Python
def bashorat(barg_uzunligi, barg_kengligi):
    if barg_uzunligi <= 2.45:
        return "setosa"
    if barg_kengligi <= 1.75:
        return "versicolor" if barg_uzunligi <= 4.95 else "virginica"
    return "virginica"

Hech qanday kutubxona kerak emas. Bu daraxtlarning tushuntirilishi naqadar yaxshi ekanini ko'rsatadi.

Bo'linish qanday tanlanadi? #

Daraxt har bir qadamda eng yaxshi ajratuvchi savolni qidiradi.

Gini nopokligi - guruh qanchalik aralash? Toza guruh Gini = 0.0 Hammasi bir sinf Qisman aralash Gini = 0.32 8 ta ko'k, 2 ta qizil To'liq aralash Gini = 0.5 Teng aralashgan Gini = 1 - Σ p² Daraxt Gini ni eng ko'p kamaytiradigan bo'linishni tanlaydi
Maqsad - har bir bo'linishdan keyin guruhlarni tozaroq qilish
Python
def gini(sinflar):
    _, sonlar = np.unique(sinflar, return_counts=True)
    ehtimolliklar = sonlar / len(sinflar)
    return 1 - np.sum(ehtimolliklar ** 2)

print(gini([0, 0, 0, 0, 0]))              # 0.0
print(gini([0, 0, 0, 0, 1]))              # 0.32
print(gini([0, 0, 0, 1, 1]))              # 0.48
print(gini([0, 1, 0, 1, 0, 1]))           # 0.5
MezonFormulaXususiyat
Gini1 - Σp²Tezroq hisoblanadi, standart
Entropiya-Σp·log2(p)Nazariy asosli, biroz sekinroq
Python
DecisionTreeClassifier(criterion="gini")       # standart
DecisionTreeClassifier(criterion="entropy")
Amalda farq kam

Gini va entropiya deyarli har doim bir xil daraxt quradi. Gini tezroq bo'lgani uchun standart qilib tanlangan.

Qayta o'qitish - daraxtlarning asosiy muammosi #

Python
daraxt_cheksiz = DecisionTreeClassifier(random_state=42)
daraxt_cheksiz.fit(X_o, y_o)

print(f"O'qitish: {daraxt_cheksiz.score(X_o, y_o):.3f}")
print(f"Sinov:    {daraxt_cheksiz.score(X_s, y_s):.3f}")
print(f"Chuqurlik: {daraxt_cheksiz.get_depth()}")
print(f"Barglar:   {daraxt_cheksiz.get_n_leaves()}")
Natija
O'qitish: 1.000
Sinov:    0.933
Chuqurlik: 5
Barglar:   9
Cheklanmagan daraxt har doim 100% aniqlik beradi

Agar chuqurlik cheklanmasa, daraxt har bir namuna uchun alohida barg yaratishi mumkin - ya'ni butun ma'lumotni yodlab oladi.

Bu qayta o'qitishning eng aniq ko'rinishi.

Cheklovlar #

Python
daraxt = DecisionTreeClassifier(
    max_depth=4,              # maksimal chuqurlik
    min_samples_split=20,     # bo'linish uchun minimal namuna
    min_samples_leaf=10,      # bargdagi minimal namuna
    max_leaf_nodes=15,        # maksimal barglar soni
    min_impurity_decrease=0.01,
    random_state=42,
)
ParametrTa'siri
max_depthEng muhim - daraxt balandligi
min_samples_splitKichik guruhlarni bo'lishni taqiqlaydi
min_samples_leafBargda kamida shuncha namuna bo'lsin
max_leaf_nodesUmumiy murakkablikni cheklaydi
ccp_alphaKesish (pruning) kuchi
Python
print("Chuqurlik  O'qitish  Sinov")
for chuqurlik in [1, 2, 3, 5, 10, None]:
    d = DecisionTreeClassifier(max_depth=chuqurlik, random_state=42).fit(X_o, y_o)
    nom = str(chuqurlik) if chuqurlik else "cheksiz"
    print(f"{nom:>9}  {d.score(X_o, y_o):8.3f}  {d.score(X_s, y_s):.3f}")
Natija
Chuqurlik  O'qitish  Sinov
        1     0.667  0.667
        2     0.962  0.978
        3     0.981  0.978
        5     1.000  0.933
       10     1.000  0.933
  cheksiz     1.000  0.933

Chuqurlik 2-3 - eng yaxshi. Undan keyin sinov natijasi tushadi.

Belgilar muhimligi #

Python
import pandas as pd

daraxt = DecisionTreeClassifier(max_depth=3, random_state=42).fit(X_o, y_o)

muhimlik = pd.Series(
    daraxt.feature_importances_,
    index=iris.feature_names,
).sort_values(ascending=False)

print(muhimlik.round(3))
Natija
petal width (cm)     0.573
petal length (cm)    0.427
sepal length (cm)    0.000
sepal width (cm)     0.000
Belgilarni tanlash uchun foydali

Daraxt ikkita belgini umuman ishlatmagan - ular ortiqcha.

Bu bilim boshqa modellar uchun ham foydali: kerakli belgilarni daraxt yordamida topib, keyin ularni logistik regressiyaga bering.

feature_importances_ cheklovlari
  1. Korrelyatsiyalangan belgilar orasida muhimlik tasodifan taqsimlanadi
  2. Ko'p noyob qiymatli belgilar sun'iy ravishda muhimroq ko'rinadi

Ishonchliroq usul - permutatsiya muhimligi:

Python
from sklearn.inspection import permutation_importance

natija = permutation_importance(daraxt, X_s, y_s, n_repeats=10, random_state=42)

Random Forest #

Bitta daraxt beqaror. Yechim - ko'p daraxt qurib, ovoz berish.

Random Forest - daraxtlar jamoasi Asl ma'lumot Tasodifiy namuna 1 Tasodifiy namuna 2 Tasodifiy namuna 3 Tasodifiy namuna N . . . daraxt 1 daraxt 2 daraxt 3 daraxt N Ovoz berish / o'rtacha
Har bir daraxt boshqacha xato qiladi - ovoz berish ularni tuzatadi

Ikki tasodifiylik manbai:

  1. Bootstrap - har bir daraxt ma'lumotning tasodifiy qismida o'qiydi
  2. Belgi tasodifiyligi - har bir bo'linishda faqat belgilarning bir qismi ko'rib chiqiladi
Python
from sklearn.ensemble import RandomForestClassifier

orman = RandomForestClassifier(
    n_estimators=200,
    max_depth=None,
    max_features="sqrt",
    n_jobs=-1,
    random_state=42,
)
orman.fit(X_o, y_o)

print(f"Bitta daraxt: {daraxt_cheksiz.score(X_s, y_s):.3f}")
print(f"Random Forest: {orman.score(X_s, y_s):.3f}")
Natija
Bitta daraxt: 0.933
Random Forest: 0.978
Nima uchun ansambl ishlaydi?

Tasavvur qiling: 100 kishi tanga tashlab bashorat qiladi va har biri 55% to'g'ri javob beradi.

Ularning ko'pchilik ovozi 99% dan yuqori aniqlik beradi - agar ular mustaqil xato qilsa.

Random Forest aynan shuni ta'minlaydi: har bir daraxt boshqa ma'lumot va boshqa belgilarni ko'radi, shuning uchun ular turlicha xato qiladi.

Muhim parametrlar #

ParametrTavsiya
n_estimators100-500; ko'proq har doim yaxshiroq, lekin sekinroq
max_features"sqrt" klassifikatsiya, 1.0 regressiya uchun
max_depthNone odatda yaxshi (ansambl qayta o'qitishni kamaytiradi)
min_samples_leaf1-5; shovqinli ma'lumotda oshiring
n_jobs-1 - barcha yadrolarni ishlatadi
class_weightNomutanosib sinflarda "balanced"
n_estimators ni oshirish xavfsiz

Daraxtlar sonini oshirish qayta o'qitishga olib kelmaydi - u faqat natijani barqarorlashtiradi.

Ma'lum bir nuqtadan keyin yaxshilanish to'xtaydi, lekin yomonlashmaydi.

OOB baholash #

Python
orman = RandomForestClassifier(
    n_estimators=200, oob_score=True, random_state=42, n_jobs=-1,
)
orman.fit(X_o, y_o)

print(f"OOB aniqlik:   {orman.oob_score_:.3f}")
print(f"Sinov aniqlik: {orman.score(X_s, y_s):.3f}")
Natija
OOB aniqlik:   0.962
Sinov aniqlik: 0.978
OOB - bepul validatsiya

Bootstrap da har bir daraxt namunalarning ~63 foizini ko'radi. Qolgan ~37 foiz - out-of-bag (OOB).

Har bir namuna uni ko'rmagan daraxtlar bilan baholanadi. Bu kross-validatsiyaga o'xshash natija beradi, lekin qo'shimcha hisob talab qilmaydi.

Gradient Boosting #

Random Forest daraxtlarni parallel quradi. Boosting esa ketma-ket: har bir yangi daraxt oldingilarining xatolarini tuzatadi.

Python
from sklearn.ensemble import GradientBoostingClassifier, HistGradientBoostingClassifier

gb = GradientBoostingClassifier(
    n_estimators=100,
    learning_rate=0.1,
    max_depth=3,
    random_state=42,
)
gb.fit(X_o, y_o)
print(f"Gradient Boosting: {gb.score(X_s, y_s):.3f}")

# Katta ma'lumot uchun ancha tezroq
hgb = HistGradientBoostingClassifier(random_state=42).fit(X_o, y_o)
print(f"HistGradientBoosting: {hgb.score(X_s, y_s):.3f}")
Random ForestGradient Boosting
DaraxtlarParallel, mustaqilKetma-ket, bog'liq
Har bir daraxtTo'liq o'sadiSayoz (2-5 chuqurlik)
Qayta o'qitishKamKo'proq xavf
SozlashOsonKo'proq e'tibor talab qiladi
Odatiy natijaYaxshiKo'pincha eng yaxshi
TezlikParallel, tezSekinroq
Jadval ma'lumotida boosting - eng yaxshisi

Kaggle musobaqalarida jadval ma'lumoti bilan g'olib chiqadigan yechimlarning katta qismi XGBoost, LightGBM yoki CatBoost ishlatadi.

Terminal
pip install xgboost lightgbm catboost

Neyron tarmoqlar rasm, matn va ovozda ustun; jadvalda esa boosting odatda yaxshiroq ishlaydi.

Regressiya uchun #

Python
from sklearn.ensemble import RandomForestRegressor

model = RandomForestRegressor(n_estimators=200, n_jobs=-1, random_state=42)
model.fit(X_o, y_o)
Daraxtlar ekstrapolyatsiya qila olmaydi

Uy narxlarini 40-150 m2 oralig'ida o'rgangan daraxt, 300 m2 uy uchun o'zi ko'rgan eng katta qiymatni qaytaradi.

Chiziqli regressiya esa chiziqni davom ettirib, mantiqiy javob beradi.

Bashorat o'qitish oralig'idan tashqarida bo'lsa - daraxtlarga ishonmang.

Amaliy topshiriq
  1. Iris ma'lumotida max_depth=2 bilan daraxt quring.
  2. export_text bilan qoidalarni chop eting.
  3. Ularni qo'lda Python funksiyasiga aylantiring.
  4. plot_tree bilan daraxtni chizing.
  5. Chuqurlikni 1 dan 15 gacha o'zgartirib jadval tuzing.
  6. feature_importances_ ni chiqaring va grafikda ko'rsating.
  7. RandomForestClassifier bilan solishtiring.
  8. n_estimators ni 1, 10, 100, 500 qilib natijani kuzating.
  9. oob_score=True qo'shing va sinov natijasi bilan solishtiring.
  10. GradientBoostingClassifier bilan ham sinang - qaysi biri yaxshiroq?

Xulosa #

  • Qaror daraxti ketma-ket savollar berib javobga keladi.
  • Masshtablash kerak emas - bu katta amaliy afzallik.
  • Gini yoki entropiya guruh qanchalik aralashligini o'lchaydi.
  • Cheklanmagan daraxt ma'lumotni yodlab oladi - max_depth ni cheklang.
  • feature_importances_ qaysi belgilar muhimligini ko'rsatadi.
  • Random Forest ko'p daraxt qurib, ularning ovozini oladi.
  • Ikki tasodifiylik: bootstrap namunalar va tasodifiy belgilar.
  • n_estimators ni oshirish xavfsiz - qayta o'qitishga olib kelmaydi.
  • OOB bepul validatsiya beradi.
  • Gradient Boosting ketma-ket xatolarni tuzatadi - jadval ma'lumotida ko'pincha eng yaxshi natija.
  • Daraxtlar ekstrapolyatsiya qila olmaydi.

Keyingi bo'limda SVM va Naive Bayes ni ko'ramiz.

Xatolik topdingizmi?

Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.