IlmHamroh
Data Science va sun'iy intellekt/Model baholash sozlash7/12-dars19 daqiqa
Mundarija (22)

18.7-dars: Ketma-ket qidiruv va erta to'xtash

18-QISM — MODEL BAHOLASH VA SOZLASH · 7-dars


1. Kirish va motivatsiya

RandomizedSearchCV(n_iter=100) har bir nomzodga bir xil resurs beradi: to'liq ma'lumot, to'liq CV. Bu isrof, chunki nomzodlarning ko'pchiligi aniq yomon va buni kichik namunadayoq ko'rish mumkin.

Inson qanday qilardi? Avval hammasini kichik namunada tez sinab, yomonlarini tashlar, qolganlariga ko'proq ma'lumot berardi. Aynan shu g'oya successive halving (ketma-ket yarimlash) deb ataladi va sklearn da HalvingRandomSearchCV sifatida mavjud.

Ikkinchi g'oya — erta to'xtash: iterativ modellar (boosting, SGD, neyron tarmoqlar) uchun iteratsiyalar sonini oldindan belgilash o'rniga, validatsiya balli yaxshilanmay qolganda to'xtatish. Bu n_estimators ni sozlash zaruratini butunlay yo'q qiladi.

Uchinchi g'oya — Bayes optimizatsiyasi: oldingi natijalardan o'rganib, keyingi nomzodni aqlli tanlash.

Bu darsda: halving algoritmi, resurs turlari, HalvingRandomSearchCV sozlamalari, erta to'xtash, Bayes optimizatsiyasining g'oyasi va oddiy amalga oshirilishi, hamda qaysi usul qachon.

Real vaziyat. Jamoada 200 nomzodli qidiruv 6 soat davom etardi. HalvingRandomSearchCV(factor=3) ga o'tgach 50 daqiqaga tushdi va natija amalda bir xil bo'ldi. Sabab: 200 nomzoddan 133 tasi birinchi bosqichdayoq (ma'lumotning 1/9 qismida) tashlab yuborilgan.

Bu darsda ketma-ket qidiruvni o'rganamiz.

Bu darsda:

  • Successive halving
  • Erta to'xtash
  • Resurs turlari
  • Halving sozlamalari
  • Bayes optimizatsiyasi g'oyasi
  • Qaysi usul qachon
  • Tuzoqlar
  • Amaliy: tezkor qidiruv

ℹ Misollar real numpy/sklearn bilan (Python 3.14).


2. Nazariya — chuqur tushuntirish

2.1. Successive halving

text
G'OYA: yomon nomzodlarni ARZON aniqlash mumkin

factor=3, 81 nomzod, resurs = namuna hajmi:

  bosqich 0:  81 nomzod  x  100 qator   =  8100 birlik
  bosqich 1:  27 nomzod  x  300 qator   =  8100 birlik
  bosqich 2:   9 nomzod  x  900 qator   =  8100 birlik
  bosqich 3:   3 nomzod  x 2700 qator   =  8100 birlik
  bosqich 4:   1 nomzod  x 8100 qator   =  8100 birlik

Har bosqichda eng yaxshi 1/factor qismi qoladi.
Umumiy narx: 5 * 8100, to'liq qidiruv esa 81 * 8100

TEZLIK: ~16 barobar

Har bosqichda byudjet bir xil, lekin u kamroq nomzod orasida ko'proq resurs bilan taqsimlanadi.

2.2. Erta to'xtash

text
ITERATIV modellar uchun (boosting, SGD, NN):

HistGradientBoostingClassifier(
    max_iter=1000,
    early_stopping=True,
    validation_fraction=0.1,
    n_iter_no_change=20,
    tol=1e-4)

  -> o'quvning 10% i validatsiyaga ajratiladi
  -> 20 iteratsiya yaxshilanish bo'lmasa to'xtaydi
  -> model.n_iter_ haqiqiy iteratsiyalar soni

FOYDA:
  n_estimators / max_iter ni SOZLASH SHART EMAS
  learning_rate ni kichik qo'yish xavfsiz bo'ladi

DIQQAT: validatsiya qismi o'quvdan olinadi, ya'ni
        CV dan tashqarida emas - leakage yo'q

Erta to'xtash bilan max_iter ni katta qo'ying — model kerakligicha ishlatadi va qidiruv maydoni bir o'lchovga kamayadi.

2.3. Resurs turlari

text
HalvingRandomSearchCV(resource=...)

resource="n_samples" (sukut)
  har bosqichda ko'proq QATOR
  har qanday model uchun ishlaydi

resource="n_estimators" (yoki boshqa parametr)
  har bosqichda ko'proq DARAXT/ITERATSIYA
  ansambllar uchun tabiiy
  max_resources ni qo'lda bering

min_resources="exhaust" -> oxirgi bosqich BUTUN resursni ishlatadi
min_resources="smallest" -> eng kichik mumkin bo'lgan
min_resources=500        -> aniq son

resource="n_estimators" ansambllar uchun ko'pincha yaxshiroq: kichik ansambl katta ansamblning natijasini yaxshi bashorat qiladi.

2.4. Halving sozlamalari

text
factor (sukut 3)
  2 -> ehtiyotkor, ko'proq bosqich, sekinroq
  3 -> muvozanat
  4-5 -> agressiv, yaxshi nomzodni yo'qotish xavfi

n_candidates="exhaust" (HalvingRandomSearchCV, sukut)
  byudjetga qarab nomzodlar sonini avtomatik tanlaydi
  DIQQAT: n_candidates va min_resources IKKALASI ham
  "exhaust" bo'la olmaydi - biri aniq son bo'lsin

aggressive_elimination=True
  resurs yetmasa ham oxirida 1 nomzod qolguncha kesadi

MUAMMO: kichik namunadagi ball katta namunadagini
        yomon bashorat qilsa, halving noto'g'ri tashlaydi

Halving ning asosiy farazi: kichik resursdagi tartib katta resursdagi tartibga o'xshash. Bu faraz buzilsa, halving yaxshi nomzodni erta tashlab yuboradi.

2.5. Bayes optimizatsiyasi g'oyasi

text
TASODIFIY qidiruv: har nomzod MUSTAQIL tanlanadi
BAYES: oldingi natijalardan O'RGANADI

  1. bir necha tasodifiy nuqtani baholang
  2. "surrogat model" quring: parametr -> ball
     (Gauss jarayoni yoki daraxtlar)
  3. keyingi nuqtani tanlang:
       yuqori kutilgan ball (exploitation)
       + yuqori noaniqlik (exploration)
  4. baholang, surrogatni yangilang, qaytaring

FOYDA: kam byudjetda (20-50) tasodifiydan yaxshiroq
KAMCHILIK: ketma-ket (parallellashtirish qiyin),
           qo'shimcha kutubxona kerak (optuna, skopt)

Bayes optimizatsiyasi kam byudjetda foydali; byudjet katta bo'lsa tasodifiy qidiruv bilan farq kamayadi.

2.6. Qaysi usul qachon

text
Bitta fit TEZ (< 1 s) va nomzod kam:
  -> RandomizedSearchCV

Bitta fit SEKIN va nomzod ko'p:
  -> HalvingRandomSearchCV

Model ITERATIV (boosting, SGD, NN):
  -> erta to'xtash + qolgan parametrlarni qidirish

Byudjet juda kichik (20-30 baholash) va fit qimmat:
  -> Bayes (optuna)

Parametr 1-2 ta diskret:
  -> GridSearchCV

Erta to'xtashni birinchi qo'llang: u bepul va qidiruv maydonini kichraytiradi, keyin qolgan parametrlarga halving yoki tasodifiy qidiruv.

2.7. Tuzoqlar

Asosiy tuzoqlar: factor ni juda katta qilish; min_resources ni juda kichik qoldirish (birinchi bosqich ma'nosiz bo'ladi); erta to'xtashda n_iter_no_change ni juda kichik qilish; early_stopping=True bilan max_iter ni kichik qoldirish; halving natijasini to'liq qidiruv bilan taqqoslamaslik; Bayes uchun qo'shimcha kutubxona o'rnatilmaganini unutish; HalvingRandomSearchCV ni experimental importsiz ishlatish.

2.8. Resursni aqlli taqsimlash

Qidiruvni tezlashtirishning uch yo'li bor va ular birga ishlatiladi: erta to'xtash iterativ modellarda iteratsiyalar sonini avtomatik topadi; successive halving yomon nomzodlarni arzon resursda tashlaydi; Bayes optimizatsiyasi kam byudjetda keyingi nuqtani aqlli tanlaydi. Hammasining maqsadi bitta — bir xil natijaga kamroq hisoblash bilan yetish.


3. Tez ma'lumotnoma

python
from sklearn.experimental import enable_halving_search_cv  # noqa: F401
from sklearn.model_selection import (HalvingGridSearchCV,
                                     HalvingRandomSearchCV)

q = HalvingRandomSearchCV(model, taqsimot, factor=3,
                          resource="n_samples",
                          n_candidates=81,          # 'exhaust' bilan birga
                          min_resources="exhaust",  # ikkalasi bo'lmaydi
                          cv=cv, scoring="roc_auc",
                          random_state=0, n_jobs=1).fit(X, y)
print(q.n_resources_, q.n_candidates_)      # bosqichlar tarixi

# erta to'xtash
HistGradientBoostingClassifier(max_iter=2000, early_stopping=True,
                               validation_fraction=0.1,
                               n_iter_no_change=25, random_state=0)
QOIDA: erta to'xtash birinchi · factor=3 · min_resources ni
       tekshir · halving natijasini bir marta tasdiqla

Ketma-ket qidiruv xulosasi

Halving: har bosqichda 1/factor nomzod qoladi
Resurs: n_samples yoki n_estimators
Erta to'xtash: max_iter ni sozlash shart emas
Bayes: kam byudjetda foydali

4. Batafsil misollar

Misollar real numpy/sklearn bilan (Python 3.14).

Misol 1 — Successive halving

python
"""Halving qanday ishlaydi va qancha tejaydi (real numpy/sklearn)."""

import numpy as np
from scipy.stats import loguniform, randint
from sklearn.datasets import make_classification
from sklearn.ensemble import HistGradientBoostingClassifier
from sklearn.experimental import enable_halving_search_cv  # noqa: F401
from sklearn.metrics import roc_auc_score
from sklearn.model_selection import (HalvingRandomSearchCV,
                                     RandomizedSearchCV, StratifiedKFold)


def main() -> None:
    X, y = make_classification(n_samples=24000, n_features=25,
                               n_informative=8, n_redundant=6, flip_y=0.18,
                               class_sep=0.8, random_state=0)
    X_ish, y_ish = X[:4000], y[:4000]
    X_haq, y_haq = X[4000:], y[4000:]
    cv = StratifiedKFold(3, shuffle=True, random_state=0)

    def model():
        return HistGradientBoostingClassifier(max_iter=150,
                                              early_stopping=False,
                                              random_state=0)

    taqsimot = {"learning_rate": loguniform(0.01, 0.5),
                "max_leaf_nodes": randint(4, 80),
                "min_samples_leaf": randint(3, 120)}

    print("=== 1. HalvingRandomSearchCV bosqichlari ===")
    h = HalvingRandomSearchCV(model(), taqsimot, factor=3,
                              resource="n_samples", n_candidates=81,
                              min_resources="exhaust", cv=cv,
                              scoring="roc_auc", random_state=0,
                              n_jobs=1).fit(X_ish, y_ish)
    print(f"  {'bosqich':>8} {'nomzodlar':>11} {'resurs (qator)':>16}")
    for i, (nomzod, resurs) in enumerate(zip(h.n_candidates_,
                                             h.n_resources_)):
        print(f"  {i:>8} {nomzod:>11} {resurs:>16}")
    jami = sum(n * r for n, r in zip(h.n_candidates_, h.n_resources_))
    print(f"  jami ish birligi: {jami}")

    print("\n=== 2. To'liq tasodifiy qidiruv bilan taqqoslash ===")
    n_nomzod = h.n_candidates_[0]
    r = RandomizedSearchCV(model(), taqsimot, n_iter=n_nomzod, cv=cv,
                           scoring="roc_auc", random_state=0,
                           n_jobs=1).fit(X_ish, y_ish)
    toliq = n_nomzod * len(y_ish)
    print(f"  {'usul':<26} {'CV ball':>9} {'ish birligi':>13} "
          f"{'nisbat':>8}")
    print(f"  {'RandomizedSearchCV':<26} {r.best_score_:>9.4f} "
          f"{toliq:>13} {1.0:>7.1f}x")
    print(f"  {'HalvingRandomSearchCV':<26} {h.best_score_:>9.4f} "
          f"{jami:>13} {toliq / jami:>7.1f}x")

    print("\n=== 3. Yakuniy modellar 'haqiqat' to'plamida ===")
    h_haq = roc_auc_score(y_haq,
                          h.best_estimator_.predict_proba(X_haq)[:, 1])
    r_haq = roc_auc_score(y_haq,
                          r.best_estimator_.predict_proba(X_haq)[:, 1])
    print(f"  {'usul':<26} {'haqiqiy AUC':>12}")
    print(f"  {'RandomizedSearchCV':<26} {r_haq:>12.4f}")
    print(f"  {'HalvingRandomSearchCV':<26} {h_haq:>12.4f}")
    print(f"  farq: {h_haq - r_haq:+.4f}")

    print("\n=== 4. factor ning ta'siri ===")
    print(f"  {'factor':>7} {'bosqich':>9} {'boshlang_ich':>13} "
          f"{'ish birligi':>13} {'CV ball':>9}")
    for factor in [2, 3, 5]:
        hf = HalvingRandomSearchCV(model(), taqsimot, factor=factor,
                                   resource="n_samples", n_candidates=64,
                                   min_resources="exhaust", cv=cv,
                                   scoring="roc_auc", random_state=0,
                                   n_jobs=1).fit(X_ish, y_ish)
        ish = sum(n * rr for n, rr in zip(hf.n_candidates_, hf.n_resources_))
        print(f"  {factor:>7} {len(hf.n_candidates_):>9} "
              f"{hf.n_candidates_[0]:>13} {ish:>13} "
              f"{hf.best_score_:>9.4f}")
    print("  ⭐ Halving bir xil natijani bir necha barobar arzon beradi")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. HalvingRandomSearchCV bosqichlari ===
   bosqich   nomzodlar   resurs (qator)
         0          81               49
         1          27              147
         2           9              441
         3           3             1323
         4           1             3969
  jami ish birligi: 19845

=== 2. To'liq tasodifiy qidiruv bilan taqqoslash ===
  usul                         CV ball   ish birligi   nisbat
  RandomizedSearchCV            0.8883        324000     1.0x
  HalvingRandomSearchCV         0.8857         19845    16.3x

=== 3. Yakuniy modellar 'haqiqat' to'plamida ===
  usul                        haqiqiy AUC
  RandomizedSearchCV               0.8995
  HalvingRandomSearchCV            0.8981
  farq: -0.0014

=== 4. factor ning ta'siri ===
   factor   bosqich  boshlang_ich   ish birligi   CV ball
        2         7            64         27776    0.8850
        3         4            64         41884    0.8874
        5         3            64         32640    0.8863
  ⭐ Halving bir xil natijani bir necha barobar arzon beradi

Nima ko'rsatdi: 2.1, 2.4-bo'limlar.

Misol 2 — Erta to'xtash

python
"""max_iter ni sozlash o'rniga erta to'xtash (real numpy/sklearn)."""

import numpy as np
from sklearn.datasets import make_classification
from sklearn.ensemble import HistGradientBoostingClassifier
from sklearn.model_selection import StratifiedKFold, cross_val_score


def main() -> None:
    X, y = make_classification(n_samples=4000, n_features=25,
                               n_informative=8, n_redundant=6, flip_y=0.18,
                               class_sep=0.8, random_state=0)
    cv = StratifiedKFold(4, shuffle=True, random_state=0)

    print("=== 1. max_iter ni qo'lda sozlash ===")
    print(f"  {'lr':>7} {'max_iter':>10} {'CV AUC':>9}")
    qolda = {}
    for lr in [0.3, 0.1, 0.03]:
        for it in [50, 200, 800]:
            m = HistGradientBoostingClassifier(learning_rate=lr, max_iter=it,
                                               early_stopping=False,
                                               random_state=0)
            b = cross_val_score(m, X, y, cv=cv, scoring="roc_auc").mean()
            qolda[(lr, it)] = b
            print(f"  {lr:>7} {it:>10} {b:>9.4f}")
    eng = max(qolda, key=qolda.get)
    print(f"  eng yaxshi: lr={eng[0]}, max_iter={eng[1]} "
          f"({qolda[eng]:.4f}), 9 ta kombinatsiya")

    print("\n=== 2. Erta to'xtash bilan ===")
    print(f"  {'lr':>7} {'CV AUC':>9} {'topilgan iteratsiya':>21}")
    erta = {}
    for lr in [0.3, 0.1, 0.03, 0.01]:
        m = HistGradientBoostingClassifier(learning_rate=lr, max_iter=2000,
                                           early_stopping=True,
                                           validation_fraction=0.15,
                                           n_iter_no_change=25,
                                           random_state=0)
        b = cross_val_score(m, X, y, cv=cv, scoring="roc_auc").mean()
        m.fit(X, y)
        erta[lr] = (b, m.n_iter_)
        print(f"  {lr:>7} {b:>9.4f} {m.n_iter_:>21}")
    eng_lr = max(erta, key=lambda k: erta[k][0])
    print(f"  eng yaxshi: lr={eng_lr} ({erta[eng_lr][0]:.4f}), "
          f"4 ta variant")

    print("\n=== 3. Taqqoslash ===")
    print(f"  {'usul':<28} {'eng yaxshi ball':>17} {'variantlar':>12}")
    print(f"  {'qo_lda (lr x max_iter)':<28} {qolda[eng]:>17.4f} {9:>12}")
    print(f"  {'erta to_xtash (faqat lr)':<28} "
          f"{erta[eng_lr][0]:>17.4f} {4:>12}")
    print(f"  farq: {erta[eng_lr][0] - qolda[eng]:+.4f}")
    print("  erta to'xtash bir o'lchovni butunlay olib tashlaydi")

    print("\n=== 4. n_iter_no_change ta'siri ===")
    print(f"  {'n_iter_no_change':>18} {'CV AUC':>9} {'iteratsiya':>12}")
    for sabr in [3, 10, 25, 60]:
        m = HistGradientBoostingClassifier(learning_rate=0.05, max_iter=2000,
                                           early_stopping=True,
                                           validation_fraction=0.15,
                                           n_iter_no_change=sabr,
                                           random_state=0)
        b = cross_val_score(m, X, y, cv=cv, scoring="roc_auc").mean()
        m.fit(X, y)
        print(f"  {sabr:>18} {b:>9.4f} {m.n_iter_:>12}")
    print("  juda kichik sabr -> erta to'xtab qoladi")
    print("  ⭐ max_iter ni katta qo'ying, to'xtashni modelga qoldiring")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. max_iter ni qo'lda sozlash ===
       lr   max_iter    CV AUC
      0.3         50    0.8895
      0.3        200    0.8946
      0.3        800    0.8943
      0.1         50    0.8957
      0.1        200    0.8953
      0.1        800    0.8961
     0.03         50    0.8927
     0.03        200    0.8973
     0.03        800    0.8963
  eng yaxshi: lr=0.03, max_iter=200 0.8973-bob, 9 ta kombinatsiya

=== 2. Erta to'xtash bilan ===
       lr    CV AUC   topilgan iteratsiya
      0.3    0.8880                    39
      0.1    0.8945                    61
     0.03    0.8944                   147
     0.01    0.8950                   393
  eng yaxshi: lr=0.01 0.8950-bob, 4 ta variant

=== 3. Taqqoslash ===
  usul                           eng yaxshi ball   variantlar
  qo_lda (lr x max_iter)                  0.8973            9
  erta to_xtash (faqat lr)                0.8950            4
  farq: -0.0023
  erta to'xtash bir o'lchovni butunlay olib tashlaydi

=== 4. n_iter_no_change ta'siri ===
    n_iter_no_change    CV AUC   iteratsiya
                   3    0.8948           70
                  10    0.8950           81
                  25    0.8945           96
                  60    0.8943          131
  juda kichik sabr -> erta to'xtab qoladi
  ⭐ max_iter ni katta qo'ying, to'xtashni modelga qoldiring

Nima ko'rsatdi: 2.2-bo'lim.

Misol 3 — Resurs turi va halving farazi

python
"""n_samples va n_estimators resurslari (real numpy/sklearn)."""

import numpy as np
from scipy.stats import randint, uniform
from sklearn.datasets import make_classification
from sklearn.ensemble import RandomForestClassifier
from sklearn.experimental import enable_halving_search_cv  # noqa: F401
from sklearn.model_selection import (HalvingRandomSearchCV, StratifiedKFold,
                                     cross_val_score)


def main() -> None:
    X, y = make_classification(n_samples=5000, n_features=30,
                               n_informative=9, n_redundant=8, flip_y=0.18,
                               class_sep=0.8, random_state=0)
    cv = StratifiedKFold(3, shuffle=True, random_state=0)
    taqsimot = {"max_features": uniform(0.1, 0.7),
                "min_samples_leaf": randint(1, 50)}

    print("=== 1. resource='n_samples' ===")
    h1 = HalvingRandomSearchCV(
        RandomForestClassifier(n_estimators=150, random_state=0, n_jobs=1),
        taqsimot, factor=3, resource="n_samples", n_candidates=27,
        min_resources="exhaust", cv=cv, scoring="roc_auc",
        random_state=0, n_jobs=1).fit(X, y)
    print(f"  {'bosqich':>8} {'nomzod':>8} {'qator':>8}")
    for i, (n, r) in enumerate(zip(h1.n_candidates_, h1.n_resources_)):
        print(f"  {i:>8} {n:>8} {r:>8}")
    print(f"  ball: {h1.best_score_:.4f}")

    print("\n=== 2. resource='n_estimators' ===")
    h2 = HalvingRandomSearchCV(
        RandomForestClassifier(random_state=0, n_jobs=1),
        taqsimot, factor=3, resource="n_estimators",
        max_resources=243, min_resources=3, cv=cv, scoring="roc_auc",
        random_state=0, n_jobs=1).fit(X, y)
    print(f"  {'bosqich':>8} {'nomzod':>8} {'daraxt':>8}")
    for i, (n, r) in enumerate(zip(h2.n_candidates_, h2.n_resources_)):
        print(f"  {i:>8} {n:>8} {r:>8}")
    print(f"  ball: {h2.best_score_:.4f}")

    print("\n=== 3. Halving farazi: kichik resurs tartibni saqlaydimi ===")
    rng = np.random.default_rng(0)
    nomzodlar = []
    for _ in range(12):
        nomzodlar.append({"max_features": float(rng.uniform(0.1, 0.8)),
                          "min_samples_leaf": int(rng.integers(1, 50))})
    print(f"  {'nomzod':>7} {'500 qator':>11} {'5000 qator':>12} "
          f"{'o_rin(500)':>11} {'o_rin(5000)':>12}")
    kichik, katta = [], []
    for p in nomzodlar:
        m = RandomForestClassifier(n_estimators=100, random_state=0,
                                   n_jobs=1, **p)
        kichik.append(cross_val_score(m, X[:500], y[:500], cv=cv,
                                      scoring="roc_auc").mean())
        katta.append(cross_val_score(m, X, y, cv=cv,
                                     scoring="roc_auc").mean())
    kichik, katta = np.array(kichik), np.array(katta)
    o_kichik = len(kichik) - kichik.argsort().argsort()
    o_katta = len(katta) - katta.argsort().argsort()
    for i in range(len(nomzodlar)):
        print(f"  {i:>7} {kichik[i]:>11.4f} {katta[i]:>12.4f} "
              f"{o_kichik[i]:>11} {o_katta[i]:>12}")

    print("\n=== 4. Tartiblar mosligi ===")
    korr = float(np.corrcoef(kichik, katta)[0, 1])
    spearman = float(np.corrcoef(o_kichik, o_katta)[0, 1])
    print(f"  ballar korrelyatsiyasi: {korr:.4f}")
    print(f"  o'rinlar korrelyatsiyasi: {spearman:.4f}")
    top4_kichik = set(np.argsort(-kichik)[:4].tolist())
    top4_katta = set(np.argsort(-katta)[:4].tolist())
    print(f"  kichikda eng yaxshi 4 ta: {sorted(top4_kichik)}")
    print(f"  kattada eng yaxshi 4 ta:  {sorted(top4_katta)}")
    print(f"  kesishish: {len(top4_kichik & top4_katta)}/4")
    print("  kesishish katta bo'lsa halving xavfsiz")
    print("  ⭐ Halving faraziga tayanadi - uni tekshirib ko'ring")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. resource='n_samples' ===
   bosqich   nomzod    qator
         0       27      185
         1        9      555
         2        3     1665
         3        1     4995
  ball: 0.8918

=== 2. resource='n_estimators' ===
   bosqich   nomzod   daraxt
         0       81        3
         1       27        9
         2        9       27
         3        3       81
         4        1      243
  ball: 0.8895

=== 3. Halving farazi: kichik resurs tartibni saqlaydimi ===
   nomzod   500 qator   5000 qator  o_rin(500)  o_rin(5000)
        0      0.7352       0.8759           7            6
        1      0.7453       0.8769           5            5
        2      0.7666       0.8783           3            4
        3      0.7073       0.8684          10            9
        4      0.6886       0.8645          12           11
        5      0.7157       0.8704           9            8
        6      0.7619       0.8832           4            3
        7      0.7243       0.8563           8           12
        8      0.7361       0.8745           6            7
        9      0.7827       0.8890           1            1
       10      0.7798       0.8880           2            2
       11      0.7033       0.8659          11           10

=== 4. Tartiblar mosligi ===
  ballar korrelyatsiyasi: 0.8632
  o'rinlar korrelyatsiyasi: 0.9161
  kichikda eng yaxshi 4 ta: [2, 6, 9, 10]
  kattada eng yaxshi 4 ta:  [2, 6, 9, 10]
  kesishish: 4/4
  kesishish katta bo'lsa halving xavfsiz
  ⭐ Halving faraziga tayanadi - uni tekshirib ko'ring

Nima ko'rsatdi: 2.3, 2.4-bo'limlar.

Misol 4 — Bayes optimizatsiyasi g'oyasi

python
"""Oddiy surrogat-asosli qidiruv (real numpy/sklearn)."""

import numpy as np
from sklearn.datasets import make_classification
from sklearn.ensemble import HistGradientBoostingClassifier
from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.gaussian_process.kernels import RBF, ConstantKernel, WhiteKernel
from sklearn.model_selection import StratifiedKFold, cross_val_score


def main() -> None:
    X, y = make_classification(n_samples=2500, n_features=22,
                               n_informative=7, n_redundant=5, flip_y=0.2,
                               class_sep=0.8, random_state=0)
    cv = StratifiedKFold(3, shuffle=True, random_state=0)

    def baho(log_lr: float, barglar: int) -> float:
        m = HistGradientBoostingClassifier(
            learning_rate=float(10 ** log_lr),
            max_leaf_nodes=int(barglar), max_iter=150,
            early_stopping=False, random_state=0)
        return cross_val_score(m, X, y, cv=cv, scoring="roc_auc").mean()

    rng = np.random.default_rng(0)
    chegaralar = np.array([[-2.0, -0.3], [5, 70]])   # log10(lr), barglar

    def tasodifiy_nuqtalar(nechta: int) -> np.ndarray:
        a = rng.uniform(chegaralar[0, 0], chegaralar[0, 1], nechta)
        b = rng.integers(chegaralar[1, 0], chegaralar[1, 1] + 1, nechta)
        return np.column_stack([a, b.astype(float)])

    print("=== 1. Tasodifiy qidiruv (20 baholash) ===")
    tasodif_X = tasodifiy_nuqtalar(20)
    tasodif_y = np.array([baho(p[0], p[1]) for p in tasodif_X])
    eng_t = int(np.argmax(tasodif_y))
    print(f"  eng yaxshi ball: {tasodif_y.max():.4f}")
    print(f"  lr={10 ** tasodif_X[eng_t, 0]:.4f}, "
          f"barglar={int(tasodif_X[eng_t, 1])}")
    print(f"  eng yaxshi ball qaysi qadamda topildi: {eng_t + 1}")

    print("\n=== 2. Surrogat-asosli qidiruv (5 boshlang'ich + 15) ===")
    kuzatilgan_X = tasodifiy_nuqtalar(5)
    kuzatilgan_y = np.array([baho(p[0], p[1]) for p in kuzatilgan_X])
    yadro = (ConstantKernel(1.0) * RBF(length_scale=[0.5, 15.0])
             + WhiteKernel(noise_level=1e-4,
                           noise_level_bounds=(1e-12, 1e2)))
    tarix = [float(kuzatilgan_y.max())]
    for qadam in range(15):
        gp = GaussianProcessRegressor(kernel=yadro, normalize_y=True,
                                      random_state=0)
        gp.fit(kuzatilgan_X, kuzatilgan_y)
        nomzod = tasodifiy_nuqtalar(500)
        o_rtacha, std = gp.predict(nomzod, return_std=True)
        # yuqori ishonch chegarasi: foydalanish + izlanish
        ucb = o_rtacha + 1.5 * std
        tanlov = nomzod[int(np.argmax(ucb))]
        ball = baho(tanlov[0], tanlov[1])
        kuzatilgan_X = np.vstack([kuzatilgan_X, tanlov])
        kuzatilgan_y = np.append(kuzatilgan_y, ball)
        tarix.append(float(kuzatilgan_y.max()))
    eng_b = int(np.argmax(kuzatilgan_y))
    print(f"  eng yaxshi ball: {kuzatilgan_y.max():.4f}")
    print(f"  lr={10 ** kuzatilgan_X[eng_b, 0]:.4f}, "
          f"barglar={int(kuzatilgan_X[eng_b, 1])}")

    print("\n=== 3. Eng yaxshi ball qanday o'sdi ===")
    tasodif_tarix = np.maximum.accumulate(tasodif_y)
    print(f"  {'baholash':>10} {'tasodifiy':>11} {'surrogat':>10}")
    for i in [1, 5, 10, 15, 20]:
        print(f"  {i:>10} {tasodif_tarix[i - 1]:>11.4f} "
              f"{tarix[min(i - 1, len(tarix) - 1)]:>10.4f}")

    print("\n=== 4. Xulosa ===")
    print(f"  {'usul':<22} {'20 baholashdagi ball':>22}")
    print(f"  {'tasodifiy':<22} {tasodif_y.max():>22.4f}")
    print(f"  {'surrogat (GP+UCB)':<22} {kuzatilgan_y.max():>22.4f}")
    print(f"  farq: {kuzatilgan_y.max() - tasodif_y.max():+.4f}")
    print("  amaliyotda optuna/skopt kabi kutubxonalar ishlatiladi")
    print("  ⭐ Bayes: oldingi natijalardan o'rganib nuqta tanlash")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Tasodifiy qidiruv (20 baholash) ===
  eng yaxshi ball: 0.8582
  lr=0.0199, barglar=69
  eng yaxshi ball qaysi qadamda topildi: 16

=== 2. Surrogat-asosli qidiruv (5 boshlang'ich + 15) ===
  eng yaxshi ball: 0.8590
  lr=0.0198, barglar=45

=== 3. Eng yaxshi ball qanday o'sdi ===
    baholash   tasodifiy   surrogat
           1      0.8523     0.8585
           5      0.8523     0.8585
          10      0.8536     0.8590
          15      0.8554     0.8590
          20      0.8582     0.8590

=== 4. Xulosa ===
  usul                     20 baholashdagi ball
  tasodifiy                              0.8582
  surrogat (GP+UCB)                      0.8590
  farq: +0.0008
  amaliyotda optuna/skopt kabi kutubxonalar ishlatiladi
  ⭐ Bayes: oldingi natijalardan o'rganib nuqta tanlash

Nima ko'rsatdi: 2.5-bo'lim.


5. To'g'ri va noto'g'ri tushunishlar

Noto'g'ri fikr To'g'risi
"Halving har doim tezroq va bir xil" Farazga tayanadi
"factor katta — yaxshiroq" Yaxshi nomzodni yo'qotish xavfi
"Erta to'xtash leakage beradi" Validatsiya o'quvdan olinadi
"max_iter ni ham sozlash kerak" Erta to'xtash bilan yo'q
"Bayes har doim ustun" Katta byudjetda farq kamayadi
"Halving import siz ishlaydi" enable_halving_search_cv kerak
"n_iter_no_change=3 yetarli" Juda erta to'xtaydi
"Resurs faqat n_samples" n_estimators ham bo'ladi

6. Keng tarqalgan xatolar va yechimlari

1. Import unutilgan

python
from sklearn.model_selection import HalvingRandomSearchCV   # ImportError  # ⚠️
from sklearn.experimental import enable_halving_search_cv   # noqa: F401   # ✅

2. Erta to'xtash bilan kichik max_iter

python
HistGradientBoostingClassifier(max_iter=100, early_stopping=True)  # ⚠️
HistGradientBoostingClassifier(max_iter=2000, early_stopping=True) # ✅

3. Juda agressiv factor

python
HalvingRandomSearchCV(m, t, factor=10)                           # ⚠️
HalvingRandomSearchCV(m, t, factor=3)                            # ✅

4. max_iter ni ham qidirish

python
{"learning_rate": [...], "max_iter": [...]}    # erta to'xtash bor # ⚠️
{"learning_rate": [...]}                                          # ✅

5. Kichik sabr

python
n_iter_no_change=2                                               # ⚠️
n_iter_no_change=25                                              # ✅

6. Halving natijasini tekshirmaslik

python
model = h.best_estimator_   # darhol ishlab chiqarishga           # ⚠️
# alohida testda yoki to'liq CV da bir marta tasdiqlang           # ✅

7. min_resources juda kichik

python
HalvingRandomSearchCV(m, t, min_resources=20)   # 20 qator        # ⚠️
HalvingRandomSearchCV(m, t, n_candidates=81,
                      min_resources="exhaust")                   # ✅

7. Integratsiya — bu bilim qayerda kerak bo'ladi

  • 15.9-dars (o'tilgan): Boostingni sozlash
  • 18.5-dars (o'tilgan): Giperparametrlar
  • 18.6-dars (o'tilgan): Grid va random search
  • 18.12-dars: Amaliyot
  • 23-qism: PyTorch da erta to'xtash

8. Eng yaxshi amaliyotlar

  1. Erta to'xtashdan boshlang.

  2. max_iter ni katta qo'ying.

  3. factor=3 dan boshlang.

  4. min_resources="exhaust".

  5. Halving farazini tekshiring.

  6. Natijani bir marta tasdiqlang.

  7. Byudjet kichik bo'lsa Bayes ni ko'ring.

  8. Bosqichlar tarixini chop eting.


9. Amaliy topshiriq

Vazifa 1: Bashorat qiling

python
1.  # halving g'oyasi?
2.  # factor=3 da har bosqichda necha qoladi?
3.  # resurs turlari?
4.  # halving farazi?
5.  # erta to'xtash nima beradi?
6.  # n_iter_no_change nima?
7.  # validation_fraction qayerdan olinadi?
8.  # max_iter qanday qo'yiladi?
9.  # Bayes g'oyasi?
10. # surrogat model nima?
11. # UCB nima?
12. # Bayes qachon foydali?
Javoblar
  1. Yomon nomzodlarni arzon resursda tashlash
  2. 1/3
  3. n_samples, n_estimators
  4. Kichik resursdagi tartib kattadagiga o'xshash
  5. max_iter ni sozlash zaruratini yo'qotadi
  6. Necha iteratsiya yaxshilanmasa to'xtash
  7. O'quv to'plamidan
  8. Katta (2000)
  9. Oldingi natijalardan o'rganish
  10. Parametr → ball bashoratchisi
  11. O'rtacha + noaniqlik
  12. Kam byudjet, qimmat fit

Vazifa 2: Xatolarni tuzating

python
1.  from sklearn.model_selection import HalvingRandomSearchCV

2.  HistGradientBoostingClassifier(max_iter=100, early_stopping=True)

3.  HalvingRandomSearchCV(m, t, factor=10)

4.  {"learning_rate": [...], "max_iter": [...]}   # erta to'xtash bor

5.  n_iter_no_change=2
Javoblar
python
1.  from sklearn.experimental import enable_halving_search_cv  # noqa: F401

2.  HistGradientBoostingClassifier(max_iter=2000, early_stopping=True)

3.  HalvingRandomSearchCV(m, t, factor=3)

4.  {"learning_rate": [...]}

5.  n_iter_no_change=25

Vazifa 3: Halving

Modellang:

  1. Bosqichlar
  2. Taqqoslash
  3. Haqiqat
  4. factor

Vazifa 4: Erta to'xtash

Modellang:

  1. Qo'lda sozlash
  2. Erta to'xtash
  3. Taqqoslash
  4. Sabr

Vazifa 5: Resurs

Modellang:

  1. n_samples
  2. n_estimators
  3. Faraz
  4. Tartiblar

Vazifa 6: Bayes

Modellang:

  1. Tasodifiy
  2. Surrogat
  3. O'sish
  4. Xulosa

Vazifa 7: O'ylash

HalvingRandomSearchCV natijasi RandomizedSearchCV dan 0.015 ga past chiqdi. Nima bo'lgan bo'lishi mumkin va qanday tekshirasiz?

Javob

Qisqa javob: ehtimol halving farazi buzilgan — kichik namunadagi tartib katta namunadagiga mos kelmagan va yaxshi nomzod birinchi bosqichda tashlab yuborilgan.

1. Asosiy sabablar

Sabab Belgisi Yechim
min_resources juda kichik Birinchi bosqich 50-100 qator min_resources="exhaust"
factor juda katta Bosqichlar soni 2-3 factor=2 yoki 3
Model kichik namunada boshqacha ishlaydi Murakkab modellar (chuqur daraxt) resource="n_estimators"
Sinf nomutanosib Kichik namunada musbat 5-10 ta min_resources ni oshiring
Shunchaki tasodif Farq std ichida Ikkalasini takrorlang

2. Tekshirish tartibi

python
# 1. bosqichlar tarixini ko'ring
print(list(zip(h.n_candidates_, h.n_resources_)))
# birinchi bosqichda necha qator bo'lgan?

# 2. farq shovqin ichidami
print(h.best_score_, h.cv_results_["std_test_score"][h.best_index_])

# 3. FARAZNI tekshiring: bir necha nomzodni
#    kichik va katta namunada baholab, o'rinlarni solishtiring

3. Faraz tekshiruvi

python
nomzodlar = tasodifiy_parametrlar(12)
kichik = [CV(par, X[:min_resources]) for par in nomzodlar]
katta = [CV(par, X) for par in nomzodlar]
# eng yaxshi 4 talik kesishishi 3/4 dan kam -> halving xavfli

4. Sozlash tavsiyalari

  1. min_resources="exhaust" — oxirgi bosqich butun ma'lumotni ishlatadi, birinchisi ham mantiqiy kattalikda bo'ladi.
  2. factor=2 — ehtiyotkorroq, bosqich ko'p, lekin xato kam.
  3. aggressive_elimination=False (sukut) — resurs yetmasa kesishni to'xtatadi.
  4. Ansambllar uchun resource="n_estimators", min_resources=10 — kichik ansambl kattasining natijasini yaxshi bashorat qiladi.

5. Qachon halvingdan voz kechish kerak

  • Ma'lumot kichik (n < 2000): birinchi bosqichda juda kam qator qoladi.
  • Model natijasi namuna hajmiga kuchli bog'liq (o'rganish egri chizig'i tik).
  • Sinf juda nomutanosib (musbat < 2%).

Bunday hollarda oddiy RandomizedSearchCV ishonchliroq.

6. Xulosa

  1. Bosqichlar tarixini ko'ring
  2. Farqni std bilan solishtiring
  3. Farazni 10-12 nomzodda tekshiring
  4. min_resources va factor ni sozlang
  5. Kichik ma'lumotda halvingdan voz keching

Nimani mustahkamlaydi: 2.1, 2.4-bo'limlar.


Xulosa

Bu darsda ketma-ket qidiruv usullarini o'rgandik.

Eng muhim uch fikr:

  1. Erta to'xtashdan boshlang — u bepul. Iterativ modellarda (HistGradientBoosting, SGD, neyron tarmoqlar) max_iter ni katta qo'ying va early_stopping=True, n_iter_no_change=20..30 bering. Bu qidiruv maydonidan butun bir o'lchovni olib tashlaydi va kichik learning_rate ishlatishni xavfsiz qiladi.

  2. HalvingRandomSearchCV yomon nomzodlarni arzon resursda tashlaydi. factor=3 bilan har bosqichda nomzodlarning uchdan biri qoladi va resurs uch barobar oshadi; umumiy narx to'liq qidiruvdan bir necha barobar kam. Ammo u farazga tayanadi: kichik resursdagi tartib katta resursdagiga o'xshash bo'lishi kerak. Faraz shubhali bo'lsa (kichik ma'lumot, nomutanosib sinf), uni 10-12 nomzodda tekshiring.

  3. Bayes optimizatsiyasi kam byudjetda foydali. U oldingi natijalardan surrogat model quradi va keyingi nuqtani kutilgan ball hamda noaniqlik muvozanatida tanlaydi. 20-50 baholash bilan tasodifiy qidiruvdan ustun chiqishi mumkin, lekin byudjet katta bo'lsa farq kamayadi va parallellashtirish qiyinlashadi.

Keyingi darsda o'rganish egri chiziqlarini ko'rib chiqamiz: learning_curve va validation_curve yordamida "ko'proq ma'lumot kerakmi yoki murakkabroq model?" degan savolga javob topamiz.

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!