ailiteracynepal 🇳🇵
पाठ आकार

अध्याय ५ · खण्ड III · 24 मिनेट

Cross-validation: आफ्ना सङ्ख्यामा विश्वास गर्ने

एउटा परीक्षण सेटले तपाईंलाई एउटा सङ्ख्या दिन्छ। Cross-validation ले तपाईंलाई धेरै दिन्छ — र तिनीबीचको फैलावटले तपाईंको अनुमान कति स्थिर छ बताउँछ। अन्य हरेक मूल्याङ्कन सङ्ख्यालाई बढी भरपर्दो बनाउने अनुशासन।

तपाईंले अहिलेसम्म रिपोर्ट गर्नुभएको हरेक शुद्धता सङ्ख्या एउटा तालिम/परीक्षण बाँडमा गणना गरिएको थियो। सङ्ख्या कुन पङ्क्ति परीक्षणमा पर्‍यो निर्भर हुन्छ — बाँड बदल्नुहोस्, अलिकति फरक सङ्ख्या पाउनुहोस्। साना डाटासेटका लागि, त्यो भिन्नता पाँच वा दश प्रतिशत बिन्दु हुनसक्छ। Cross-validation त्यो प्रविधि हो जसले धेरै splits मा औसत निकालेर बढी स्थिर, बढी भरपर्दो अनुमान दिन्छ। यो खण्डको अन्त्यसम्ममा तपाईंसँग एकल-बाँड मूल्याङ्कन सङ्ख्यामा फेरि कहिल्यै विश्वास नगर्ने अनुशासन हुनेछ — र उद्धृत गर्न लायक सङ्ख्या उत्पादन गर्ने औजार।

एकल-बाँड समस्या

सानो चिन्तन प्रयोग। मान्नुहोस् तपाईंले मोडेल तालिम दिनुभयो र 0.84 को परीक्षण शुद्धता रिपोर्ट गर्नुहुन्छ। 0.84 ले वास्तवमै तपाईंलाई के भन्दैछ?

यसले तपाईंलाई भन्दैछ कि मोडेलले त्यो विशिष्ट परीक्षण सेटमा 84% हासिल गर्‍यो — तपाईंले random_state=42 सँग बाँडेको बेला जुन पङ्क्ति परीक्षणमा परे। फरक अनियमित बीजसँग, तपाईंले 0.81 वा 0.87 पाउन सक्नुहुन्थ्यो। सानो परीक्षण सेट (भनौँ, 200 पङ्क्ति) सँग, यो भिन्नता सजिलै 5 प्रतिशत बिन्दु हुन सक्छ।

एकल सङ्ख्या रिपोर्ट गर्नाले यहाँ नभएको सटीकता सुझाव दिन्छ। इमानदार संस्करण “84% ± something” हो — तर something थाहा पाउन, तपाईंलाई धेरै मूल्याङ्कन चाहिन्छ।

k-fold cross-validation: मानक

मानक दृष्टिकोण:

  1. तालिम डाटालाई k बराबर आकारका folds मा बाँड्नुहोस् (सामान्यतया k=5 वा k=10)।
  2. हरेक fold का लागि: a. त्यो fold राख्नुहोस्। b. अरू (k-1) folds मा मोडेल तालिम दिनुहोस्। c. राखिएको fold मा स्कोर गर्नुहोस्।
  3. k स्कोरको औसत निकाल्नुहोस्। औसत र मानक विचलन रिपोर्ट गर्नुहोस्।

scikit-learn मा:

from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression

model = LogisticRegression(max_iter=1000)
scores = cross_val_score(model, X_train, y_train, cv=5, scoring="accuracy")

print(f"CV scores: {scores}")
print(f"Mean: {scores.mean():.3f}  Std: {scores.std():.3f}")

आउटपुट:

CV scores: [0.823 0.841 0.818 0.835 0.829]
Mean: 0.829  Std: 0.008

औसत (0.829) तपाईंको शुद्धताको बिन्दु अनुमान हो। मानक विचलन (0.008) ले तपाईंलाई त्यो अनुमान कति स्थिर छ भन्छ। सानो std (~0.02 भन्दा तल) को अर्थ मोडेल विश्वसनीय रूपमा लगभग 83% छ। ठूलो std (~0.04 भन्दा माथि) को अर्थ यो डाटासेटबाट एकल-बाँड सङ्ख्या धेरै प्रतिशत बिन्दुले भ्रामक हुन सक्छ।

Cross-validation कहिले प्रयोग गर्ने

तीन अवस्था जहाँ cross-validation ले सबैभन्दा ठूलो फरक पार्छ:

1. साना डाटासेट। 200-पङ्क्तिको डाटासेटलाई 80/20 बाँडले केवल 40 परीक्षण पङ्क्ति छाड्छ। एउटा अशुभ पङ्क्तिले शुद्धतालाई 2.5 प्रतिशत बिन्दु सर्न सक्छ। Cross-validation ले तपाईंलाई तालिम र मूल्याङ्कन दुवैका लागि हरेक पङ्क्ति प्रयोग गर्न दिन्छ, folds भर गुणित।

2. हाइपरपारामिटर ट्युनिङ। GridSearchCVRandomizedSearchCV ले भित्री रूपमा cross-validation प्रयोग गर्छन् — त्यसैले तिनले परीक्षण सेट लीक नगरी हाइपरपारामिटर छान्छन्। CV स्कोर तिनले अनुकूलन गर्ने हो।

3. मोडेल तुलना गर्ने। जब तपाईं, भनौँ, लोजिस्टिक रिग्रेसन र random forest बीच निर्णय लिँदै हुनुहुन्छ, भिन्नता एकल-बाँड भिन्नताभन्दा सानो हुनसक्छ। Cross-validation ले तपाईंलाई इमानदारीसाथ तुलना गर्न सक्ने औसत स्कोर दिन्छ।

Stratified cross-validation

असन्तुलित कक्षासहितको वर्गीकरणका लागि, पूर्वनिर्धारित cross_val_score ले दुर्लभ कक्षा कम-प्रतिनिधित्व वा अनुपस्थित भएका folds उत्पादन गर्न सक्छ। हरेक fold मा कक्षा अनुपात सुरक्षित गर्न StratifiedKFold प्रयोग गर्नुहोस्:

from sklearn.model_selection import StratifiedKFold

scores = cross_val_score(
    model, X_train, y_train,
    cv=StratifiedKFold(n_splits=5, shuffle=True, random_state=42),
    scoring="f1",
)

व्यवहारमा, scikit-learn का वर्गीकरणकर्ता scorer ले स्वचालित रूपमा stratified CV मा default हुन्छ। तर रिग्रेसनका लागि, वा जब तपाईंलाई नियन्त्रण चाहिन्छ, स्पष्ट रूपमा तोक्नुहोस्।

Time-series cross-validation

अस्थायी डाटा (NEPSE मूल्य, दैनिक कारोबार, आदि) का लागि, cross-validation को अनियमित-बाँड संस्करण गलत छ — हरेक fold मा तालिममा भविष्यको डाटा हुनेछ। TimeSeriesSplit प्रयोग गर्नुहोस्:

from sklearn.model_selection import TimeSeriesSplit

tscv = TimeSeriesSplit(n_splits=5)
scores = cross_val_score(model, X_train, y_train, cv=tscv, scoring="neg_mean_absolute_error")
print(f"Negative MAE per fold: {scores}")

TimeSeriesSplit ले folds बनाउँछ जहाँ हरेक तालिम सेटलाई समय क्रममा राखिएको परीक्षण fold ले पछ्याउँछ — त्यसैले मोडेल सधैं यसको तालिम डाटाको भविष्यमा परीक्षण गरिन्छ। यो मोडेललाई उत्पादनमा कसरी प्रयोग गरिनेछ मेल खान्छ।

Grouped cross-validation

डाटामा जहाँ उही अस्तित्व धेरै पङ्क्तिमा देखापर्छ (Course 02 अध्याय 5 को प्रति ऋणी धेरै ऋण भएको ऋण डाटासेट), GroupKFold प्रयोग गर्नुहोस्:

from sklearn.model_selection import GroupKFold

gkf = GroupKFold(n_splits=5)
scores = cross_val_score(
    model, X_train, y_train,
    cv=gkf.split(X_train, y_train, groups=df_train["borrower_id"]),
    scoring="f1",
)

यसले सुनिश्चित गर्छ कि हरेक ऋणी पूर्ण रूपमा एक fold (तालिम वा परीक्षण) मा बस्छ, कहिल्यै folds मा बाँडिँदैन। Course 02 अध्याय 5 को लीकेज अनुशासन जस्तै तर्क, CV मा लागू।

सँगै राख्ने: हाइपरपारामिटर ट्युनिङभित्र cross-validation

पछिल्लो खण्डको GridSearchCVRandomizedSearchCV ले पहिले नै भित्री रूपमा cross-validation गर्छन्। पूर्ण ढाँचाले सबै संयोजन गर्छ:

from sklearn.model_selection import GridSearchCV, StratifiedKFold
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression

pipeline = Pipeline([
    ("scale", StandardScaler()),
    ("clf", LogisticRegression(max_iter=1000)),
])

param_grid = {
    "clf__C": [0.01, 0.1, 1.0, 10.0, 100.0],
    "clf__penalty": ["l1", "l2"],
    "clf__solver": ["liblinear"],
}

cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)

grid = GridSearchCV(
    pipeline,
    param_grid=param_grid,
    cv=cv,
    scoring="f1",
    n_jobs=-1,
)

grid.fit(X_train, y_train)

print(f"Best params: {grid.best_params_}")
print(f"Best CV F1: {grid.best_score_:.3f}")
print(f"Test F1: {grid.score(X_test, y_test):.3f}")

तीन इमानदार सङ्ख्या बाहिर आउँछन्:

  • सर्वोत्तम CV F1 स्कोर (5 folds मा औसत)। यो तपाईंको ट्युन गरिएको मोडेलको अपेक्षित F1 हो।
  • परीक्षण F1 स्कोर। यो ट्युनिङले कहिल्यै नदेखेको डाटामा वास्तवमै इमानदार मूल्याङ्कन हो।
  • (अन्तर्निहित) CV स्कोरहरूको फैलावट, जुन तपाईं grid.cv_results_ मार्फत स्थिरताको अनुभूतिका लागि पनि पहुँच गर्न सक्नुहुन्छ।

यदि CV F1 र परीक्षण F1 समान छन् (~0.02 भित्र) भने, मोडेल बलियो छ। यदि तिनी धेरै फरक छन् भने, केही गलत छ — सामान्यतया डाटा लीक, वितरण सर्ने, वा धेरै-सानो परीक्षण सेट।

सानो कार्यगत उदाहरण

स्प्याम डाटासेटमा:

from sklearn.model_selection import cross_validate

scoring = ["accuracy", "precision", "recall", "f1"]
results = cross_validate(
    model, X_train, y_train,
    cv=5, scoring=scoring,
    return_train_score=True,
)

import pandas as pd
df_results = pd.DataFrame(results)
print(df_results[["test_accuracy", "test_precision", "test_recall", "test_f1"]].describe().round(3))

आउटपुट (चित्रात्मक):

       test_accuracy  test_precision  test_recall  test_f1
count          5.000           5.000        5.000    5.000
mean           0.974           0.913        0.881    0.897
std            0.005           0.018        0.023    0.014
min            0.968           0.895        0.860    0.880
max            0.980           0.937        0.913    0.917

तपाईंले पाँच मूल्याङ्कन देख्नुहुन्छ — प्रति fold एक। तपाईंले रिपोर्ट गर्ने औसत हो। मानक विचलनले तपाईंलाई अनुमान कति स्थिर छ भन्छ। Min/max ले तपाईंलाई folds भर सबैभन्दा खराब-केस प्रदर्शनको अनुभूति दिन्छ। यो केवल “98% शुद्धता” भन्दा धेरै धनी तस्बिर हो।

यो अध्यायबाट इमानदार निष्कर्ष

अध्याय 5 का तीन ठूला चाल थिए: सही फिचर छान्नुहोस्, हाइपरपारामिटर ट्युन गर्नुहोस्, cross-validation सँग प्रमाणित गर्नुहोस्। सँगै तिनले 75%-शुद्ध आधारलाई 85%-शुद्ध मोडेलमा नियमित रूपमा लैजान्छन् जुन तपाईं कसैलाई पनि रक्षा गर्न सक्नुहुन्छ। अधिकांश लाभ चलाख मोडेलिङबाट होइन — अनुशासनयुक्त अभ्यासबाट हो।

तपाईंले रिपोर्ट गर्ने अन्तिम सङ्ख्या यो हुनुपर्छ:

Model: Random Forest (तालिम सेटमा RandomizedSearchCV बाट सर्वोत्तम params) तालिममा 5-fold CV F1: 0.86 ± 0.013 राखिएको परीक्षण F1: 0.85 प्रति-समूह F1: Bagmati 0.87, Karnali 0.78 (तैनाती अघि अतिरिक्त Karnali डाटा सिफारिस)।

पाँच सङ्ख्या। प्रत्येक कमाइएको। कुनै झुटो बोल्दैनन्।

आफ्नो बुझाइ जाँच्नुहोस्

Quick check

एक टिम सदस्यले cross-validation चलाउँछन् र fold स्कोर [0.82, 0.69, 0.85, 0.91, 0.68] पाउँछन्। तिनले 'औसत शुद्धता 0.79' रिपोर्ट गर्छन्। ठूलो फैलावटले तपाईंलाई के भन्छ?

Quick check

एक टिम सदस्यले NEPSE close-price पूर्वानुमान मोडेल तालिम दिन्छन् र पूर्वनिर्धारित 5-fold cross-validation सँग प्रमाणित गर्छन्। तिनले cross-validation मा 'MAE = 4 NPR' रिपोर्ट गर्छन्। तपाईंलाई यो गलत हो शङ्का छ। सम्भावित मुद्दा के हो?

अब के आउँछ

तपाईं मोडेल बनाउन, तिनलाई मूल्याङ्कन गर्न, र तिनलाई ट्युन गर्न सक्नुहुन्छ। Course 03 को अन्तिम अध्याय capstone हो: पूर्ण, अन्त-देखि-अन्त ML परियोजना, वास्तविक नेपाली समस्याबाट फ्रेम गरिएको, बनाइएको र दोहोर्‍याइएको, र इमानदारीसाथ प्रस्तुत गरिएको। अध्याय 6 को अन्त्यसम्ममा तपाईंसँग एक वास्तविक, सकिएको, साझायोग्य ML परियोजना हुनेछ — ठ्याक्कै Course 01 NEPSE सारांशकर्ता जस्तै। कामको आकार अब परिचित छ; यस पटक मोडेल तपाईंले आफै तालिम दिनुभएको छ।