Data Preprocessing: encoding, scaling, আর 'data leakage'-এর ফাঁদ

model-এ ঢোকানোর আগে data প্রস্তুত করা (Series 03, Episode 08)

🟡 INTERMEDIATE Series 03 — Data — AI-এর ভিত্তি Episode 08 / 09

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

🧩 ১. গল্প: Rahim-এর "৯৯% accuracy" model বাস্তবে ফেল

Rahim প্রথম ML model বানিয়ে উচ্ছ্বসিত — training-এ ৯৯% accuracy! কিন্তু production-এ দেওয়ার পর model যাচ্ছেতাই prediction দিচ্ছে। Boss বিরক্ত, Rahim হতভম্ব।

Rahim: "Maya আপা, আমার model তো ৯৯% accuracy দিয়েছিল! বাস্তবে এত খারাপ কেন?"

Maya: "তোমার model cheat করেছে — তুমি বুঝতে পারোনি। এটাকে বলে data leakage। আর তার আগে প্রশ্ন — তুমি কি missing value, categorical column আর scaling ঠিকমতো handle করেছিলে? Model যত ভালোই হোক, garbage in → garbage out। আজ আমরা preprocessing শিখব — data-কে ML-এর যোগ্য করে তোলা, আর সেই ভয়ংকর leakage কীভাবে এড়ানো যায়।"

২. সমস্যা: ML model কাঁচা data নেয় না

বাস্তব data সবসময় নোংরা। একটা সাধারণ job/customer dataset-এ থাকে:

Preprocessing = এই সমস্যাগুলো ঠিক করে data-কে model-এর যোগ্য, পরিষ্কার সংখ্যার টেবিলে রূপান্তর করা।

🎯 ৩. কেন preprocessing দরকার

Must Know / Good to Know / Learn Later:
Must Know: missing value handling, one-hot/label encoding, standardization, train/test split, data leakage ধারণা।
Good to Know: outlier treatment, scikit-learn Pipeline, target/frequency encoding।
Learn Later: advanced imputation (KNN/iterative), feature store, automated preprocessing।

🪜 ৪. তিন Level-এ preprocessing বোঝা

Level 1 — সহজ intuition

রান্নার আগে সবজি ধুয়ে, কেটে, বেছে নিতে হয় — পচা অংশ ফেলে দিতে হয়। Preprocessing হলো ML-এর সেই "সবজি কাটার" ধাপ। নোংরা data সরাসরি model-এ দিলে রান্না নষ্ট হবেই।

Level 2 — technical ভাবে

Preprocessing মানে raw feature-গুলোকে এমন সংখ্যায় রূপান্তর করা যা model-friendly — missing value পূরণ (imputation), category-কে সংখ্যায় (encoding), সব feature একই scale-এ (scaling), আর অস্বাভাবিক মান (outlier) নিয়ে সিদ্ধান্ত।

Level 3 — engineer দৃষ্টিতে

Engineer রা preprocessing-কে একটা reproducible pipeline হিসেবে দেখে — training-এ যা করা হয়, হুবহু তাই inference/production-এ হতে হবে। আর সবচেয়ে বড় শঙ্কা — এই ধাপে যেন future/test তথ্য leak না হয়। এটাই junior আর engineer-এর আসল পার্থক্য।

🕳️ ৫. Missing value: চেনা ও সামলানো

import pandas as pd import numpy as np df = pd.DataFrame({ "title": ["Python Dev", "ML Engineer", "Data Analyst", "Backend"], "salary": [45000, np.nan, 40000, 70000], "city": ["Dhaka", "Dhaka", np.nan, "Sylhet"], }) # কোথায় কতগুলো missing? print(df.isna().sum()) # কৌশল ১: বাদ দেওয়া (missing কম হলে) df_dropped = df.dropna() # কৌশল ২: number column পূরণ (median বেশি robust) df["salary"] = df["salary"].fillna(df["salary"].median()) # কৌশল ৩: category column পূরণ (mode / "Unknown") df["city"] = df["city"].fillna("Unknown")
কখন কোনটা? missing খুব কম হলে row বাদ দেওয়া চলে। বেশি হলে পূরণ (impute) করুন — number-এ median (outlier-এ কম প্রভাবিত), category-তে mode বা আলাদা "Unknown" class। সতর্কতা: median/mean হিসাব করতে হবে শুধু training data থেকে (নিচে leakage অংশে বিস্তারিত)।

🔤 ৬. Categorical variable: encoding

Model text বোঝে না — category-কে সংখ্যায় আনতে হবে। দুটো প্রধান উপায়:

# One-Hot Encoding: প্রতিটা category => আলাদা 0/1 column # (nominal/ক্রমহীন category-র জন্য: city, industry) df_ohe = pd.get_dummies(df, columns=["city"]) # city_Dhaka, city_Sylhet, city_Unknown => 0/1 # Label / Ordinal Encoding: category => 0,1,2... # (ordinal/ক্রম-যুক্ত category-র জন্য: "Low<Mid<High") from sklearn.preprocessing import OrdinalEncoder levels = [["Low", "Mid", "High"]] enc = OrdinalEncoder(categories=levels) # enc.fit_transform(df[["level"]]) # Low=0, Mid=1, High=2
গুরুত্বপূর্ণ নিয়ম: ক্রমহীন category-তে (city, color) label encoding (0,1,2) দেবেন না — তাহলে model ভুল করে ভাববে "Sylhet(2) > Dhaka(1)", যা অর্থহীন। সেখানে one-hot ব্যবহার করুন। শুধু সত্যিকারের ক্রম থাকলে (Low/Mid/High) ordinal encoding ঠিক আছে।

📏 ৭. Normalization বনাম Standardization (scaling)

age (২০–৬০) আর salary (৩০০০০–২০০০০০) একই scale-এ না থাকলে অনেক algorithm বড় সংখ্যাকে বেশি গুরুত্ব দেয়। সমাধান scaling:

Normalization (Min-Max)
মানকে ০–১ range-এ আনে।
সূত্র: (x − min) / (max − min)
outlier-এ সংবেদনশীল।
Standardization (Z-score)
গড়=০, std=১ করে।
সূত্র: (x − mean) / std
সাধারণত বেশি ব্যবহৃত ও robust।
from sklearn.preprocessing import StandardScaler, MinMaxScaler scaler = StandardScaler() # গড়=0, std=1 X_scaled = scaler.fit_transform(X_train[["age", "salary"]]) # একই scaler test-এ শুধু transform (fit নয়!) — নিচে কারণ X_test_scaled = scaler.transform(X_test[["age", "salary"]])
Tree-based model (Decision Tree, Random Forest, XGBoost)-এ scaling সাধারণত লাগে না — এরা scale-invariant। কিন্তু Linear/Logistic Regression, KNN, SVM, neural net-এ scaling প্রায় বাধ্যতামূলক।

🎯 ৮. Outlier: চেনা ও সিদ্ধান্ত

# IQR পদ্ধতিতে outlier চেনা Q1 = df["salary"].quantile(0.25) Q3 = df["salary"].quantile(0.75) IQR = Q3 - Q1 low = Q1 - 1.5 * IQR high = Q3 + 1.5 * IQR outliers = df[(df["salary"] < low) | (df["salary"] > high)] print(outliers)
সব outlier ফেলে দেবেন না! কিছু outlier আসল, গুরুত্বপূর্ণ signal (যেমন fraud detection-এ অস্বাভাবিক transaction-ই তো target)। আগে বুঝুন এটা ভুল data (data entry error) নাকি সত্যিকারের বিরল ঘটনা। ভুল হলে ঠিক করুন/বাদ দিন; আসল হলে রাখুন বা আলাদাভাবে model করুন।

💀 ৯. Data leakage কী — সবচেয়ে বিপজ্জনক ভুল

Data leakage হলো — model training-এর সময় এমন তথ্য দেখে ফেলা যা বাস্তবে prediction-এর মুহূর্তে পাওয়া যাবে না (future বা test তথ্য)। ফল: training/test-এ দুর্দান্ত score, কিন্তু production-এ ভয়াবহ ফেল।

Leakage যেভাবে ঘটে (দুটো ক্লাসিক উদাহরণ): ১) পুরো data-তে scale/impute করে তারপর split -> test-এর mean/std training-এ "leak" হলো -> model আসলে test সম্পর্কে আগেই "জানে" ২) target থেকে তৈরি feature model-এ ঢোকানো যেমন churn predict করতে "account_closed_date" -> এটা তো churn হওয়ার পরেই পাওয়া যায়! -> model cheat করছে, বাস্তবে থাকবে না
Rahim-এর "৯৯% accuracy"-র রহস্য এখানেই: সে পুরো dataset-এ scaling করেছিল তারপর train/test split করেছিল — test-এর তথ্য training-এ leak করেছে। Model test data আগেই "চিনে ফেলেছিল"।

✂️ ১০. train/test split ও leakage এড়ানো

সঠিক ক্রম সবসময়: আগে split, তারপর শুধু training data থেকে fit — তারপর test-এ শুধু transform।

from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler # ধাপ ১: আগে split (leakage-এর প্রথম প্রতিরক্ষা) X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42 ) scaler = StandardScaler() # ধাপ ২: fit শুধু training data-তে (mean/std শেখা) X_train_scaled = scaler.fit_transform(X_train) # ধাপ ৩: test-এ শুধু transform (একই mean/std প্রয়োগ) X_test_scaled = scaler.transform(X_test) # fit নয়!
মন্ত্র মনে রাখুন: fit শুধু train-এ, transform সব জায়গায়। imputation, scaling, encoding — সব preprocessing-এর statistic (mean, median, category তালিকা) শুধু training data থেকে শিখতে হবে।

🔧 ১১. scikit-learn Pipeline: leakage-proof উপায়

হাতে হাতে fit/transform মনে রাখা কঠিন — একটা ভুলেই leakage। এর সবচেয়ে নিরাপদ সমাধান Pipeline + ColumnTransformer, যা cross-validation-এও leakage আটকায়:

from sklearn.pipeline import Pipeline from sklearn.compose import ColumnTransformer from sklearn.preprocessing import StandardScaler, OneHotEncoder from sklearn.impute import SimpleImputer from sklearn.linear_model import LogisticRegression num_cols = ["age", "salary"] cat_cols = ["city", "industry"] # number: median দিয়ে পূরণ + standardize num_pipe = Pipeline([ ("impute", SimpleImputer(strategy="median")), ("scale", StandardScaler()), ]) # category: mode দিয়ে পূরণ + one-hot cat_pipe = Pipeline([ ("impute", SimpleImputer(strategy="most_frequent")), ("onehot", OneHotEncoder(handle_unknown="ignore")), ]) pre = ColumnTransformer([ ("num", num_pipe, num_cols), ("cat", cat_pipe, cat_cols), ]) # পুরো flow এক object-এ: preprocess + model model = Pipeline([ ("pre", pre), ("clf", LogisticRegression(max_iter=1000)), ]) model.fit(X_train, y_train) # সব fit শুধু train-এ model.score(X_test, y_test) # test-এ শুধু transform, নিরাপদ
কেন Pipeline? এটা preprocessing ও model-কে এক করে রাখে — তাই fit শুধু train-এ হয়, আর cross-validation করলেও প্রতিটা fold-এ leakage আপনাআপনি এড়ানো হয়। production-এ deploy করাও সহজ (এক object)।

🇧🇩 ১২. বাস্তব উদাহরণ: BD churn data preprocessing

ধরুন একটা BD telecom (GP/Robi ধরনের) churn dataset — কে গ্রাহক ছেড়ে যাবে। column: age, monthly_bill, plan_type (category), tenure, target churned। একজন engineer যা করবে:

# ১. LEAKAGE ফাঁদ: এই column বাদ দিতে হবে! # "disconnection_date" — churn হওয়ার পরেই জানা যায় df = df.drop(columns=["disconnection_date"]) # ২. আগে split X = df.drop(columns=["churned"]) y = df["churned"] X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, stratify=y, random_state=42 ) # ৩. Pipeline দিয়ে impute+scale+encode (সব fit train-এ) model.fit(X_train, y_train)

stratify=y কেন? churn সাধারণত imbalanced (হয়তো ১০% churn); stratify নিশ্চিত করে train ও test-এ churn-এর অনুপাত একই থাকে।

👷 ১৩. একজন AI Engineer-এর দৃষ্টিতে

Engineer রা তিনটা জিনিস কখনো ভোলে না:

১. আগে split, তারপর fit — leakage-এর এক নম্বর প্রতিরক্ষা।
২. Pipeline-এ সব preprocessing bundle করা — যাতে training ও production-এ হুবহু একই রূপান্তর হয়।
৩. প্রতিটা feature-কে প্রশ্ন করা: "prediction-এর মুহূর্তে এটা কি সত্যিই জানা থাকবে?" — না হলে সেটা leakage, বাদ দিতে হবে।

"কাগজে দারুণ score কিন্তু বাস্তবে খারাপ" — এর ৯০% কারণ data leakage। তাই engineer সবার আগে এই ফাঁদটা খোঁজে।

💼 ১৪. Boss Question

Boss: "Model বানানোই তো আসল কাজ, এই data ধোয়ামোছায় এত সময় কেন? এটা business-এ কী দেয়?"

উত্তর: কারণ ভুল preprocessing মানে ভুল model — আর ভুল model ব্যবসায় সরাসরি ক্ষতি। ধরুন churn model leakage-এর কারণে test-এ ৯৯% দেখাল, আমরা ভরসা করে marketing budget সাজালাম, বাস্তবে model কিছুই ধরল না — টাকা নষ্ট, আস্থা নষ্ট। ভালো preprocessing মানে model বাস্তবেও যেমন score দেখায় তেমনই কাজ করে — এটাই নির্ভরযোগ্য, তাই business-value-যুক্ত AI।

🔎 ১৫. Job Requirement Decoder

"Experience with data preprocessing, feature scaling, and building robust ML pipelines."
প্রশ্নউত্তর
এর মানে কী?আপনি কাঁচা data পরিষ্কার করে, encode/scale করে, leakage ছাড়া model-ready করতে পারেন।
কোম্পানি কেন চায়?বাস্তবে সময়ের বড় অংশ data preprocessing-এ যায়; ভুল হলে পুরো model অকেজো।
কোন সমস্যা সমাধান করে?"training-এ ভালো, production-এ খারাপ" model-এর মূল কারণ (leakage) দূর করে।
Junior-এর কী জানা লাগে?missing value, one-hot/ordinal encoding, standardization, train/test split, leakage, sklearn Pipeline।
এখনই কী master লাগে না?advanced imputation, feature store, automated feature engineering tool।
GitHub-এ কীভাবে দেখাবেন?একটা project-এ Pipeline + ColumnTransformer ব্যবহার করে README-তে leakage-এড়ানোর কৌশল ব্যাখ্যা করুন।
Interview-তে কী জিজ্ঞেস করতে পারে?"data leakage কী ও কীভাবে এড়াবেন?", "normalization vs standardization?", "কেন fit শুধু train-এ?"

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

ভুল ১: পুরো data-তে scale/impute করে তারপর split। → ঠিক: আগে split, তারপর শুধু train-এ fit — নাহলে leakage।

ভুল ২: test data-তে fit_transform করা। → ঠিক: test-এ শুধু transform; statistic train থেকেই আসবে।

ভুল ৩: ক্রমহীন category-তে label encoding (0,1,2)। → ঠিক: nominal-এ one-hot; ordinal encoding শুধু সত্যিকারের ক্রম থাকলে।

ভুল ৪: সব outlier অন্ধভাবে ফেলে দেওয়া। → ঠিক: আগে বুঝুন ভুল data নাকি আসল বিরল ঘটনা।

ভুল ৫: target-নির্ভর/future column feature হিসেবে রাখা। → ঠিক: prediction-মুহূর্তে পাওয়া যাবে না এমন column বাদ দিন (leakage)।

🎤 ১৭. Interview Prep

প্রশ্ন ১: Data leakage কী এবং কীভাবে এড়াবেন?
উত্তর: training-এ এমন তথ্য দেখা যা inference-এ পাওয়া যাবে না। এড়াতে — আগে split, fit শুধু train-এ, target/future column বাদ, আর Pipeline ব্যবহার।

প্রশ্ন ২: Normalization আর standardization-এর পার্থক্য, কখন কোনটা?
উত্তর: normalization ০–১ range-এ আনে (min-max); standardization গড়=০/std=১ করে (z-score)। সাধারণত standardization বেশি robust; distribution-নির্দিষ্ট algorithm-এ পছন্দমতো।

প্রশ্ন ৩: ক্রমহীন category-তে label encoding কেন খারাপ?
উত্তর: এটা কৃত্রিম ক্রম/দূরত্ব তৈরি করে (Sylhet>Dhaka), যা model ভুল ব্যাখ্যা করে। one-hot ভালো।

প্রশ্ন ৪: Tree-based model-এ কি scaling লাগে?
উত্তর: সাধারণত না; এরা scale-invariant। কিন্তু Linear/KNN/SVM/neural net-এ লাগে।

✍️ ১৮. হাতে-কলমে (Mini Exercise)

একটা ছোট dataset (নিজের বানানো বা Kaggle-এর Titanic) নিয়ে করুন:

১. প্রতিটা column-এ কতগুলো missing value আছে বের করুন।
২. number column median দিয়ে, category column mode দিয়ে পূরণ করুন।
৩. একটা category column one-hot encode করুন।
৪. train_test_split করে শুধু train-এ StandardScaler.fit করুন, test-এ শুধু transform।
৫. একই কাজ Pipeline + ColumnTransformer দিয়ে করুন এবং বলুন কেন এটা leakage থেকে নিরাপদ।

🚀 ১৯. Project Connection

flagship "Bangladesh Tech Career Assistant"-এ আমরা এবার job data-কে ML-ready করব — city/industry one-hot, salary/experience standardize, missing value impute — সব একটা leakage-proof Pipeline-এ।

Project P3 (Customer Churn Prediction)-এ এই preprocessing সরাসরি লাগবে — বিশেষ করে leakage এড়ানো ও stratified split। এই পর্বের Pipeline-ই পরের সিরিজে (Series 05) model-এর সাথে জুড়ে যাবে।

📌 ২০. সারসংক্ষেপ

এই পর্বে আমরা শিখলাম:

✓ কেন ML model কাঁচা data নেয় না — garbage in, garbage out
Missing value চেনা ও impute (median/mode/Unknown)
Encoding — nominal-এ one-hot, ordinal-এ ordinal (label encoding-এর ফাঁদ)
Scaling — normalization vs standardization, কোথায় লাগে কোথায় লাগে না
Outlier — অন্ধভাবে ফেলবেন না, আগে বুঝুন
Data leakage — সবচেয়ে বিপজ্জনক ভুল, "কাগজে ভালো, বাস্তবে ফেল"-এর মূল কারণ
আগে split, fit শুধু train-এ, আর leakage-proof scikit-learn Pipeline

➡️ ২১. পরবর্তী পর্বে কী শিখব

পরবর্তী Episode (S03E09): "Project — Bangladesh Job Market Data দিয়ে প্রশ্নের উত্তর বের করা"।

NumPy, Pandas, Matplotlib, SQL আর preprocessing — এই সিরিজের সব শেখা এবার এক জায়গায়। আমরা flagship-এর Project P1 (Bangladesh Job Market Data Analyzer) সম্পূর্ণ করব — একটা end-to-end EDA project যা data দিয়ে বাস্তব প্রশ্নের উত্তর দেয়, আর হবে আপনার প্রথম portfolio piece।
© 2025 Sheikh Thanbir Alam. All Rights Reserved. thanbirtamim.github.io
এই লেখা মূল লেখকের সম্পত্তি — লিখিত অনুমতি ছাড়া কপি করে অন্য কোনো ওয়েবসাইট, ব্লগ, বই বা প্ল্যাটফর্মে প্রকাশ/বিতরণ করা কঠোরভাবে নিষিদ্ধ। Content may not be copied or republished without permission.