ailiteracynepal 🇳🇵
पाठ आकार

अध्याय ५ · खण्ड II · 26 मिनेट

श्रेणी एन्कोडिङ र सङ्ख्या स्केलिङ

मोडेलले समान दायराका सङ्ख्या खान्छन्। 'मोरङ' लाई सङ्ख्यामा बदल्ने र 50,000 NPR लाई मोडेलले 18 वर्षको उमेरसँग तुलना गर्न मिल्ने मानमा बदल्ने — यी दुई विश्वव्यापी तयारी चरण हुन्। मूलतः यान्त्रिक। विशिष्ट तरिकाले गलत गर्न सजिलो।

मोडेल गणितीय फङ्क्सन हो। यसका इनपुटहरू सङ्ख्या हुनुपर्छन्, झन्डै तुलनायोग्य दायरामा, अर्थपूर्ण मानहरूबीचको फरकसहित। वास्तविक संसारको डाटा यो रूपमा विरलै आउँछ। श्रेणीगत पाठलाई सङ्ख्यात्मक बनाउनुपर्छ। धेरै फरक दायरा भएका सङ्ख्यात्मक स्तम्भ (लाखमा ऋण रकम, वर्षमा उमेर) लाई समान स्केलमा राख्नुपर्छ। यी दुई सञ्चालन — इन्कोडिङस्केलिङ — मोडेलअघिको अन्तिम यान्त्रिक तयारी चरण हुन्। यो उदास सुनिन्छ। यिनी राम्रा परियोजना चुपचाप बिगार्ने साना गल्ती हुने ठाउँ पनि हुन्।

इन्कोडिङ किन महत्त्वपूर्ण छ

वास्तविक डाटासेटमा झन्डै हरेक चाखलाग्दो स्तम्भ श्रेणीगत हो — जिल्ला, पेसा, विक्रेता, विद्यालय प्रकार। मोडेलले “मोरङ” लाई केहीले गुणन गर्न सक्दैन। तपाईंले यिनलाई सङ्ख्यामा रूपान्तरण गर्नुपर्छ, र कसरी रूपान्तरण गर्नुहुन्छ मोडेलले के सिक्न सक्छ निर्णय गर्छ।

तीन इन्कोडिङ रणनीतिले झन्डै हरेक केस ओगट्छन्।

रणनीति 1: one-hot इन्कोडिङ

साना-कार्डिनालिटी श्रेणीगत स्तम्भका लागि पूर्वनिर्धारित। हरेक अद्वितीय मान आफ्नो 0/1 स्तम्भ बन्छ:

import pandas as pd

df = pd.DataFrame({"district": ["Morang", "Kaski", "Morang", "Bhaktapur"]})
encoded = pd.get_dummies(df, columns=["district"], drop_first=False)
print(encoded)

आउटपुट:

   district_Bhaktapur  district_Kaski  district_Morang
0               False           False             True
1               False            True            False
2               False           False             True
3                True           False            False

तीन जिल्ला तीन नयाँ बुलियन स्तम्भ बन्छन्। मोडेलले अब “district_Morang True भएका पङ्क्तिले 8% डिफल्ट गर्छन्” सिक्न सक्छ।

कहिले प्रयोग गर्ने: साना श्रेणीगत स्तम्भ (सामान्यतया ~30 अद्वितीय मानसम्म)। नेपालका 7 प्रदेश वा 14 क्षेत्र (पुरानो प्रशासनिक विभाजन) का लागि — one-hot ठीक छ। सबै 77 जिल्लाका लागि — one-hot सीमामा छ। हजारौं विक्रेताका लागि — one-hot गलत छ।

drop_first=True आर्गुमेन्टले एउटा स्तम्भ हटाउँछ (मोडेलले अरूबाट अनुमान गर्न सक्छ), आयाम केही घटाउँछ र केही रेखीय मोडेलका लागि “पूर्ण मल्टीकोलिनियरिटी” बाट जोगाउँछ। उपयोगी तर सधैं आवश्यक होइन।

रणनीति 2: ordinal इन्कोडिङ

जब श्रेणीहरूको प्राकृतिक क्रम हुन्छ — शिक्षा स्तर (primary, secondary, tertiary), Likert मापदण्ड (strongly disagreestrongly agree) — क्रमलाई सम्मान गर्ने पूर्णाङ्क तोक्नुहोस्:

edu_order = {"primary": 1, "secondary": 2, "tertiary": 3}
df["education"] = df["education"].map(edu_order)

मोडेलले अब 1, 2, 3 देख्छ र 3 लाई 2 भन्दा “बढी” सिक्न सक्छ। यो सही छ जब क्रम वास्तविक हो र गलत छ जब छैन। district लाई ordinal पूर्णाङ्क (Morang=1, Kaski=2, ...) का रूपमा इन्कोड गर्नु गलत छ — कुनै क्रम छैन, र मोडेलले “मोरङ काँस्कीभन्दा कम छ” गलत रूपमा अर्थपूर्ण सिक्नेछ।

रणनीति 3: target इन्कोडिङ

उच्च-कार्डिनालिटी श्रेणीगतका लागि (हजारौं विक्रेता, हजारौं ऋणी), one-hot अव्यवहारिक छ र ordinal अर्थहीन छ। Target इन्कोडिङ ले हरेक श्रेणीलाई त्यो श्रेणीका लागि लक्ष्य चरको औसत मानले प्रतिस्थापन गर्छ — हजारौं को सट्टा एकल स्तम्भ।

ऋण डिफल्ट पूर्वानुमानका लागि:

default_rate_by_vendor = df.groupby("vendor")["defaulted"].mean()
df["vendor_default_rate"] = df["vendor"].map(default_rate_by_vendor)

हरेक विक्रेता त्यो विक्रेताका लागि ऐतिहासिक डिफल्ट दर — 0 र 1 बीचको सङ्ख्या बन्छ। मोडेलले अब यसलाई प्रयोग गर्न सक्छ।

Course 02 का लागि निचोड: साना श्रेणीगतका लागि one-hot, क्रमबद्धका लागि ordinal, उच्च-कार्डिनालिटीका लागि target इन्कोडिङ (ध्यानले)।

स्केलिङ किन महत्त्वपूर्ण छ

ऋण रकम (दायरा 0 देखि 5,000,000) र ऋणी उमेर (दायरा 18 देखि 70) धेरै फरक स्केलमा छन्। केही मोडेल — दूरीमा आधारित कुनै पनि (k-NN, k-means, SVM, न्यूरल नेटवर्क) — ले ऋण रकमलाई उमेरभन्दा हजार गुणा महत्त्वपूर्ण ठान्छन्, केवल सङ्ख्या ठूला भएकाले। रुख-आधारित मोडेल (निर्णय रुख, र्‍यान्डम फरेस्ट, ग्रेडियन्ट बूस्टिङ) अधिकांश इम्युन छन्।

दुई स्केलिङ रणनीतिले झन्डै सबै ओगट्छन्।

रणनीति A: मानकीकरण

औसत घटाउनुहोस्, मानक विचलनले विभाजन गर्नुहोस्। नतिजाको औसत 0 र मानक विचलन 1 हुन्छ:

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
df[["loan_amount", "age"]] = scaler.fit_transform(df[["loan_amount", "age"]])

यसपछि, दुवै स्तम्भ 0 वरिपरि केन्द्रित छन्, करिब 68% मान ±1 भित्र र झन्डै सबै ±3 भित्र। मोडेलले अब तिनलाई तुलनायोग्य ठान्छ।

प्रयोग गर्ने: स्तम्भ झन्डै सममित (सामान्य-जस्तो) छ। अधिकांश सङ्ख्यात्मक स्तम्भ मानकीकरणसँग ठीक चल्छन्।

रणनीति B: min-max स्केलिङ

[0, 1] दायरामा खुम्च्याउनुहोस्:

from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler()
df[["loan_amount", "age"]] = scaler.fit_transform(df[["loan_amount", "age"]])

यसपछि, न्यूनतम मान 0 र अधिकतम 1 बन्छ, बाँकी सबै आनुपातिक रूपमा बीचमा।

प्रयोग गर्ने: जब तपाईंलाई सीमित मान चाहिन्छ (केही न्यूरल नेटवर्कले यो अपेक्षा गर्छन्), वा जब वितरण धेरै बाङ्गो छ र तपाईं केही चरमले हावी हुन चाहनुहुन्न। सामान्य प्रयोगका लागि मानकीकरणभन्दा कम सामान्य।

बाङ्गो स्तम्भका लागि तेस्रो विकल्प: log रूपान्तरण

दायाँ-बाङ्गो स्तम्भ (ऋण रकम, आय, कारोबार मान) का लागि, log रूपान्तरण प्रायः स्केलिङ अघि सही चाल हो। यसले लामो पुच्छर खुम्च्याउँछ र वितरणलाई बढी सममित बनाउँछ:

import numpy as np
df["log_loan_amount"] = np.log1p(df["loan_amount"])

np.log1p(x) ले log(1 + x) गणना गर्छ — +1 ले तपाईंलाई त्रुटिबिनै शून्य सम्हाल्न दिन्छ (log(0) अपरिभाषित छ)। बाङ्गो स्तम्भ लग-रूपान्तरण गरेपछि, मानकीकरण नतिजामा सुन्दर रूपमा चल्छ।

यो पूरै खण्डमा सबैभन्दा बढी टेकिने माइन

गहिरो, गर्न सजिलो गल्ती: पूरै डाटासेटमा स्केलर फिट गर्नुहोस्, अनि तालिम र परीक्षणमा बाँड्नुहोस्। यो गलत हो किनभने स्केलरको औसत र मानक विचलनले परीक्षण सेटको जानकारी समावेश गर्छ, तालिम समयमा अनुपलब्ध हुनुपर्ने ज्ञान लीक गर्दै।

सही ढाँचा:

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

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

scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)   # तालिममा मात्र फिट गर्नुहोस्
X_test = scaler.transform(X_test)         # तालिमका पारामिटर प्रयोग गरेर परीक्षण रूपान्तरण

तालिममा fit_transform (औसत र std गणना गर्छ, अनि लागू गर्छ)। परीक्षणमा केवल transform (उही पारामिटर लागू गर्छ, पुन: गणना गर्दैन)।

इन्कोडर, इम्प्युटर, र डाटामा निर्भर अन्य कुनै पनि पूर्व-प्रशोधनमा उही नियम लागू हुन्छ: तालिममा मात्र फिट गर्नुहोस्, तालिम र परीक्षण अलग्गै रूपान्तरण गर्नुहोस्

Pipeline सँग सँगै राख्ने

Scikit-learn को Pipeline ले सही ढाँचालाई स्वचालित बनाउँछ:

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.ensemble import RandomForestClassifier

numeric = ["loan_amount", "age"]
categorical = ["district", "occupation"]

preprocessor = ColumnTransformer([
    ("num", StandardScaler(), numeric),
    ("cat", OneHotEncoder(handle_unknown="ignore"), categorical),
])

model = Pipeline([
    ("preprocess", preprocessor),
    ("classifier", RandomForestClassifier()),
])

model.fit(X_train, y_train)            # सबै तालिममा मात्र फिट
predictions = model.predict(X_test)    # परीक्षण सही रूपान्तरण

Pipeline ले स्केलर र इन्कोडर तालिम डाटामा फिट हुन्छन् र परीक्षणमा स्वचालित रूपमा लागू हुन्छन् भन्ने सुनिश्चित गर्छ — कुनै लीकेज छैन, कुनै गल्ती छैन। कुन मोडेल प्रयोग गर्ने थाहा हुनुअघि नै, कुनै पनि मोडेलिङ परियोजनाका लागि पूर्वनिर्धारित सुरुवात संरचनाका रूपमा यो ढाँचा प्रयोग गर्नुहोस्।

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

Quick check

नयाँ निर्माताले 5,000 अद्वितीय विक्रेता ID भएको स्तम्भलाई one-hot इन्कोड गर्छन् र मोडेलले घण्टौं तालिम लिँदा र नाटकीय रूपमा अधिक-फिट हुँदा छक्क पर्छन्। सही निदान के हो?

Quick check

एक टिम सदस्यले लेख्छिन्: scaler = StandardScaler() X = scaler.fit_transform(X) X_train, X_test = train_test_split(X) model.fit(X_train, ...) model.score(X_test, ...) यहाँ लीकेज समस्या के हो, र उपचार के हो?

अब के आउँछ

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