ailiteracynepal 🇳🇵
पाठ आकार

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

डाटा बाँड्ने: तालिम, प्रमाणीकरण, परीक्षण

डाटालाई मोडेलले देख्न सक्ने भाग, तपाईंले ट्युन गर्न प्रयोग गर्ने भाग, र तपाईंले लुकाएर राख्ने भागमा बाँड्नुहोस्। बाँड गलत गर्नुहोस् र तपाईंको इमानदार-देखिने शुद्धता सङ्ख्या झूटो हुन्। तीन साना अनुशासनले यो रोक्छन्।

तालिम डाटामा मोडेलको शुद्धताले तपाईंलाई झन्डै केही पनि बताउँदैन। निस्सन्देह यो राम्रो गर्छ — यसले ती उदाहरण देख्यो। मोडेलको इमानदार मापन यसले नदेखेको डाटामा यसको शुद्धता हो। यही कारणले तपाईं बाँड्नुहुन्छ: तपाईं डाटालाई एक तर्फ राख्नुहुन्छ जुन मोडेलले तालिममा कहिल्यै हेर्न पाउँदैन, र तपाईं त्यो डाटा प्रयोग गरेर मोडेलले वास्तविक केही सिकेको छ कि उदाहरण मात्र कण्ठ गरेको छ निर्णय गर्नुहुन्छ। अनुशासन सरल सुनिन्छ। यसलाई गलत गर्ने तरिका अचम्म र सामान्य छन्। यो खण्ड ध्यानवान् संस्करण हो।

तीन टुक्रा, तीन काम

सफा प्रयोगात्मक सेटअपमा डाटाका तीन उप-सेट हुन्छन्:

तालिम सेट मोडेल फिट हुने डाटा। सामान्यतया कुलको 60-80%। मोडेलले यहाँ ढाँचा सिक्छ।

प्रमाणीकरण सेट विकासका बेला निर्णय गर्न प्रयोग गरिने डाटा — कुन मोडेल, कुन हाइपरपारामिटर, कुन फिचर सेट उत्तम काम गर्छ। सामान्यतया कुलको 10-20%। तपाईं परियोजनाभर यसलाई धेरै पटक हेर्नुहुन्छ।

परीक्षण सेट अन्तिम मोडेल न्याय गर्न प्रयोग गरिने डाटा। तपाईं यसलाई एक पटक हेर्नुहुन्छ, अन्त्यमा। सामान्यतया कुलको 10-20%। यसलाई पवित्र ठान्नुहोस्।

यदि तपाईंसँग दुई बाँड (तालिम र परीक्षण) मात्र छन् भने, परीक्षण सेटले दुवै काम गर्छ — र तपाईं गल्तीले आफ्ना निर्णय यसमा ट्युन गर्नुहुन्छ। “मैले यो हाइपरपारामिटर कोसिस गरेँ र के परीक्षण शुद्धता पाएँ” को पन्ध्र राउन्डपछि, परीक्षण सेटले अब केही पनि परीक्षण गरिरहेको छैन। यो तालिमको भाग बन्यो।

यान्त्रिक: सफा तीन-तर्फी बाँड

Scikit-learn मा निर्मित तीन-तर्फी बाँडकर्ता छैन, तर दुई कलले तपाईंलाई चाहिने दिन्छन्:

from sklearn.model_selection import train_test_split

# पहिलो बाँड: 80% temp / 20% परीक्षण
X_temp, X_test, y_temp, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42,
)

# दोस्रो बाँड: 80% को, 75% तालिम / 25% val लिनुहोस् (त्यसैले मूल 60/20/20 हो)
X_train, X_val, y_train, y_val = train_test_split(
    X_temp, y_temp, test_size=0.25, random_state=42,
)

print(len(X_train), len(X_val), len(X_test))

random_state=42 ले बाँडलाई निर्धारक बनाउँछ — स्क्रिप्ट पुन: चलाउँदा उही बाँड उत्पादन हुन्छ। पुन: उत्पादनयोग्यताका लागि आवश्यक।

अधिकांश परियोजनाका लागि, 60-20-20 वा 70-15-15 ठीक छ। डाटा सानो हुँदा (1,000 पङ्क्तिभन्दा कम), ठूलो तालिम अंशलाई विचार गर्नुहोस्। डाटा ठूलो हुँदा, तपाईं val/परीक्षण प्रतिशत खुम्च्याउन सक्नुहुन्छ — दश लाख पङ्क्तिको 80-10-10 ले तपाईंलाई प्रत्येक मूल्याङ्कन सेटमा 100,000 दिन्छ।

बाँडमा चार जाल

जाल 1: समय-शृङ्खला डाटा अनियमित रूपमा बाँड्ने। भविष्यको NEPSE मूल्य पूर्वानुमान गर्ने मोडेल जुन 2025 को डाटा 2026 सँग बीचमा तालिम दिइएको थियो, धोका दिँदै छ: यसले तालिमका बेला पछिका मितिका पङ्क्ति देखेको थियो। 2026 बाट परीक्षण पङ्क्ति “वितरणभित्र” देखिन्छन् किनभने तालिम सेटमा समान पङ्क्ति छन्। उत्पादनमा, मोडेलले विगत मात्र देख्छ। सही बाँड समयद्वारा हो:

df = df.sort_values("date")
cutoff = "2026-06-01"
train = df[df["date"] < cutoff]
test = df[df["date"] >= cutoff]

समय-शृङ्खलाका लागि, सधैं क्रमशः बाँड्नुहोस्। सधैं।

जाल 2: स्तरीकरण विफलता। लक्ष्य चर असन्तुलित हुँदा (जस्तै केवल 5% ऋण डिफल्ट हुन्छन्), अनियमित बाँडले सबै डिफल्टलाई तालिम सेटमा र कुनै परीक्षणमा नल्याउन सक्छ। stratify= प्रयोग गर्नुहोस्:

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, stratify=y, random_state=42,
)

stratify=y ले दुवै बाँडमा कक्षा अनुपात सुरक्षित गर्छ। असन्तुलित कक्षासहितको वर्गीकरण समस्याका लागि सधैं प्रयोग गर्नुहोस्।

जाल 3: समूहीकृत डाटा लीक। यदि उही ऋणी धेरै पङ्क्तिमा देखापर्छ (समयसँग धेरै ऋण), अनियमित बाँडले तिनका केही पङ्क्ति तालिममा र केही परीक्षणमा राख्छ। मोडेलले तालिमबाट ऋणी “जान्छ”, र परीक्षणमा तिनको व्यवहार पूर्वानुमान गर्नु धेरै सजिलो हुन्छ। GroupShuffleSplit प्रयोग गर्नुहोस्:

from sklearn.model_selection import GroupShuffleSplit

splitter = GroupShuffleSplit(test_size=0.2, random_state=42)
train_idx, test_idx = next(splitter.split(X, y, groups=df["borrower_id"]))

यसले दिइएको ऋणीका सबै पङ्क्तिलाई तालिम वा परीक्षणमा बस्न सुनिश्चित गर्छ, दुवैमा कहिल्यै होइन। तपाईंको डाटामा प्राकृतिक समूह (ऋणी, विद्यार्थी, ग्राहक, उपकरण) हुँदा सधैं प्रयोग गर्नुहोस्।

जाल 4: वितरण सर्ने। सफा बाँडसहित पनि, तालिम वितरण उत्पादनसँग मेल नखान सक्छ। केवल 2024 काठमाडौं ऋणमा तालिम दिइएको, 2024 काठमाडौं ऋणमा मूल्याङ्कन गरिएको मोडेल अझै 2026 कर्णाली ऋणमा विफल हुन सक्छ। उपचार बाँडमा छैन — यो तपाईं तैनाती गर्ने जनसङ्ख्यालाई प्रतिनिधित्व गर्ने डाटा सङ्कलनमा छ। बाँडले तपाईंसँग जे छ त्यो प्रमाणित गर्न सक्छ; यसले सङ्कलन नभएको प्रतिनिधित्व बनाउन सक्दैन।

पूर्ण तयारी पाइपलाइन

अध्याय 5 सँगै राख्ने। कच्चा डाटाबाट मोडेल-तयार बाँडसम्म सफा तयारी प्रहार:

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline

# 1. सफा डाटा लोड गर्नुहोस् (अध्याय 3 / 4 को आउटपुट)
df = pd.read_csv("data/clean/loans.csv")

# 2. फिचर इन्जिनियर गर्नुहोस्
df["log_loan_amount"] = np.log1p(df["loan_amount"])
df["loan_to_income_ratio"] = df["loan_amount"] / df["monthly_income"]
df["application_date"] = pd.to_datetime(df["application_date"])
df["application_month"] = df["application_date"].dt.month

# 3. फिचर स्तम्भ र लक्ष्य छान्नुहोस्
numeric = ["log_loan_amount", "loan_to_income_ratio", "application_month", "monthly_income"]
categorical = ["district", "occupation_category"]
target = "defaulted"

X = df[numeric + categorical]
y = df[target]

# 4. बाँड्नुहोस् — स्तरीकृत, राखिएको परीक्षण सेटसहित
X_temp, X_test, y_temp, y_test = train_test_split(
    X, y, test_size=0.2, stratify=y, random_state=42,
)
X_train, X_val, y_train, y_val = train_test_split(
    X_temp, y_temp, test_size=0.25, stratify=y_temp, random_state=42,
)

# 5. पूर्व-प्रशोधन पाइपलाइन बनाउनुहोस् (तालिममा मात्र फिट गर्नुहोस्)
preprocess = ColumnTransformer([
    ("num", StandardScaler(), numeric),
    ("cat", OneHotEncoder(handle_unknown="ignore"), categorical),
])

# 6. बाँड बचाउनुहोस् — तपाईंले कोसिस गर्ने हरेक मोडेलका लागि यिनै पुन: प्रयोग गर्नुहुनेछ
import joblib
joblib.dump((X_train, y_train), "data/splits/train.joblib")
joblib.dump((X_val, y_val),     "data/splits/val.joblib")
joblib.dump((X_test, y_test),   "data/splits/test.joblib")
joblib.dump(preprocess,         "data/splits/preprocess.joblib")

जब तपाईं Course 03 मा मोडेल तालिम सुरु गर्नुहुन्छ, तपाईं यी बाँड लोड गर्नुहुन्छ र हरेक प्रयोगका लागि उही तालिम/val/परीक्षण सीमा प्रयोग गर्नुहुन्छ। फरक बाँडसँग मोडेल तुलना गर्नु केहीसँग पनि तुलना नगर्नु हो।

अन्त्यमा “इमानदार” कस्तो देखिन्छ

मोडेलमा विश्वसनीय रिपोर्टको यो संरचना हुन्छ:

  • data/splits/train.joblib (n=4,800 पङ्क्ति) मा तालिम।
  • प्रमाणीकरण सेट (data/splits/val.joblib, n=1,600 पङ्क्ति) प्रयोग गरेर ट्युन गरिएका हाइपरपारामिटर।
  • अन्तिम मोडेल परीक्षण सेट (data/splits/test.joblib, n=1,600 पङ्क्ति) मा एक पटक मूल्याङ्कन।
  • परीक्षण शुद्धता: 0.87। परीक्षण F1: 0.72।
  • तालिम शुद्धता: 0.91 (परीक्षणभन्दा अलि उच्च, अपेक्षाअनुसार — मामूली अधिक-फिट)।
  • प्रमाणीकरण शुद्धता: 0.88 (परीक्षणसँग धेरै नजिक, सुझाव दिँदै प्रमाणीकरण-सेट मार्गदर्शन निष्पक्ष थियो)।

जब तालिम र परीक्षणबीचको अन्तर ठूलो हुन्छ (0.99 बनाम 0.62), तपाईंसँग अधिक-फिट छ र पठाउनुहुन्न। जब प्रमाणीकरण र परीक्षणबीचको अन्तर ठूलो हुन्छ (0.92 बनाम 0.68), तपाईंले आफ्नो हाइपरपारामिटर खोजी अधिक-फिट गर्नुभयो र छानबिन गर्नुपर्छ। इमानदार मूल्याङ्कनले यी अन्तर प्रकट गर्छ; अव्यवस्थित बाँडले लुकाउँछ।

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

Quick check

तपाईं अर्को-हप्ता NEPSE बन्द पूर्वानुमान गर्ने मोडेल बनाउँदै हुनुहुन्छ। तपाईंले `random_state=42` सँग `train_test_split` प्रयोग गरेर आफ्नो दैनिक मूल्य डाटा अनियमित रूपमा 80/20 बाँड्नुभयो। तपाईंको परीक्षण शुद्धता 94% छ, जुन उत्कृष्ट देखिन्छ। सम्भावित गलत के हो?

Quick check

ऋण डाटासेटमा 5,000 अद्वितीय ऋणी प्रतिनिधित्व गर्ने 50,000 पङ्क्ति छन् (केही ऋणीसँग धेरै ऋण छन्)। तपाईंले अनियमित 80/20 बाँड गर्नुहुन्छ। मोडेलले 91% परीक्षण शुद्धता हासिल गर्छ। एक टिम सदस्यले लीकेजको शङ्का गर्छिन्। के शङ्का जायज छ?

अब के आउँछ

तपाईंसँग सफा, बाँडिएको, तयार डाटासेट छ। यान्त्रिक काम सकियो। Course 02 को अन्तिम अध्यायले कीबोर्डबाट एक छिन हट्छ र यो सबैको मानवीय आयाम हेर्छ — पूर्वाग्रह कहाँबाट छिर्छ, नेपालमा वास्तविक मानिसहरूको डाटा हुँदा गोपनीयताको अर्थ के हो, र तपाईंले कहिल्यै नदेखेको कसैले तपाईंको कामलाई विश्वास गर्न सक्ने गरी डाटासेट कसरी कागजात गर्ने। प्राविधिक तयारी महत्त्वपूर्ण छ। जिम्मेवारीसँग गर्नु काम महत्त्वपूर्ण बनाउने हो।