ailiteracynepal 🇳🇵
पाठ आकार

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

फिचर छान्ने र संयोजन गर्ने

तपाईंले मोडेलमा गर्न सक्ने सबैभन्दा उच्च-लिभरेज सुधार। राम्रा फिचरले राम्रा मोडेललाई झन्डै हरेक पटक हराउँछन्। यो फिचर छनोट र फिचर इन्जिनियरिङको ध्यानवान् संस्करण हो — तपाईंले साप्ताहिक प्रयोग गर्ने मूर्त ढाँचासँग।

तपाईंलाई बलियो मोडेल चाहिन्छ र एउटै मात्र गर्न सक्नुहुन्छ भने, आफ्ना फिचरमा काम गर्नुहोस्। राम्रा फिचरले कुनै पनि आकारका झन्डै हरेक परियोजनामा राम्रा मोडेल हराउँछन्। उत्कृष्ट फिचरमा रेखीय रिग्रेसनले औसत फिचरमा random forest लाई नियमित रूपमा हराउँछ। यो खण्डले तपाईंलाई फिचर छान्ने, संयोजन गर्ने, र काट्ने व्यवहारिक ढाँचा — हरेक लागू ML अभ्यासकर्ताको दैनिक काम — दिन्छ।

फिचर काम दुई भागमा

फिचर काम दुई फरक गतिविधिमा बाँडिन्छ:

फिचर इन्जिनियरिङ — विद्यमानबाट नयाँ फिचर बनाउने। हामीले यो Course 02 अध्याय 5 (“यथार्थलाई स्तम्भमा बदल्ने”) मा ओगट्यौं र निरन्तर प्रयोग गर्छौँ। चार चाल: विघटन (मिति → वर्ष, महिना, dayofweek), संयोजन (loan_amount / monthly_income), सङ्कलन (प्रति ऋणी अघिल्ला ऋणको गन्ती), र बाह्य सन्दर्भ (के 2023 खडेरी वर्ष थियो?)।

फिचर छनोट — उम्मेदवारको लामो सूचीबाट कुन फिचर वास्तवमै मोडेललाई खुवाउने छान्ने। केही फिचरले हानि गर्छन् — तिनले शोर थप्छन्, overfitting प्रोत्साहित गर्छन्, तालिम ढिलो बनाउँछन्। तिनलाई इमानदारीसाथ हटाउनुले प्रायः प्रदर्शन सुधार्छ।

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

फिचर छनोट किन महत्त्वपूर्ण छ

तपाईं सधैंका लागि फिचर थप्न सक्नुहुन्छ। tabular परियोजनामा लगभग 20-30 फिचरपछि, हरेक अतिरिक्तले लगभग बराबर जोखिम र इनाम बोक्छ:

  • अलिकति सम्भावित सङ्केत थप्छ।
  • धेरै सम्भावित overfitting जोखिम थप्छ।
  • मोडेलको अप्टिमाइजर अल्मल्याउने शोर थप्छ।
  • मर्मत लगत थप्छ (सफा गर्न, इन्कोड गर्न, निगरानी गर्न एक थप स्तम्भ)।

15 ध्यानले छानिएका फिचर भएको मोडेलले 80 फिचर भएकोलाई नियमित रूपमा हराउँछ, जहाँ अतिरिक्त 65 शोर हुन्। काट्नु वास्तविक सीप हो।

विधि 1 — filter छनोट (सस्तो, छिटो)

लक्ष्यको विरुद्ध हरेक फिचर स्वतन्त्र रूपमा स्कोर गर्नुहोस्, शीर्ष k राख्नुहोस्। तीन सामान्य स्कोरिङ फङ्क्सन:

from sklearn.feature_selection import SelectKBest, f_classif, mutual_info_classif

# F-test (रेखीय सम्बन्ध)
selector = SelectKBest(f_classif, k=10)
X_selected = selector.fit_transform(X_train, y_train)

# Mutual information (गैर-रेखीय सम्बन्ध पनि समात्छ)
selector = SelectKBest(mutual_info_classif, k=10)
X_selected = selector.fit_transform(X_train, y_train)

# कुन राखिए?
kept_mask = selector.get_support()
kept_features = [name for name, kept in zip(X_train.columns, kept_mask) if kept]
print(kept_features)

रिग्रेसनका लागि, f_regression वा mutual_info_regression प्रयोग गर्नुहोस्।

Filter छनोट छिटो छ (कुनै मोडेल तालिम आवश्यक छैन), सरल छ, र राम्रो पहिलो प्रहार हो। तल्लो छेउ यो हो कि यसले हरेक फिचरलाई एक्लै स्कोर गर्छ — यसलाई थाहा छैन कि दुई सहसम्बन्धित फिचरले उही सङ्केत बोक्छन्, त्यसैले यसले दुवै राख्न सक्छ र राम्रो-तर-फरक फिचर अस्वीकार गर्न सक्छ।

विधि 2 — wrapper छनोट (ढिलो तर सिद्धान्तपूर्ण)

फरक फिचर उपसेटसँग मोडेल तालिम दिनुहोस् र सबैभन्दा राम्रो प्रदर्शन गर्ने उपसेट छान्नुहोस्। scikit-learn मा सबैभन्दा सामान्य Recursive Feature Elimination (RFE) हो:

from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegression

model = LogisticRegression(max_iter=1000)
rfe = RFE(model, n_features_to_select=10, step=1)
rfe.fit(X_train, y_train)

kept = [name for name, kept in zip(X_train.columns, rfe.support_) if kept]
print(kept)

RFE ले मोडेल तालिम दिने, भार (वा फिचर importances) हेर्ने, कमजोर फिचरहरू हटाउने, र चाहेको सङ्ख्या बाँकी नरहेसम्म दोहोर्‍याउने काम गर्छ। यसले फिचर अन्तरक्रियालाई filter छनोटले सक्ने भन्दा फरक तरिकाले लेखाजोखा गर्छ।

तल्लो छेउ यो हो कि ठूला डाटासेटमा ढिलो हुनसक्छ — हरेक चरणमा पूरा मोडेल तालिम आवश्यक। मिलिसेकेन्डमा फिट हुने मोडेल (केही हजार पङ्क्तिमा लोजिस्टिक रिग्रेसन) का लागि, यो ठीक छ। तालिम दिन एक घण्टा लाग्ने मोडेलका लागि, RFE अव्यवहारिक छ।

विधि 3 — embedded छनोट (तपाईंका लागि छान्ने मोडेल)

केही मोडेलहरूले तालिमको भागका रूपमा फिचर छनोट गर्छन्। सबैभन्दा उपयोगी दुई:

Lasso (L1 regularisation) ले असूचनात्मक फिचरका भारलाई ठ्याक्कै शून्य मा तान्छ:

from sklearn.linear_model import LassoCV

lasso = LassoCV(cv=5, random_state=42).fit(X_train, y_train)
nonzero_features = [name for name, w in zip(X_train.columns, lasso.coef_) if w != 0]
print(f"Lasso kept {len(nonzero_features)} features:")
print(nonzero_features)

Tree-based feature importances ले मोडेलले सबैभन्दा बढी भर पर्ने फिचर पहिचान गर्छन्:

from sklearn.ensemble import RandomForestClassifier

rf = RandomForestClassifier(n_estimators=200, random_state=42).fit(X_train, y_train)
importances = sorted(zip(X_train.columns, rf.feature_importances_), key=lambda x: x[1], reverse=True)
for name, imp in importances[:15]:
    print(f"  {name:40s} {imp:.4f}")

दुवैले तपाईंलाई मोडेलको योगदानद्वारा फिचरहरूको श्रेणीबद्ध सूची दिन्छन्। तपाईं अनि शीर्ष-N फिचरमा सानो मोडेल तालिम दिन र प्रदर्शन सुरक्षित छ कि छैन जाँच्न सक्नुहुन्छ।

फिचर संयोजन गर्ने — जब अन्तरक्रिया महत्त्वपूर्ण हुन्छ

कहिलेकाहीं सही फिचर एकल स्तम्भ होइन तर दुईको संयोजन हो। ऋणको जोखिम loan_amount * borrower_age मा निर्भर हुनसक्छ — ठूलो ऋण भएको युवा ऋणी भागहरूको योगले सुझाव दिने भन्दा जोखिमपूर्ण हुन्छ। रेखीय र केही रुख मोडेलले यस्तो अन्तरक्रिया समात्न सक्दैनन् जबसम्म तपाईं यसलाई स्पष्ट बनाउनुहुन्न।

दुई ढाँचा:

बहुपद फिचर (खण्ड 3.3 मा ओगटिएको) — सबै वर्ग र जोडा अन्तरक्रिया स्वचालित रूपमा उत्पन्न गर्नुहोस्:

from sklearn.preprocessing import PolynomialFeatures
poly = PolynomialFeatures(degree=2, interaction_only=True, include_bias=False)
X_poly = poly.fit_transform(X)

interaction_only=True ले वर्ग शब्द स्किप गर्छ (जुन तपाईंलाई श्रेणीगत-शैलीका फिचरका लागि प्रायः चाहिँदैन) र केवल गुणनहरू राख्छ।

हातले बनाइएका अन्तरक्रिया — कहिलेकाहीं तपाईंलाई डोमेन ज्ञानबाट कुन अन्तरक्रिया महत्त्वपूर्ण छ थाहा हुन्छ:

df["amount_per_year_of_age"] = df["loan_amount"] / df["borrower_age"]
df["urban_high_amount"] = (df["is_urban"] == 1) & (df["loan_amount"] > 100000)

Tabular डाटाका लागि हातले बनाइएका अन्तरक्रिया सामान्यतया बहुपदभन्दा राम्रा हुन्छन् — तपाईंले डोमेन ज्ञान ल्याउनुहुन्छ जुन बहुपद विस्तारमा हुँदैन।

उपयोगी sanity check — फिचरबीच सहसम्बन्ध

धेरै सहसम्बन्धित फिचर redundant हुन्छन्। सँगै चल्ने दुई फिचरले लगभग उही सङ्केत बोक्छन्, तर तपाईं शोरको दोब्बर भुक्तानी गर्नुहुन्छ। छिटो जाँच:

import seaborn as sns
import matplotlib.pyplot as plt

corr = X_train.corr()
sns.heatmap(corr, annot=False, cmap="coolwarm", center=0)
plt.show()

उच्च पूर्ण सहसम्बन्ध (0.9 भन्दा माथि, भनौँ) भएका off-diagonal cells खोज्नुहोस्। यदि दुई फिचर 0.95-सहसम्बन्धित छन् भने, एउटा हटाउने विचार गर्नुहोस्। मोडेलका पूर्वानुमान बरै बदलिनेछन्, तर मोडेल सरल र बलियो हुनेछ।

कार्यगत उदाहरण — ऋण डाटासेट काट्ने

अध्याय 1 को ऋण-डिफल्ट डाटासेट काटौं। मानौं इन्जिनियरिङपछि हामीसँग 30 उम्मेदवार फिचर छन्, र हामी कार्यशील सेट भेट्न चाहन्छौं:

import pandas as pd
from sklearn.feature_selection import SelectKBest, mutual_info_classif
from sklearn.ensemble import RandomForestClassifier
from sklearn.pipeline import Pipeline

# चरण 1: mutual information ले 20 मा filter गर्नुहोस्
filter_selector = SelectKBest(mutual_info_classif, k=20)
filter_selector.fit(X_train, y_train)
filter_kept = X_train.columns[filter_selector.get_support()]
print(f"After filter ({len(filter_kept)} features):", list(filter_kept))

# चरण 2: ती 20 मा random forest तालिम दिनुहोस्, importance ले श्रेणीबद्ध गर्नुहोस्
X_train_filtered = X_train[filter_kept]
rf = RandomForestClassifier(n_estimators=200, random_state=42).fit(X_train_filtered, y_train)
top_15 = sorted(zip(filter_kept, rf.feature_importances_), key=lambda x: x[1], reverse=True)[:15]
top_15_names = [name for name, _ in top_15]
print(f"Top 15 by importance:", top_15_names)

# चरण 3: शीर्ष 15 मा अन्तिम मोडेल तालिम दिनुहोस्, शुद्धता तुलना गर्नुहोस्
model_full = Pipeline([("pp", make_preprocessor(filter_kept)), ("clf", LogisticRegression(max_iter=1000))])
model_pruned = Pipeline([("pp", make_preprocessor(top_15_names)), ("clf", LogisticRegression(max_iter=1000))])

for name, m, cols in [("Full (30)", model_full, X_train.columns), ("Pruned (15)", model_pruned, top_15_names)]:
    m.fit(X_train[cols], y_train)
    score = m.score(X_test[cols], y_test)
    print(f"{name:15s} test accuracy: {score:.3f}")

तपाईंले सामान्यतया यस्तै देख्नुहुनेछ:

Full (30)       test accuracy: 0.831
Pruned (15)     test accuracy: 0.829

Pruned मोडेल तालिम गर्न 2 प्रतिशत बिन्दु (सापेक्ष) सस्तो छ, व्याख्या गर्न सजिलो, र त्यत्तिकै राम्रो। यो जीत हो — सधैं उच्च शुद्धता होइन, तर उही शुद्धता कम जटिलतासँग। उत्पादनमा, त्यो महत्त्वपूर्ण छ।

के नगर्ने

नाम दिन लायक दुई विरोधी-ढाँचा:

  • परीक्षण-सेट प्रदर्शनमा आधारित फिचर छान्नुहुन्न। परीक्षण सेटविरुद्ध फिचर ट्युन गर्नाले तपाईंको मोडेल छनोटमा जानकारी लीक गर्छ। बरु cross-validation (अर्को खण्ड) प्रयोग गर्नुहोस्।
  • डोमेन अर्थ भएका “कम-महत्त्व” फिचरहरू अन्धाधुन्ध नहटाउनुहोस्। यदि is_first_time_borrower कम-महत्त्व छ तर stakeholders लाई मोडेलले यसलाई विचार गरेको देख्न आवश्यक छ भने, राख्नुहोस्। फिचर छनोट प्राविधिक लिभर हो, निर्णयको प्रतिस्थापन होइन।

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

Quick check

एक टिम सदस्यले गर्वका साथ आफ्नो मोडेलमा विभिन्न स्वचालित स्रोतबाट 50 फिचर थप्छन्। परीक्षण शुद्धता 0.3 प्रतिशत बिन्दुले बढ्छ तर तालिम समय दस गुणा बढ्छ। सही पढाइ के हो?

Quick check

एक टिम सदस्यले filter छनोट (SelectKBest) प्रयोग गरेर F-score ले शीर्ष 10 फिचर राख्छन्। तिनी नोट गर्छन् कि शीर्ष 10 मध्ये 5 उही अन्तर्निहित सङ्केतका धेरै समान भिन्नताहरू (loan_amount, log_loan_amount, loan_amount_per_1000, loan_amount_squared, loan_amount_zscored) छन्। के गलत छ?

अब के आउँछ

राम्रा फिचर हातमा। अर्को खण्डले अर्को लिभर सम्हाल्छ: हाइपरपारामिटर — तपाईंले तालिमअघि सेट गर्ने नब (max_depth, n_neighbors, alpha) जसले मोडेलले कसरी सिक्छ आकार दिन्छ। यिनलाई राम्रोसँग सेट गर्नु उही डाटामा 75%-शुद्ध र 85%-शुद्ध मोडेलबीचको फरक हुनसक्छ। हामी GridSearchCVRandomizedSearchCV, तिनलाई ट्युन गर्ने मानक औजारहरू भेट्छौँ।