Overfitting, Underfitting, Cross-Validation ও Hyperparameter Tuning

model কেন generalize করে না (Series 05, Episode 08)

🟡 INTERMEDIATE Series 05 — Classical Machine Learning Episode 08 / 11

📑 এই পর্বে যা যা আছে

📝 ১. গল্প: Rahim-এর "৯৯% accuracy" ফাঁদ

Rahim একটা churn model বানাল। Training-এ accuracy ৯৯%! সে খুশিতে Maya-কে দেখাতে গেল। Maya শুধু একটা প্রশ্ন করল — "এই ৯৯% কি training data-তে, নাকি নতুন, আগে-না-দেখা data-তে?"

Maya: "একজন ছাত্র যদি পরীক্ষার প্রশ্নপত্র আগে থেকে মুখস্থ করে ফেলে, সে ওই পরীক্ষায় ১০০ পাবে। কিন্তু নতুন প্রশ্ন দিলে ধরা খাবে। তোমার model এখন ঠিক তাই করছে — data মুখস্থ (memorize) করেছে, শেখেনি (generalize করেনি)। এটাই overfitting। Production-এ এই model খারাপ prediction দেবে, আর আমরা বুঝতেও পারব না কেন।"

এই episode-এ আমরা শিখব — কেন model generalize করে না, কীভাবে সেটা ধরব (cross-validation), আর কীভাবে সেরা model বাছব (hyperparameter tuning)। এটা classical ML-এর সবচেয়ে জরুরি practical skill-গুলোর একটা।

২. সমস্যা: training-এ দারুণ, real data-তে ধরাশায়ী

আমরা model train করি অতীত data দিয়ে, কিন্তু আসল লক্ষ্য হলো ভবিষ্যতের, আগে-না-দেখা data-তে ভালো করা। Model যদি training data-র প্রতিটা খুঁটিনাটি (এমনকি noise-ও) মুখস্থ করে ফেলে, তাহলে সে training-এ চমৎকার কিন্তু বাস্তবে দুর্বল।

মূল প্রশ্ন: model কি pattern (নিয়ম) শিখেছে, নাকি data মুখস্থ করেছে? পার্থক্য বোঝার একমাত্র উপায় — model-কে আগে-না-দেখা data-তে যাচাই করা।

🎯 ৩. Overfitting ও Underfitting কী? (৩ স্তরে)

Level 1 — সহজ intuition

Underfitting: model বড্ড সরল — কিছুই ঠিকমতো শেখেনি (যেমন সব প্রশ্নের উত্তরে "জানি না")। Overfitting: model বড্ড জটিল — সব মুখস্থ করেছে, কিন্তু বুঝে শেখেনি। Good fit: মাঝামাঝি — আসল নিয়মটা ধরেছে, noise বাদ দিয়েছে।

Level 2 — technical ভাবে কী হচ্ছে

Underfitting = high bias (model assumption বড্ড কড়া, data-র জটিলতা ধরতে পারে না)। Overfitting = high variance (model training data-র সামান্য পরিবর্তনেও অনেক বদলে যায়, noise-কেও signal ভাবে)। লক্ষ্য — bias আর variance-এর মধ্যে balance (bias-variance trade-off, Series 04-এ আলোচিত)।

Level 3 — engineer perspective

একজন engineer শুধু training accuracy দেখে খুশি হয় না। সে সবসময় দুটো সংখ্যা পাশাপাশি দেখে — training score আর validation score। যদি training অনেক বেশি আর validation অনেক কম → overfitting। দুটোই কম → underfitting। এই gap-টাই আসল diagnostic tool।

অবস্থাTraining scoreValidation scoreসমাধানের দিক
Underfittingকমকমআরও শক্তিশালী model, বেশি feature, কম regularization
Overfittingখুব বেশিঅনেক কমআরও data, regularization, model সরল করা
Good fitভালোকাছাকাছি ভালোএটাই লক্ষ্য

🖼️ ৪. Visual: bias-variance আর fitting curve

Underfitting Good Fit Overfitting (high bias) (high variance) o o o o o o --------- _/ \_ /\ o /\ o o o o o o \/ \/ o (সরল রেখা, (মসৃণ curve, (প্রতিটা বিন্দু কিছুই ধরেনি) নিয়ম ধরেছে) ছুঁয়ে গেছে = noise মুখস্থ) Training error: বেশি কম খুব কম Validation err: বেশি কম বেশি <-- সমস্যা!

খেয়াল করুন — overfitting-এ curve প্রতিটা training বিন্দু ছুঁয়ে যায় (এমনকি noise-ও), কিন্তু নতুন data এলে ভুল করে। Good fit noise উপেক্ষা করে মূল trend ধরে।

🚧 ৫. কেন একটা test set যথেষ্ট না

আপনি হয়তো ভাবছেন — "একটা test set রাখলেই তো হলো।" সমস্যা হলো, আপনি যদি বারবার একই test set দেখে model বা hyperparameter বদলান, তাহলে ধীরে ধীরে আপনি test set-এর উপরেও overfit করে ফেলেন। এটা এক ধরনের সূক্ষ্ম data leakage — সিদ্ধান্ত নেওয়ার সময় test data-র তথ্য চুইয়ে ঢুকে পড়ে।

সঠিক ভাগ: Train (শেখার জন্য) → Validation (model/hyperparameter বাছাইয়ের জন্য) → Test (একদম শেষে, একবার, honest final score-এর জন্য)। Test set-কে "সিন্দুকে তালা মেরে" রাখুন — শুধু একবার খুলবেন।

কিন্তু ছোট dataset-এ আলাদা validation set রাখা মানে শেখার data আরও কমে যাওয়া। এই সমস্যার সুন্দর সমাধান — Cross-Validation

🔁 ৬. Cross-Validation: k-fold কীভাবে কাজ করে

k-fold CV-তে data-কে k ভাগে (fold) ভাগ করা হয়। প্রতিবার ১টা fold validation, বাকি (k-1)টা training। এভাবে k বার train-validate করা হয়, প্রতিবার ভিন্ন fold validation হিসেবে। শেষে k-টা score-এর গড় নেওয়া হয়।

5-fold Cross-Validation (k=5): Fold 1: [VAL][TRN][TRN][TRN][TRN] -> score1 Fold 2: [TRN][VAL][TRN][TRN][TRN] -> score2 Fold 3: [TRN][TRN][VAL][TRN][TRN] -> score3 Fold 4: [TRN][TRN][TRN][VAL][TRN] -> score4 Fold 5: [TRN][TRN][TRN][TRN][VAL] -> score5 Final CV score = (score1 + ... + score5) / 5

লাভ: প্রতিটা data point কোনো-না-কোনো বার validation-এ যায়, তাই score অনেক বেশি নির্ভরযোগ্য এবং কম "ভাগ্য-নির্ভর"। classification-এ সাধারণত StratifiedKFold ব্যবহার হয় — যাতে প্রতিটা fold-এ class-এর অনুপাত ঠিক থাকে (imbalanced data-তে খুব জরুরি, যা Episode 05-এ দেখেছি)।

💻 ৭. কোড: k-fold CV হাতে-কলমে (scikit-learn)

কেন scikit-learn? কারণ এটাই industry-তে classical ML-এর standard, আর CV/tuning এর মধ্যে built-in।

import numpy as np from sklearn.datasets import make_classification from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import cross_val_score, StratifiedKFold # একটা উদাহরণ dataset (বাস্তবে এখানে আপনার churn/job data বসবে) X, y = make_classification( n_samples=1000, n_features=20, n_informative=8, weights=[0.7, 0.3], random_state=42, ) model = RandomForestClassifier(n_estimators=200, random_state=42) # StratifiedKFold: প্রতিটা fold-এ class অনুপাত ঠিক রাখে cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42) scores = cross_val_score(model, X, y, cv=cv, scoring="f1") print("প্রতি fold f1:", np.round(scores, 3)) print("গড় f1: %.3f (+/- %.3f)" % (scores.mean(), scores.std()))
একটা মাত্র সংখ্যা (একবারের accuracy) বিশ্বাস করবেন না। CV আপনাকে গড় ± স্ট্যান্ডার্ড ডেভিয়েশন দেয় — যা বলে model কতটা স্থিতিশীল। বড় std মানে model অস্থির, ভরসা কম।

🎛️ ৮. Hyperparameter কী, আর কেন tune করতে হয়

দুই ধরনের "parameter" আছে। Parameter = model নিজে data থেকে শেখে (যেমন linear regression-এর coefficient)। Hyperparameter = আপনি training-এর আগে সেট করেন, model এগুলো শেখে না (যেমন Random Forest-এর n_estimators, max_depth; XGBoost-এর learning_rate)।

Parameter

data থেকে শেখা হয় (training-এ)।
উদাহরণ: weight, coefficient, split threshold।
Hyperparameter

আপনি হাতে সেট করেন (training-এর আগে)।
উদাহরণ: max_depth, n_estimators, learning_rate

ভুল hyperparameter মানেই overfitting বা underfitting। যেমন — খুব বেশি max_depth = tree সব মুখস্থ করে (overfit); খুব কম = কিছুই শেখে না (underfit)। সঠিক মান খুঁজে বের করার প্রক্রিয়াই hyperparameter tuning

🔍 ৯. GridSearchCV ও RandomizedSearchCV

GridSearchCV: আপনি কিছু মান দেন, এটা প্রতিটা সম্ভাব্য combination CV দিয়ে যাচাই করে সেরাটা বেছে দেয় (নিখুঁত কিন্তু ধীর)। RandomizedSearchCV: combination থেকে random কিছু চেষ্টা করে (দ্রুত, বড় search space-এ বেশি কার্যকর)।

from sklearn.model_selection import GridSearchCV param_grid = { "n_estimators": [100, 200, 400], "max_depth": [4, 8, 16, None], "min_samples_leaf": [1, 2, 5], } grid = GridSearchCV( RandomForestClassifier(random_state=42), param_grid=param_grid, cv=cv, # উপরের StratifiedKFold scoring="f1", n_jobs=-1, # সব CPU core ব্যবহার ) grid.fit(X, y) print("সেরা hyperparameter:", grid.best_params_) print("সেরা CV f1: %.3f" % grid.best_score_) best_model = grid.best_estimator_ # এটাই final model
খুব গুরুত্বপূর্ণ: preprocessing (scaling, encoding) সবসময় Pipeline-এর ভেতরে রাখুন, তারপর সেই pipeline-কে CV-তে দিন। নাহলে scaling পুরো data-র উপর হয়ে গেলে validation fold-এর তথ্য চুইয়ে ঢুকে data leakage হয় — CV score মিথ্যা রকম ভালো দেখায়।

🧪 ১০. Experiment: overfit model-কে ধরা ও সারানো

নিজে চালিয়ে দেখুন — একটা ইচ্ছাকৃত overfit model বানান, তারপর সারান:

from sklearn.model_selection import train_test_split from sklearn.metrics import f1_score from sklearn.tree import DecisionTreeClassifier X_tr, X_te, y_tr, y_te = train_test_split( X, y, test_size=0.2, stratify=y, random_state=42, ) # ধাপ ১: ইচ্ছাকৃত overfit (গভীর tree, কোনো সীমা নেই) over = DecisionTreeClassifier(random_state=42) # max_depth=None over.fit(X_tr, y_tr) print("Overfit -> train:", f1_score(y_tr, over.predict(X_tr))) print("Overfit -> test :", f1_score(y_te, over.predict(X_te))) # আশা করুন: train ~1.0, test অনেক কম => বড় gap = overfitting # ধাপ ২: সারানো (depth সীমিত + leaf সীমা = regularization) fixed = DecisionTreeClassifier( max_depth=5, min_samples_leaf=10, random_state=42, ) fixed.fit(X_tr, y_tr) print("Fixed -> train:", f1_score(y_tr, fixed.predict(X_tr))) print("Fixed -> test :", f1_score(y_te, fixed.predict(X_te))) # আশা করুন: train একটু কমবে, কিন্তু test বাড়বে; gap ছোট হবে

কী দেখবেন: ধাপ ১-এ train আর test-এর মধ্যে বিশাল gap = overfitting-এর স্পষ্ট প্রমাণ। ধাপ ২-এ gap ছোট হয়ে test score উন্নত — এটাই regularization-এর শক্তি। মনে রাখবেন, সামান্য কম train score কিন্তু ভালো test score = ভালো model।

🇧🇩 ১১. Bangladesh উদাহরণ ও Boss Question

ধরুন একটা fintech (যেমন bKash/Nagad ধরনের) fraud detection model বানাল, past ৬ মাসের data-তে ৯৮% accuracy। Production-এ গিয়ে সেটা ভুয়া transaction ধরতে পারল না — কারণ model পুরনো fraud pattern মুখস্থ করেছিল, নতুন pattern-এ generalize করেনি। CV দিয়ে আগে যাচাই করলে এই ঝুঁকি অনেকটা ধরা পড়ত।

💼 Boss Question

Boss: "তুমি বললে model ৯৯% accurate। তাহলে আসল customer-দের উপর চালানোর পর এত ভুল কেন? আমার তো টাকা যাচ্ছে!"

উত্তর: "স্যার, ৯৯% ছিল training data-তে — অর্থাৎ model যা আগে দেখেছে তার উপর। আসল পরীক্ষা হয় আগে-না-দেখা data-তে। আমরা এখন থেকে cross-validation দিয়ে deploy করার আগেই realistic performance মাপব, আর hyperparameter tuning দিয়ে model যেন generalize করে সেটা নিশ্চিত করব। তাহলে production-এর ভুল, মানে আপনার আর্থিক ঝুঁকি, অনেক কমবে।" — এটাই CV/tuning-এর business value: deploy-এর আগে বাস্তব ঝুঁকি জানা।

🔎 ১২. Job Requirement Decoder

JD-তে প্রায়ই দেখবেন: "Experience with model evaluation, cross-validation and hyperparameter tuning."

১. কী বোঝায়? আপনি model-কে honestly যাচাই করতে জানেন — শুধু train accuracy দেখে সিদ্ধান্ত নেন না।

২. কেন চায়? Overfit model production-এ টাকা ও বিশ্বাস নষ্ট করে; কোম্পানি এমন কাউকে চায় যে এই ফাঁদ চেনে।

৩. কোন সমস্যা সমাধান করে? "lab-এ ভালো, বাস্তবে খারাপ" — এই gap ধরা ও কমানো।

৪. junior-এর কী জানা লাগে? train/val/test split, k-fold ও StratifiedKFold, overfit vs underfit ধরা, GridSearchCV/RandomizedSearchCV, Pipeline দিয়ে leakage এড়ানো।

৫. এখনই কী master লাগে না? Bayesian optimization, Optuna, nested CV — এগুলো পরে।

৬. GitHub-এ কীভাবে দেখাবে? একটা notebook-এ train vs val curve, CV score (mean±std), আর tuning-এর আগে-পরে তুলনা দেখান।

৭. Interview-তে কী জিজ্ঞেস করতে পারে? "Overfitting কীভাবে ধরবেন/কমাবেন?", "k-fold CV কেন?", "Grid vs Random search?", "Pipeline ছাড়া CV করলে সমস্যা কী?"
Must Know: overfit/underfit, k-fold CV, GridSearchCV, Pipeline। Good to Know: RandomizedSearchCV, learning curve, StratifiedKFold। Learn Later: Optuna/Bayesian tuning, nested CV। — চাকরির আগে Must+Good, বাকিটা পরে শিখলেও চলবে।

⚠️ ১৩. সাধারণ ভুল

ভুল ১: শুধু training accuracy দেখে খুশি হওয়া। → validation/CV score দেখুন।

ভুল ২: test set বারবার দেখে model tune করা। → test একদম শেষে, একবার।

ভুল ৩: পুরো data-তে scaling/encoding করে তারপর split করা। → leakage; Pipeline + CV ব্যবহার করুন।

ভুল ৪: imbalanced data-তে সাধারণ KFold ব্যবহার। → StratifiedKFold নিন।

ভুল ৫: "overfitting = সবসময় খারাপ, কম train score = খারাপ" ভাবা। → সামান্য কম train কিন্তু ভালো test = ভালো model। gap-টাই আসল কথা।

🎤 ১৪. Interview Prep

প্রশ্ন ১: Overfitting কী এবং কীভাবে কমাবেন?
উত্তর: model training data (noise সহ) মুখস্থ করে, নতুন data-তে খারাপ করে। কমানোর উপায় — আরও data, regularization, model সরল করা (কম depth), cross-validation দিয়ে যাচাই।

প্রশ্ন ২: Cross-validation কেন দরকার, একটা test set যথেষ্ট নয় কেন?
উত্তর: একবারের split ভাগ্য-নির্ভর; CV প্রতিটা data point-কে validation-এ নেয়, তাই স্থিতিশীল ও নির্ভরযোগ্য estimate দেয়, বিশেষত ছোট data-তে।

প্রশ্ন ৩: Parameter আর hyperparameter-এর পার্থক্য?
উত্তর: parameter model data থেকে শেখে (coefficient); hyperparameter আপনি training-এর আগে সেট করেন (max_depth, learning_rate)।

প্রশ্ন ৪: Grid search বনাম random search?
উত্তর: grid সব combination দেখে (নিখুঁত, ধীর); random কিছু random combination দেখে (দ্রুত, বড় search space-এ বেশি কার্যকর)।

✍️ ১৫. হাতে-কলমে

Episode 06-এর Random Forest churn model নিন (P3)। এবার:

১. train_test_split করে train ও test আলাদা করুন (test সিন্দুকে তালা)।
২. train-এ StratifiedKFold(5) দিয়ে cross_val_score বের করুন — mean±std লিখুন।
৩. GridSearchCV দিয়ে max_depthn_estimators tune করুন।
৪. tuning-এর আগের ও পরের test f1 তুলনা করুন।
৫. একটা DecisionTree-কে ইচ্ছাকৃত overfit করান, train vs test gap দেখান।

প্রশ্ন: tuning কি সবসময় বড় উন্নতি দেয়? কখন দেয় না?

🚀 ১৬. Project Connection ও সারসংক্ষেপ

আমাদের flagship "Bangladesh Tech Career Assistant"-এ যখন আমরা JD থেকে role/seniority predict করব (V3), তখন CV দিয়ে যাচাই করব model সত্যিই generalize করে কি না — নাহলে একটা নির্দিষ্ট কোম্পানির JD-তে ভালো, বাকিতে ভুল করবে। P2 (House Price) ও P3 (Churn) দুটোতেই এই CV+tuning প্রয়োগ করলে portfolio অনেক শক্ত দেখাবে।

এই Episode-এ শিখলাম:

✓ Overfitting = data মুখস্থ (high variance); Underfitting = কিছুই শেখেনি (high bias)
✓ শুধু training score মিথ্যা আশা দেয় — train vs validation gap দেখুন
✓ Train → Validation → Test-এর সঠিক ভূমিকা, আর test set "তালাবদ্ধ" রাখা
✓ k-fold ও StratifiedKFold cross-validation নির্ভরযোগ্য estimate দেয় (mean±std)
✓ Parameter ≠ hyperparameter; GridSearchCV/RandomizedSearchCV দিয়ে tuning
✓ Pipeline + CV দিয়ে preprocessing leakage এড়ানো — নাহলে score মিথ্যা ভালো
পরবর্তী Episode: Unsupervised Learning — K-Means ও PCA। এতক্ষণ আমরা label নিয়ে (supervised) কাজ করেছি; এবার দেখব label ছাড়াই data-তে কীভাবে pattern ও গঠন খুঁজে বের করা যায়।
© 2025 Sheikh Thanbir Alam. All Rights Reserved. thanbirtamim.github.io
এই লেখা মূল লেখকের সম্পত্তি — লিখিত অনুমতি ছাড়া কপি করে অন্য কোনো ওয়েবসাইট, ব্লগ, বই বা প্ল্যাটফর্মে প্রকাশ/বিতরণ করা কঠোরভাবে নিষিদ্ধ। Content may not be copied or republished without permission.