अध्याय ५ · खण्ड 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: मानक
मानक दृष्टिकोण:
- तालिम डाटालाई k बराबर आकारका folds मा बाँड्नुहोस् (सामान्यतया k=5 वा k=10)।
- हरेक fold का लागि: a. त्यो fold राख्नुहोस्। b. अरू (k-1) folds मा मोडेल तालिम दिनुहोस्। c. राखिएको fold मा स्कोर गर्नुहोस्।
- 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. हाइपरपारामिटर ट्युनिङ। GridSearchCV र RandomizedSearchCV ले भित्री रूपमा 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
पछिल्लो खण्डको GridSearchCV र RandomizedSearchCV ले पहिले नै भित्री रूपमा 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 सारांशकर्ता जस्तै। कामको आकार अब परिचित छ; यस पटक मोडेल तपाईंले आफै तालिम दिनुभएको छ।