IlmHamroh
Data Science va sun'iy intellekt/ML asoslari3/10-dars17 daqiqa
Mundarija (22)

12.3-dars: Train, validation, test va cross-validation

12-QISM — MACHINE LEARNING ASOSLARI · 3-dars


1. Kirish va motivatsiya

ML ning markaziy savoli: "Model yangi ma'lumotda qanday ishlaydi?". Javobni faqat bitta yo'l bilan olish mumkin — modelni ko'rmagan ma'lumotda sinash. Shu sababli ma'lumot bo'linadi: train (o'qitish), validation (model va giperparametr tanlash), test (yakuniy, bir martalik baho).

Bu — 8.8-darsdagi mustaqil tekshiruv g'oyasining ML dagi shakli. Ammo amalda ko'p nozik joylar bor: kichik ma'lumotda bitta bo'linish tasodifiy bo'ladi (cross-validation kerak), sinflar nomutanosib bo'lsa stratifikatsiya kerak, bir foydalanuvchining ko'p qatori bo'lsa guruh bo'yicha ajratish kerak, vaqt qatorlarida esa kelajakdan o'tmishga bashorat qilib bo'lmaydi.

Real vaziyat. Jamoa model tanlash uchun 15 ta variantni sinadi va har birini test to'plamida baholaydi; eng yaxshisini tanlaydi (test aniqligi 0.91). Ishlab chiqarishda aniqlik 0.84 chiqadi. Sabab: test to'plami 15 marta ishlatilgani uchun u endi "mustaqil" emas — model shu to'plamga moslab tanlandi (11.9 dagi ko'p taqqoslash muammosining ML shakli). To'g'ri yo'l: model tanlashni validation (yoki cross-validation) da qilish, test to'plamini esa oxirida bir marta ochish.

Bu darsda ma'lumotni ajratish va validatsiyani o'rganamiz.

Bu darsda:

  • Uch to'plam: train, validation, test
  • Cross-validation (K-fold)
  • Stratifikatsiya (nomutanosib sinflar)
  • Guruh bo'yicha ajratish (klasterlangan ma'lumot)
  • Vaqt qatorlari uchun ajratish
  • Ichma-ich (nested) CV va halol baholash
  • Ajratish tuzoqlari
  • Amaliy: to'g'ri validatsiya sxemasi

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


2. Nazariya — chuqur tushuntirish

2.1. Uch to'plam

text
TRAIN (60-80%)      — model parametrlarini o'rganadi (fit)
VALIDATION (10-20%) — model va giperparametr tanlash (ko'p marta ishlatiladi)
TEST (10-20%)       — YAKUNIY baho, BIR MARTA ochiladi

Nega uchta?
  train'da baholash — yodlash (12.1, Misol 3)
  validation'da ko'p tanlov qilinsa — unga ham "moslashish" boshlanadi
  test — halol baho uchun daxlsiz qoladi

Uch to'plam qoidasi — halol baholashning asosi. Validation to'plami "sarflanadigan" resurs: unda qancha ko'p qaror qabul qilinsa, u shunchalik optimistik bo'ladi 11.9-bob. Test to'plami — bir martalik: natija e'lon qilingandan keyin unga qaytib model tanlash mumkin emas. Amalda test ko'pincha vaqt bo'yicha ajratiladi (eng yangi davr) — chunki ishlab chiqarishda model aynan kelajakda ishlaydi.

2.2. Cross-validation

text
K-FOLD (K = 5 odatiy):
  ma'lumot 5 bo'lakka bo'linadi; har safar 4 bo'lakda o'qitiladi, 1 da baholanadi
  → 5 ta baho; o'rtacha va SD hisoblanadi

Afzalligi: butun ma'lumotdan foydalanadi, baho barqarorroq (bitta bo'linish tasodifi yo'q)
Narxi:     K marta o'qitish (hisoblash vaqti)

from sklearn.model_selection import cross_val_score, KFold
cross_val_score(model, X, y, cv=5, scoring="r2")

Cross-validation — kichik va o'rta ma'lumotda standart usul: bitta holdout bo'linishi tasodifiy bo'lishi mumkin, CV esa K ta bahoning o'rtachasini beradi va noaniqlikni (SD) ko'rsatadi. Odatiy K = 5 yoki 10. Juda kichik ma'lumotda — LOO (leave-one-out, K = n): kam siljish, lekin katta dispersiya va qimmat. CV — model tanlash va giperparametr sozlash uchun; test to'plami baribir alohida qoladi.

2.3. Stratifikatsiya

text
Nomutanosib sinflar (2% firibgar): tasodifiy bo'linishda bo'laklarda sinf ulushi farq qiladi
  → baholar beqaror, ba'zi bo'lakda musbat sinf umuman bo'lmasligi mumkin

YECHIM: stratifikatsiya — har bo'lakda sinf ulushi asl ulushga teng
  train_test_split(..., stratify=y)
  StratifiedKFold(n_splits=5, shuffle=True, random_state=0)
  cross_val_score(clf, X, y, cv=5)      # klassifikatsiyada standart — Stratified

Stratifikatsiya — klassifikatsiyada deyarli har doim kerak, ayniqsa sinflar nomutanosib bo'lsa 12.7-bob. sklearn cross_val_score klassifikator uchun standart holatda StratifiedKFold ishlatadi, lekin train_test_split da stratify=y ni qo'lda ko'rsatish kerak. Regressiyada kerak emas, lekin kuchli qiyshiq nishonda kvantillar bo'yicha stratifikatsiya foydali bo'lishi mumkin.

2.4. Guruh bo'yicha ajratish

text
Klasterlangan ma'lumot: bir foydalanuvchining 20 sessiyasi, bir bemorning 5 tashrifi
  tasodifiy ajratishda BIR foydalanuvchi ham train'da, ham test'da bo'ladi
  → model uni "tanib qoladi" → optimistik baho (11.3 dagi soxta mustaqillik)

YECHIM: guruh bo'yicha ajratish
  GroupShuffleSplit, GroupKFold, StratifiedGroupKFold
  cross_val_score(model, X, y, cv=GroupKFold(5), groups=user_id)

Guruh bo'yicha ajratish — ML dagi eng ko'p e'tibordan chetda qoladigan qoida. Guruh — bir-biriga bog'liq kuzatuvlar to'plami: foydalanuvchi, bemor, do'kon, hujjat. Agar guruh ikki to'plamga bo'linib ketsa, baho haqiqatdan yuqori chiqadi (model shaxsiy xususiyatlarni yodlab oladi). Qoida: bashorat qilinadigan birlik — ajratish birligi.

2.5. Vaqt qatorlari uchun ajratish

text
Vaqt bilan bog'liq ma'lumotda tasodifiy ajratish — leakage (kelajakdan o'tmishga)

TO'G'RI: vaqt bo'yicha ajratish
  train: yanvar-sentabr    test: oktabr-dekabr

TimeSeriesSplit: kengayuvchi oyna
  fold 1: train [1..100]      test [101..120]
  fold 2: train [1..120]      test [121..140]
  ...

Qo'shimcha: "gap" (bo'shliq) — nishon oynasi bilan ustma-ust tushmaslik uchun

Vaqt tartibi muhim bo'lsa (talab, narx, churn, moliyaviy ma'lumot), ajratish vaqt bo'yicha bo'lishi shart: model faqat o'tmishni ko'rib, kelajakni bashorat qiladi. TimeSeriesSplit — bir necha "kengayuvchi oyna" bo'linishi. Bu 12.2 dagi vaqt kesimi g'oyasining validatsiya darajasidagi davomi.

2.6. Ichma-ich (nested) CV

text
Muammo: giperparametrni CV bilan tanlab, o'sha CV bahosini "yakuniy natija" deb olish —
        optimistik (CV ma'lumotiga moslashish)

NESTED CV:
  tashqi halqa (5-fold): halol baho
    ichki halqa (5-fold): giperparametr tanlash
  → 25 marta o'qitish, lekin siljimagan baho

Amalda: kichik ma'lumotda nested CV; katta ma'lumotda alohida test to'plami yetarli

Nested CV — "model tanlash bahosi" va "model sifati bahosi" ni ajratadi. Oddiy (nested emas) CV da giperparametr tanlash uchun ishlatilgan bahoni yakuniy deb e'lon qilish — optimizm manbai 11.9-bob. Katta ma'lumotda soddaroq yechim: train/validation/test uch bo'linishi.

2.7. Ajratish tuzoqlari

Asosiy tuzoqlar: test bilan model tanlash (test — bir martalik); fit ni butun ma'lumotda (scaler, imputer — faqat train'da, 12.9); stratifikatsiyasiz nomutanosib sinf; guruhni bo'lib yuborish (user ikki to'plamda); vaqt qatorida tasodifiy ajratish; dublikatlar (bir xil qator train va testda — sun'iy yuqori baho); random_state yo'q (takrorlanmaydi); juda kichik test (baho beqaror — SD ni ko'ring); CV natijasini SD siz hisobot qilish.

2.8. Validatsiya — halol bahoning asosi

Ma'lumot train (o'qitish), validation (tanlov) va test (yakuniy, bir martalik) ga bo'linadi. Cross-validation — bitta bo'linish tasodifini yo'qotadi va noaniqlikni (SD) ko'rsatadi. Stratifikatsiya — nomutanosib sinflarda; guruh bo'yicha ajratish — klasterlangan ma'lumotda (bir foydalanuvchi bir to'plamda); vaqt bo'yicha — vaqt qatorlarida (TimeSeriesSplit). Nested CV — giperparametr tanlash va halol baholashni ajratadi. Keyingi dars — overfitting va underfitting: model murakkabligi va umumlashtirish.


3. Tez ma'lumotnoma

python
import numpy as np
from sklearn.model_selection import (GroupKFold, GroupShuffleSplit, KFold,
                                     StratifiedKFold, TimeSeriesSplit,
                                     cross_val_score, cross_validate, train_test_split)

X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.2, random_state=0, stratify=y)

cross_val_score(model, X_tr, y_tr, cv=5, scoring="roc_auc")            # klassifikatsiya
cross_val_score(model, X_tr, y_tr, cv=KFold(5, shuffle=True, random_state=0))  # regressiya

# guruh bo'yicha
cross_val_score(model, X, y, cv=GroupKFold(5), groups=guruhlar)

# vaqt bo'yicha
for tr, te in TimeSeriesSplit(n_splits=5).split(X): ...

# ko'p metrika va vaqt
cross_validate(model, X, y, cv=5, scoring=["accuracy", "roc_auc"], return_train_score=True)
QOIDA: test — bir marta · stratify · guruh bo'yicha · vaqtda tartib bilan · SD ni ko'rsat

Validatsiya xulosasi

Train — o'qitish; validation — tanlov; test — yakuniy (bir marta)
CV (K=5) — barqaror baho + SD; kichik ma'lumotda ayniqsa muhim
Stratifikatsiya — nomutanosib sinflar
Guruh bo'yicha — bir foydalanuvchi bir to'plamda
Vaqt bo'yicha — kelajakdan o'tmishga bashorat yo'q
Nested CV — tanlov va baholashni ajratadi

4. Batafsil misollar

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

Misol 1 — Bitta bo'linish tasodifi va CV

python
"""Holdout bahosi tasodifiy tebranadi; CV barqarorroq (real numpy/sklearn)."""

import numpy as np
from sklearn.linear_model import Ridge
from sklearn.model_selection import KFold, cross_val_score, train_test_split


def main() -> None:
    rng = np.random.default_rng(0)
    n = 200
    X = rng.normal(size=(n, 5))
    y = X @ np.array([2.0, -1.0, 0.5, 0.0, 0.0]) + rng.normal(0, 1.5, n)

    print("=== 1. 10 xil tasodifiy holdout (20% test) ===")
    ballar = []
    for seed in range(10):
        Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.2, random_state=seed)
        ballar.append(Ridge(alpha=1.0).fit(Xtr, ytr).score(Xte, yte))
    ballar = np.array(ballar)
    print(f"  R^2: min {ballar.min():.3f}, max {ballar.max():.3f}, "
          f"o'rtacha {ballar.mean():.3f} (SD {ballar.std():.3f})")

    print("\n=== 2. 5-fold cross-validation ===")
    cv = KFold(n_splits=5, shuffle=True, random_state=0)
    cvb = cross_val_score(Ridge(alpha=1.0), X, y, cv=cv, scoring="r2")
    print(f"  bo'laklar: {np.round(cvb, 3).tolist()}")
    print(f"  o'rtacha {cvb.mean():.3f} (SD {cvb.std():.3f})")

    print("\n=== 3. CV ning o'zi ham tasodifga bog'liq (turli seed) ===")
    ort = [cross_val_score(Ridge(alpha=1.0), X, y,
                           cv=KFold(5, shuffle=True, random_state=s), scoring="r2").mean()
           for s in range(10)]
    print(f"  CV o'rtachalari: min {min(ort):.3f}, max {max(ort):.3f} "
          f"(tarqoqlik holdoutdan kichik)")

    print("\n=== 4. Katta ma'lumotda farq kamayadi ===")
    Xb = rng.normal(size=(5000, 5))
    yb = Xb @ np.array([2.0, -1.0, 0.5, 0.0, 0.0]) + rng.normal(0, 1.5, 5000)
    b2 = [Ridge(alpha=1.0).fit(*train_test_split(Xb, yb, test_size=0.2, random_state=s)[::2])
          .score(*train_test_split(Xb, yb, test_size=0.2, random_state=s)[1::2])
          for s in range(10)]
    print(f"  n=5000 holdout R^2 SD: {np.std(b2):.4f}")
    print("  ⭐ Kichik ma'lumotda CV — majburiy")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. 10 xil tasodifiy holdout (20% test) ===
  R^2: min 0.535, max 0.762, o'rtacha 0.643 (SD 0.074)

=== 2. 5-fold cross-validation ===
  bo'laklar: [0.606, 0.719, 0.572, 0.686, 0.731]
  o'rtacha 0.663 (SD 0.063)

=== 3. CV ning o'zi ham tasodifga bog'liq (turli seed) ===
  CV o'rtachalari: min 0.624, max 0.663 (tarqoqlik holdoutdan kichik)

=== 4. Katta ma'lumotda farq kamayadi ===
  n=5000 holdout R^2 SD: 0.0149
  ⭐ Kichik ma'lumotda CV — majburiy

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

Misol 2 — Stratifikatsiya va guruh bo'yicha ajratish

python
"""Nomutanosib sinf va klasterlangan ma'lumot: to'g'ri ajratish (real numpy/sklearn)."""

import numpy as np
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import (GroupKFold, StratifiedKFold, cross_val_score,
                                     train_test_split)


def main() -> None:
    rng = np.random.default_rng(1)

    print("=== 1. Nomutanosib sinf: stratifikatsiyasiz va bilan ===")
    n = 600
    y = (rng.random(n) < 0.05).astype(int)                  # 5% musbat
    X = rng.normal(y[:, None] * 1.2, 1.0, (n, 3))
    ulush_siz, ulush_bilan = [], []
    for s in range(20):
        _, _, ytr, yte = train_test_split(X, y, test_size=0.25, random_state=s)
        ulush_siz.append(yte.mean())
        _, _, ytr2, yte2 = train_test_split(X, y, test_size=0.25, random_state=s, stratify=y)
        ulush_bilan.append(yte2.mean())
    print(f"  stratifikatsiyasiz test ulushi: {min(ulush_siz):.3f}..{max(ulush_siz):.3f}")
    print(f"  stratifikatsiya bilan:          {min(ulush_bilan):.3f}..{max(ulush_bilan):.3f}")

    print("\n=== 2. Klasterlangan ma'lumot: 50 foydalanuvchi × 20 sessiya ===")
    n_user, n_sess = 50, 20
    shaxsiy = rng.normal(0, 2.0, n_user)                    # kuchli shaxsiy effekt
    user_id = np.repeat(np.arange(n_user), n_sess)
    signal = rng.normal(0, 1, n_user * n_sess)
    z = shaxsiy[user_id] + 0.6 * signal
    yg = (rng.random(n_user * n_sess) < 1 / (1 + np.exp(-z))).astype(int)
    Xg = np.column_stack([signal, shaxsiy[user_id] + rng.normal(0, 0.3, n_user * n_sess)])

    model = RandomForestClassifier(n_estimators=120, min_samples_leaf=2, random_state=0)
    oddiy = cross_val_score(model, Xg, yg, cv=StratifiedKFold(5, shuffle=True, random_state=0),
                            scoring="roc_auc")
    guruh = cross_val_score(model, Xg, yg, cv=GroupKFold(5), groups=user_id, scoring="roc_auc")
    print(f"  oddiy CV AUC:  {oddiy.mean():.3f} (SD {oddiy.std():.3f})  ← optimistik")
    print(f"  guruh CV AUC:  {guruh.mean():.3f} (SD {guruh.std():.3f})  ← halol")

    print("\n=== 3. Nega farq bor ===")
    print("  oddiy CV da bir foydalanuvchining sessiyalari ham train, ham testda —")
    print("  moslashuvchan model (o'rmon) shaxsiy darajani yodlab oladi")
    print("  ⭐ Ajratish birligi — bashorat birligi")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Nomutanosib sinf: stratifikatsiyasiz va bilan ===
  stratifikatsiyasiz test ulushi: 0.020..0.067
  stratifikatsiya bilan:          0.040..0.047

=== 2. Klasterlangan ma'lumot: 50 foydalanuvchi × 20 sessiya ===
  oddiy CV AUC:  0.801 (SD 0.010)  ← optimistik
  guruh CV AUC:  0.795 (SD 0.075)  ← halol

=== 3. Nega farq bor ===
  oddiy CV da bir foydalanuvchining sessiyalari ham train, ham testda —
  moslashuvchan model (o'rmon) shaxsiy darajani yodlab oladi
  ⭐ Ajratish birligi — bashorat birligi

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

Misol 3 — Vaqt bo'yicha ajratish

python
"""Vaqt qatorida tasodifiy ajratish optimistik baho beradi (real numpy/sklearn)."""

import numpy as np
from sklearn.linear_model import Ridge
from sklearn.model_selection import KFold, TimeSeriesSplit, cross_val_score


def main() -> None:
    rng = np.random.default_rng(2)
    n = 500
    t = np.arange(n)
    trend = 0.05 * t
    mavsum = 3 * np.sin(2 * np.pi * t / 30)
    shovqin = np.cumsum(rng.normal(0, 0.5, n))              # tasodifiy yurish
    y = 20 + trend + mavsum + shovqin
    X = np.column_stack([t, np.sin(2 * np.pi * t / 30), np.cos(2 * np.pi * t / 30)])

    print("=== 1. Tasodifiy K-fold (NOTO'G'RI) ===")
    kf = cross_val_score(Ridge(), X, y, cv=KFold(5, shuffle=True, random_state=0), scoring="r2")
    print(f"  R^2: {np.round(kf, 3).tolist()}, o'rtacha {kf.mean():.3f}")

    print("\n=== 2. TimeSeriesSplit (TO'G'RI) ===")
    ts = cross_val_score(Ridge(), X, y, cv=TimeSeriesSplit(n_splits=5), scoring="r2")
    print(f"  R^2: {np.round(ts, 3).tolist()}, o'rtacha {ts.mean():.3f}")

    print("\n=== 3. Bo'linishlar tuzilishi ===")
    for i, (tr, te) in enumerate(TimeSeriesSplit(n_splits=3).split(X), start=1):
        print(f"  fold {i}: train [{tr[0]}..{tr[-1]}] ({len(tr)}), "
              f"test [{te[0]}..{te[-1]}] ({len(te)})")

    print("\n=== 4. Oxirgi davr — test ===")
    kesim = int(0.8 * n)
    m = Ridge().fit(X[:kesim], y[:kesim])
    print(f"  train [0..{kesim - 1}], test [{kesim}..{n - 1}]: R^2 = {m.score(X[kesim:], y[kesim:]):.3f}")
    print("  izoh: R^2 manfiy — model o'rtachadan ham yomon; sabab — tasodifiy yurish")
    print("  (nostatsionar qator). Tasodifiy K-fold buni YASHIRADI: 0.80 kabi soxta natija")
    print("  ⭐ Vaqt tartibi — ajratishda ham saqlanadi")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Tasodifiy K-fold (NOTO'G'RI) ===
  R^2: [0.779, 0.808, 0.807, 0.828, 0.797], o'rtacha 0.804

=== 2. TimeSeriesSplit (TO'G'RI) ===
  R^2: [-0.522, 0.597, -3.956, 0.731, -0.359], o'rtacha -0.702

=== 3. Bo'linishlar tuzilishi ===
  fold 1: train [0..124] (125), test [125..249] (125)
  fold 2: train [0..249] (250), test [250..374] (125)
  fold 3: train [0..374] (375), test [375..499] (125)

=== 4. Oxirgi davr — test ===
  train [0..399], test [400..499]: R^2 = -0.017
  izoh: R^2 manfiy — model o'rtachadan ham yomon; sabab — tasodifiy yurish
  (nostatsionar qator). Tasodifiy K-fold buni YASHIRADI: 0.80 kabi soxta natija
  ⭐ Vaqt tartibi — ajratishda ham saqlanadi

Nima ko'rsatdi: 2.5, 2.7-bo'limlar.

Misol 4 — Test to'plamini "ishlatib yuborish"

python
"""Test to'plamida ko'p model sinash — optimistik natija (real numpy/sklearn)."""

import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score, train_test_split


def main() -> None:
    rng = np.random.default_rng(3)
    n, p = 600, 40
    X = rng.normal(size=(n, p))
    y = rng.integers(0, 2, n)                    # NISHON — TASODIFIY (signal yo'q!)

    X_qolgan, X_te, y_qolgan, y_te = train_test_split(X, y, test_size=0.3,
                                                      random_state=0, stratify=y)
    X_tr, X_val, y_tr, y_val = train_test_split(X_qolgan, y_qolgan, test_size=0.3,
                                                random_state=0, stratify=y_qolgan)

    print("=== 1. 40 xil belgilar to'plamini sinaymiz ===")
    eng_yaxshi_test, eng_yaxshi_val = -1.0, -1.0
    i_test = i_val = -1
    for i in range(40):
        ustunlar = rng.choice(p, size=8, replace=False)
        m = LogisticRegression(max_iter=1000).fit(X_tr[:, ustunlar], y_tr)
        v = m.score(X_val[:, ustunlar], y_val)
        t = m.score(X_te[:, ustunlar], y_te)
        if t > eng_yaxshi_test:
            eng_yaxshi_test, i_test = t, i
        if v > eng_yaxshi_val:
            eng_yaxshi_val, i_val, val_test = v, i, t

    print(f"  test bo'yicha tanlangan: test balli {eng_yaxshi_test:.3f}  ← optimistik")
    print(f"  validation bo'yicha tanlangan: val {eng_yaxshi_val:.3f}, test {val_test:.3f}")
    print("  (nishon tasodifiy — haqiqiy aniqlik 0.5 atrofida bo'lishi kerak)")

    print("\n=== 2. Nega shunday ===")
    print("  40 ta variantdan eng yaxshisini tanlash — shovqinni 'topish' 11.9-bob")

    print("\n=== 3. To'g'ri tartib ===")
    print("  1) CV yoki validation'da tanlash")
    print("  2) test'ni BIR MARTA ochish")
    cv = cross_val_score(LogisticRegression(max_iter=1000), X_qolgan, y_qolgan, cv=5)
    print(f"  CV bahosi (tasodifiy nishon): {cv.mean():.3f} — to'g'ri, 0.5 atrofida")
    print("  ⭐ Test to'plami — bir martalik resurs")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. 40 xil belgilar to'plamini sinaymiz ===
  test bo'yicha tanlangan: test balli 0.589  ← optimistik
  validation bo'yicha tanlangan: val 0.595, test 0.483
  (nishon tasodifiy — haqiqiy aniqlik 0.5 atrofida bo'lishi kerak)

=== 2. Nega shunday ===
  40 ta variantdan eng yaxshisini tanlash — shovqinni 'topish' 11.9-bob

=== 3. To'g'ri tartib ===
  1) CV yoki validation'da tanlash
  2) test'ni BIR MARTA ochish
  CV bahosi (tasodifiy nishon): 0.474 — to'g'ri, 0.5 atrofida
  ⭐ Test to'plami — bir martalik resurs

Nima ko'rsatdi: 2.1, 2.6, 2.7-bo'limlar.


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

Noto'g'ri fikr To'g'risi
"Test bilan model tanlash mumkin" Bir martalik resurs
"Bitta holdout yetarli" Kichik ma'lumotda CV
"CV — test o'rnini bosadi" Alohida test kerak
"Stratifikatsiya avtomatik" train_test_split da qo'lda
"Tasodifiy ajratish har doim to'g'ri" Guruh va vaqtni hisobga oling
"CV o'rtachasi yetarli" SD ni ham bering
"Vaqt qatori — oddiy ma'lumot" Vaqt bo'yicha ajratish
"Dublikatlar zarar qilmaydi" Sun'iy yuqori baho

6. Keng tarqalgan xatolar va yechimlari

1. Test bilan tanlash

python
for m in modellar: print(m.fit(X_tr, y_tr).score(X_te, y_te))     # ⚠️
for m in modellar: print(cross_val_score(m, X_tr, y_tr, cv=5).mean())  # ✅

2. Stratifikatsiyasiz

python
train_test_split(X, y, test_size=0.2, random_state=0)             # ⚠️
train_test_split(X, y, test_size=0.2, random_state=0, stratify=y) # ✅

3. Guruhni bo'lish

python
cross_val_score(model, X, y, cv=5)          # bir user ko'p qator # ⚠️
cross_val_score(model, X, y, cv=GroupKFold(5), groups=user_id)    # ✅

4. Vaqt qatorida shuffle

python
KFold(5, shuffle=True)                                            # ⚠️
TimeSeriesSplit(n_splits=5)                                       # ✅

5. Butun ma'lumotda fit

python
X_scaled = StandardScaler().fit_transform(X); train_test_split(X_scaled, y)  # ⚠️
make_pipeline(StandardScaler(), model)   # CV ichida 12.9-bob       # ✅

6. SD siz hisobot

python
print("CV:", scores.mean())                                       # ⚠️
print(f"CV: {scores.mean():.3f} ± {scores.std():.3f}")            # ✅

7. Dublikatlar

python
train_test_split(df, ...)                    # takroriy qatorlar   # ⚠️
df = df.drop_duplicates(); train_test_split(df, ...)              # ✅

7. Integratsiya — bu bilim qayerda kerak bo'ladi

  • 8.8-dars (o'tilgan): Mustaqil tekshiruv g'oyasi
  • 11.9-dars (o'tilgan): Ko'p taqqoslash va optimizm
  • 12.2-dars (o'tilgan): Vaqt kesimi, guruh birligi
  • 12.4-12.5-darslar: Overfitting, bias-variance
  • 12.9-dars: Pipeline (leakage oldini olish)

8. Eng yaxshi amaliyotlar

  1. Test to'plamini birinchi kunda ajrating va yopib qo'ying.

  2. Model tanlash — CV yoki validation'da.

  3. Klassifikatsiyada stratifikatsiya.

  4. Guruh bo'lsa — guruh bo'yicha ajratish.

  5. Vaqt bo'lsa — vaqt bo'yicha.

  6. CV natijasini SD bilan bering.

  7. Barcha tayyorlashni pipeline ichida qiling.

  8. Dublikatlarni oldindan tozalang.


9. Amaliy topshiriq

Vazifa 1: Bashorat qiling

python
1.  # uch to'plam nomi?
2.  # test qachon ishlatiladi?
3.  # K-fold nima qiladi?
4.  # odatiy K?
5.  # stratifikatsiya nima uchun?
6.  # guruh bo'yicha ajratish qachon?
7.  # vaqt qatorida qaysi splitter?
8.  # nested CV nima uchun?
9.  # CV natijasida nima ko'rsatiladi?
10. # scaler qayerda fit qilinadi?
11. # dublikatlar ta'siri?
12. # test 15 marta ishlatilsa?
Javoblar
  1. Train, validation, test
  2. Oxirida, bir marta
  3. K ta bo'lakda navbatma-navbat baholaydi
  4. 5 yoki 10
  5. Sinf ulushini saqlash
  6. Klasterlangan ma'lumotda
  7. TimeSeriesSplit
  8. Tanlov va baholashni ajratish
  9. O'rtacha va SD
  10. Faqat train'da (pipeline ichida)
  11. Sun'iy yuqori baho
  12. Baho optimistik bo'ladi

Vazifa 2: Xatolarni tuzating

python
1.  best = max(modellar, key=lambda m: m.fit(X_tr, y_tr).score(X_te, y_te))

2.  train_test_split(X, y, test_size=0.2)   # 3% musbat sinf

3.  cross_val_score(model, X, y, cv=5)   # har user 15 sessiya

4.  KFold(5, shuffle=True).split(kunlik_savdo)

5.  print("CV:", scores.mean())
Javoblar
python
1.  best = max(modellar, key=lambda m: cross_val_score(m, X_tr, y_tr, cv=5).mean())

2.  train_test_split(X, y, test_size=0.2, random_state=0, stratify=y)

3.  cross_val_score(model, X, y, cv=GroupKFold(5), groups=user_id)

4.  TimeSeriesSplit(n_splits=5).split(kunlik_savdo)

5.  print(f"CV: {scores.mean():.3f} ± {scores.std():.3f}")

Vazifa 3: Validatsiya sxemasi

Modellang:

  1. Ma'lumot turi (klaster, vaqt, nomutanosib)
  2. Mos splitter tanlash
  3. CV natijasi
  4. Sxemani hujjatlashtirish

Vazifa 4: Holdout tebranishi

Modellang:

  1. n = 100, 500, 2000
  2. 30 xil holdout
  3. SD ni solishtirish
  4. CV bilan solishtirish

Vazifa 5: Guruh effekti

Modellang:

  1. Klasterlangan ma'lumot
  2. Oddiy va guruh CV
  3. Farqni tushuntirish
  4. To'g'ri sxema

Vazifa 6: Integratsiya

Modellang:

  1. Vaqt kesimi (12.2)
  2. TimeSeriesSplit
  3. Stratifikatsiya
  4. Pipeline (12.9 ga tayyorgarlik)

Vazifa 7: O'ylash

Kaggle musobaqalarida ishtirokchilar ko'pincha "leaderboard'ga moslashib qolish" (leaderboard overfitting) muammosiga duch keladi: ochiq reyting jadvalida yuqori natija ko'rsatgan yechim yopiq baholashda pastga tushadi. Bu qanday mexanizm, va u kundalik ML ishida qanday ko'rinishda uchraydi?

Javob

Qisqa javob: ochiq leaderboard — takroriy ishlatiladigan validatsiya to'plami. Unga qarab yuzlab qaror qabul qilinsa, model shu to'plamning shovqiniga moslashadi 11.9-bob. Kundalik ishda xuddi shunday: test to'plamiga qarab model tanlash, CV natijasiga qarab cheksiz tajriba qilish.

1. Mexanizm

  • Har yuborilgan yechim — yangi "test"
  • Eng yaxshi natija tanlanadi (maksimum tanlash — 11.2 g'olib la'nati)
  • Tanlangan natija haqiqiydan yuqori (shovqin + moslashish)

2. Kundalik ishdagi shakllari

Holat Xavf
Test bilan model tanlash Optimistik baho
CV da yuzlab variant CV ga moslashish
Belgilarni test natijasiga qarab tanlash Leakage
Metrikani natijadan keyin almashtirish p-hacking (8.8)

3. Himoya

  1. Test to'plamini yopib qo'yish (bir martalik)
  2. Nested CV yoki alohida validation
  3. Tajribalar sonini hujjatlashtirish
  4. Yakuniy modelni yangi davr ma'lumotida sinash
  5. Oddiyroq modelni afzal ko'rish (barqarorroq)

4. Data Scientist qanday

  • Har tajribani jurnalga yozadi (nechta variant sinaldi)
  • Yakuniy natijani mustaqil ma'lumotda tasdiqlaydi
  • CV va test farqini kuzatadi (katta farq — moslashish belgisi)

5. Xulosa

  1. Har takroriy baholash — moslashish xavfi
  2. Tanlov qancha ko'p bo'lsa, optimizm shuncha katta
  3. Test — bir martalik; CV — cheklangan resurs
  4. Mustaqil tasdiqlash — yagona ishonchli usul

Nimani mustahkamlaydi: 2.1, 2.6, 2.7-bo'limlar.


Xulosa

Bu darsda ma'lumotni ajratish va validatsiyani o'rgandik.

Eng muhim uch fikr:

  1. Uch to'plam. Train — o'qitish, validation — model va giperparametr tanlash, test — yakuniy baho (bir marta ochiladi). Test bilan tanlov qilish — optimistik natija (11.9 ning ML shakli).

  2. Cross-validation. K-fold (K = 5) bitta bo'linish tasodifini yo'qotadi va noaniqlikni ko'rsatadi (o'rtacha ± SD). Kichik ma'lumotda majburiy; katta ma'lumotda oddiy holdout ham yetarli bo'lishi mumkin.

  3. Ma'lumot tuzilishiga mos ajratish. Stratifikatsiya (nomutanosib sinflar), guruh bo'yicha (bir foydalanuvchi bir to'plamda — aks holda optimistik baho), vaqt bo'yicha (TimeSeriesSplit — kelajakdan o'tmishga bashorat yo'q). Barcha tayyorlash qadamlari pipeline ichida 12.9-bob.

Keyingi darsda overfitting va underfittingni o'rganamiz: model murakkabligi, o'quv va validatsiya egri chiziqlari, hamda regularizatsiya bilan muvozanat.

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

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