Chapter 3 of 18
The vocabulary of the table every model actually learns from
আগের চ্যাপ্টারে একটা কথা বারবার শুনেছেন: "মডেল ডেটা থেকে শেখে।" Supervised learning-এর লেবেল করা ডেটা লাগে, unsupervised-এর লেবেল ছাড়া ডেটা, semi-supervised-এর একটু একটা আর অনেকটা আরেকটা। কিন্তু "ডেটা" জিনিসটা মডেলের কাছে পৌঁছানোর সময় আসলে দেখতে কেমন — সেটা কেউ বলেনি। এই চ্যাপ্টারটা ঠিক সেই কথাটাই।
Dataset মানে হলো উদাহরণের একটা সংগ্রহ, যেখান থেকে মডেল শেখে। এলোমেলো তথ্যের স্তূপ না — গোছানো একটা সংগ্রহ, যেখানে প্রতিটা উদাহরণকে একই কায়দায়, একই মাপগুলো দিয়ে বর্ণনা করা হয়েছে, যাতে একটার সাথে আরেকটা তুলনা করা যায়।
সবচেয়ে সহজে বোঝার উপায় হলো একটা এক্সেল শিট কল্পনা করা। ধরুন একটা ব্যাংকের পুরনো লোনের রেকর্ড:
| বয়স | মাসিক আয় (টাকা) | চাকরির বছর | চলমান লোন | শোধ করেছে? |
|---|---|---|---|---|
| ২৮ | ৪৫,০০০ | ৩ | ১ | হ্যাঁ |
| ৪১ | ১,২০,০০০ | ১২ | ০ | হ্যাঁ |
| ২৩ | ২২,০০০ | ১ | ২ | না |
| ৩৫ | ৭৮,০০০ | ৭ | ১ | হ্যাঁ |
পুরো টেবিলটাই dataset। প্রতিটা সারি (row) একজন লোন আবেদনকারী। প্রতিটা কলাম তার সম্পর্কে মাপা একটা জিনিস। ব্যস, এতটুকুই — আর পরে যত ML কনসেপ্ট শিখবেন, প্রায় সবগুলোই এই ছবিটার ভাষাতেই সংজ্ঞায়িত।
খেয়াল করুন, প্রতিটা সারিতে ঠিক একই চারটা জিনিস, ঠিক একই ক্রমে লেখা আছে। এটা সাজানোর শখ না — এটা বাধ্যতামূলক। মডেল শেখে উদাহরণগুলো একে অপরের সাথে তুলনা করে ("যাদের আয় বেশি আর চলমান লোন কম, তারা বেশিরভাগ শোধ করেছে")। এক সারিতে যদি আয় থাকে আর আরেক সারিতে আয়ের বদলে জুতার সাইজ থাকে, তাহলে তুলনা করার কিছুই থাকে না। এই সামঞ্জস্যটাই একগাদা রেকর্ডকে একটা dataset বানায়।
এখন একটা কথা আগেই বলে রাখি, নাহলে পরে গুলিয়ে যাবে: সব ডেটা কিন্তু এমন সুন্দর টেবিল হয়ে আসে না। একটা ছবি আসলে পিক্সেলের উজ্জ্বলতার গ্রিড। একটা অডিও ক্লিপ হাজার হাজার সংখ্যার সিকোয়েন্স। একটা বাক্য শুধু কিছু শব্দ। কোনোটাই এক্সেল শিট হয়ে আসে না।
কিন্তু আসল কথাটা হলো — মডেলের কাছে পৌঁছানোর আগে এগুলো সবাইকে টেবিলে রূপান্তর করা হয়। হাতে লেখা একটা সংখ্যার ২৮×২৮ সাদাকালো ছবি হয়ে যায় ৭৮৪টা সংখ্যার একটা সারি (প্রতি পিক্সেলে একটা)। দশ সেকেন্ডের অডিও হয়ে যায় হাজার হাজার সংখ্যার সারি। একটা বাক্য হয়ে যায় শব্দগুলোর প্রতিনিধিত্ব করা সংখ্যার সারি। মানে, এক্সেল শিটের এই মানসিক ছবিটা শুধু টেবিল-আকৃতির ডেটার জন্য না — এটাই সেই আকৃতি যেটায় সবকিছু বদলে নেওয়া হয়।
বাস্তবে ট্রেইনিংয়ের আগে dataset-টাকে ভাগ করে ফেলা হয় — একটা training set যেটা থেকে মডেল শেখে, আর একটা test set যেটা সরিয়ে রাখা হয় দেখার জন্য যে মডেল আসলেই কিছু শিখেছে কিনা। এই ভাগটা নিয়ে পরের একটা চ্যাপ্টারে বিস্তারিত আসবে। আপাতত শুধু জেনে রাখুন, "the dataset" বলতে সাধারণত ভাগ করার আগের পুরো সংগ্রহটাকে বোঝায়।
এখানে এমন একটা জিনিস আছে যেটায় প্রায় সব শিক্ষার্থী প্রথমবার হোঁচট খায়: sample, instance, observation, example, data point, record, আর row — এই সাতটা শব্দ একদম একই জিনিস বোঝায়।
Dataset-এর একটামাত্র আইটেম। টেবিলের একটা সারি। একজন লোন আবেদনকারী। একটা ছবি। একটা ইমেইল।
এগুলো কনসেপ্টের সূক্ষ্ম ভ্যারিয়েশন না — বিভিন্ন কমিউনিটির বিভিন্ন অভ্যাস, এই যা। পরিসংখ্যানের লোকেরা বলে "observation"। ডেটাবেসের লোকেরা বলে "record"। ML ইঞ্জিনিয়াররা সাধারণত বলে "sample" বা "example"। রিসার্চ পেপারে থাকে "instance" বা "data point"। ৪৫,০০০ টাকা আয় করা সেই ২৮ বছর বয়সী আবেদনকারীই একসাথে এই সাতটা শব্দের সবগুলো।
| যে শব্দটা দেখবেন | কারা বেশি ব্যবহার করে | মানে কী |
|---|---|---|
| Sample | ML ইঞ্জিনিয়ার, ডিপ লার্নিং কোড আর ডকুমেন্টেশন | Dataset-এর একটা আইটেম |
| Example | বই, টিউটোরিয়াল, ML পেপার | Dataset-এর একটা আইটেম |
| Instance | রিসার্চ পেপার, ক্লাসিক্যাল ML সাহিত্য | Dataset-এর একটা আইটেম |
| Observation | পরিসংখ্যানবিদ, স্ট্যাটস ব্যাকগ্রাউন্ডের ডেটা সায়েন্টিস্ট | Dataset-এর একটা আইটেম |
| Data point | সাধারণ আলাপ, বিশেষ করে গ্রাফের প্রসঙ্গে (একটা ডট) | Dataset-এর একটা আইটেম |
| Record / Row | ডেটাবেস আর ডেটা ইঞ্জিনিয়ারিংয়ের লোকজন | Dataset-এর একটা আইটেম |
গাণিতিকভাবে একটা sample-কে সাধারণত vector হিসেবে লেখা হয় — মানে সংখ্যার একটা সাজানো তালিকা — আর চিহ্ন হিসেবে ব্যবহার হয় । আমাদের প্রথম আবেদনকারী হবে:
উপরের মানে শুধু "১ নম্বর sample"। এটাকে ইনডেক্স হিসেবে পড়ুন, পাওয়ার হিসেবে না — হলো দ্বিতীয় আবেদনকারী, তৃতীয়, এভাবে। টা sample-এর একটা dataset মানে — এই পুরো সংগ্রহটা।
ক্লাসিক্যাল স্ট্যাটিসটিকসে "a sample" বলতে প্রায়ই বোঝায় জনসংখ্যা থেকে নেওয়া একটা গোটা দল — যেমন "আমরা ৫০০ জনের একটা sample নিয়েছি।" কিন্তু ML-এ "a sample" মানে একটামাত্র উদাহরণ। তাই একজন ML-এর লোক "৫,০০০ samples" বললে বোঝায় ৫,০০০টা আলাদা সারি, আর একজন পরিসংখ্যানবিদ "৫,০০০-এর একটা sample" বললে বোঝায় ওই সাইজের একটামাত্র সংগ্রহ। একই শব্দ, আলাদা একক। মিশ্র টিমে এটা নিয়ে সত্যিই ভুল বোঝাবুঝি হয় — সন্দেহ হলে জিজ্ঞেস করে নিন কে কোনটা বোঝাচ্ছেন।
আরেকটা শব্দ আলাদা করে মনে রাখুন: sample size, সাধারণত দিয়ে লেখা হয় — মানে dataset-এ কতগুলো sample আছে। আমাদের ছোট্ট লোন টেবিলে । বাস্তবে হয়তো । মোটা দাগে, sample যত বেশি, মডেলের শেখার প্রমাণও তত বেশি — আর এ কারণেই "আমাদের আরও ডেটা লাগবে" কথাটা মেশিন লার্নিংয়ে সবচেয়ে বেশি শোনা যায়।
Sample যদি হয় একটা সারি, তাহলে feature হলো একটা কলাম। মানে একটা sample-এর একটা মাপযোগ্য বৈশিষ্ট্য — প্রতিটা উদাহরণ সম্পর্কে আপনি যে নির্দিষ্ট জিনিসটা রেকর্ড করেছেন।
লোন টেবিলে feature গুলো হলো: বয়স, মাসিক আয়, চাকরির বছর, আর চলমান লোন। মোট চারটা feature। প্রতিটাই একই আবেদনকারীকে দেখার একেকটা আলাদা চোখ।
Feature-ই সেই জিনিস যা মডেল আসলে দেখে প্রেডিকশন করার সময়। এই কথাটা জোর দিয়ে বলা দরকার, কারণ এটাই ব্যাখ্যা করে কেন বাস্তব ML-এর এত বড় অংশ অ্যালগরিদম নিয়ে না, ডেটা নিয়ে: মডেল শুধু ততটুকুই ব্যবহার করতে পারে যতটুকু feature-এ আছে। ধরুন লোন শোধ করার ব্যাপারে আবেদনকারীর সততা প্রচণ্ড গুরুত্বপূর্ণ, কিন্তু আপনি সেটার সাথে সম্পর্কিত কিছুই রেকর্ড করেননি — তাহলে দুনিয়ার কোনো অ্যালগরিদমই সেটা হিসেবে ধরতে পারবে না। মডেল পৃথিবীকে চেনে না, সে চেনে আপনার কলামগুলোকে।
"Sample"-এর মতো "feature"-এরও কিছু সমার্থক শব্দ আছে যেগুলোর সাথে দেখা হবেই:
| শব্দ | কোন ক্ষেত্র থেকে এসেছে | মন্তব্য |
|---|---|---|
| Feature | মেশিন লার্নিং | স্ট্যান্ডার্ড ML শব্দ — এটাই ব্যবহার করুন |
| Attribute | ডেটা মাইনিং, ডেটাবেস | একদম একই মানে |
| Variable | পরিসংখ্যান | নির্দিষ্টভাবে "independent variable" বা "predictor" |
| Input / Input variable | সাধারণ ML আলোচনা | জোর দেয় যে এটা মডেলের ভেতরে যায় |
| Column / Field | ডেটা ইঞ্জিনিয়ারিং | একই মানে, টেবিল-কেন্দ্রিক ভাষায় |
| Dimension | জ্যামিতিক দৃষ্টিকোণের আলোচনা | একই জিনিস, স্পেসের একটা অক্ষ হিসেবে দেখা — নিচে এটা নিয়ে আরও আছে |
সব feature সাধারণ সংখ্যা না, আর এই ধরনটা গুরুত্বপূর্ণ — কারণ মডেল শুধু অঙ্ক কষতে পারে, তাই শেষ পর্যন্ত সবকিছুই সংখ্যা হয়ে যেতে হবে।
Numerical (continuous)
সত্যিকারের মাপ, যেটা একটা রেঞ্জের মধ্যে যেকোনো মান নিতে পারে: আয় (৪৫,০০০ টাকা), তাপমাত্রা (৩১.৪°C), উচ্চতা (১৭২.৫ সেমি)। এগুলো প্রায় সরাসরিই মডেলে দেওয়া যায়, সাধারণত তুলনীয় রেঞ্জে scale করে নেওয়ার পর।
Numerical (discrete / count)
পূর্ণসংখ্যার গণনা: চলমান লোনের সংখ্যা (২), বাড়ির রুমের সংখ্যা (৩), আগের কেনাকাটার সংখ্যা (১৭)। সংখ্যাই, তবে শুধু পূর্ণ মানেই পড়ে — "২.৫টা লোন" বলে কিছু হয় না।
Categorical (nominal)
নামওয়ালা গ্রুপ, যাদের কোনো স্বাভাবিক ক্রম নেই: শহর (ঢাকা / চট্টগ্রাম / খুলনা), রক্তের গ্রুপ (A / B / O), ডিভাইস (Android / iOS)। ট্রেইনিংয়ের আগে এগুলোকে সংখ্যায় রূপান্তর করতেই হবে — সাধারণত one-hot encoding দিয়ে, যেটা একটা শহর কলামকে কয়েকটা হ্যাঁ/না কলামে ভেঙে ফেলে।
Categorical (ordinal)
নামওয়ালা গ্রুপ, কিন্তু এদের একটা ক্রম আছে: শিক্ষাগত যোগ্যতা (SSC < HSC < অনার্স < মাস্টার্স), সন্তুষ্টির রেটিং (খারাপ < মোটামুটি < ভালো < চমৎকার)। এই ক্রমটা আসল তথ্য, তাই এগুলোকে সাধারণত one-hot না করে ক্রমানুসারে সংখ্যা (১, ২, ৩, ৪) দেওয়া হয়।
ধরুন আপনি শহরকে এনকোড করলেন ঢাকা = ১, চট্টগ্রাম = ২, খুলনা = ৩ — আর সেটা সরাসরি মডেলে দিয়ে দিলেন। মডেল, যে শুধু অঙ্ক বোঝে, চুপচাপ ধরে নেবে খুলনা ঢাকার তিনগুণ, আর চট্টগ্রাম ঠিক এদের মাঝখানে। এর কোনোটাই সত্যি না — ওই সংখ্যাগুলো নিছক নাম ছিল। ঠিক এই কারণেই nominal ক্যাটাগরিকে নম্বর না দিয়ে one-hot encode করা হয় (আলাদা হ্যাঁ/না কলাম): যাতে মডেল এমন একটা ক্রম বানিয়ে না ফেলে যেটার আসলে অস্তিত্বই নেই।
যেহেতু মডেল শুধু feature-এ যা আছে তা-ই ব্যবহার করতে পারে, তাই বাস্তব ML-এর বিরাট একটা সময় খরচ হয় ভালো feature বানাতে। এই কাজটার নাম feature engineering। সহজ কিন্তু শক্তিশালী একটা উদাহরণ: মডেলকে আলাদা করে monthly_income আর monthly_loan_payment না দিয়ে, আপনি নিজে হিসাব করলেন debt_to_income = monthly_loan_payment / monthly_income আর সেটা দিলেন। তথ্যটা টেকনিক্যালি আগেও ছিল, কিন্তু অনুপাত হিসেবে মডেলের জন্য এটা ব্যবহার করা অনেক সহজ — আপনি চিন্তার একটা অংশ ওর হয়ে করে দিলেন। ভালো feature প্রায়ই ফ্যান্সি অ্যালগরিদমকে হারিয়ে দেয়, আর নতুনরা এটাকে ধারাবাহিকভাবে কম গুরুত্ব দেয়।
লোন টেবিলে ফিরে যান আর শেষ কলামটা দেখুন: শোধ করেছে? — হ্যাঁ, হ্যাঁ, না, হ্যাঁ।
এই কলামটা বাকিগুলোর চেয়ে ধরনেই আলাদা। বয়স, আয়, চাকরির বছর, চলমান লোন — এগুলো আবেদনকারীকে বর্ণনা করে ফলাফল জানার আগে। "শোধ করেছে?" নিজেই সেই ফলাফল। নতুন কারও জন্য এটাই মডেলের প্রেডিক্ট করার কথা, আর ট্রেইনিংয়ের সময় এটাই সেই সঠিক উত্তর যেটা আমাদের কাছে আগে থেকেই আছে।
এটাই label: একটা sample-এর সাথে জুড়ে থাকা জানা সঠিক উত্তর।
Supervised learning চ্যাপ্টারের সেই "উত্তরমালা"-র আইডিয়াটাই এটা, এবার তার আসল নামসহ। "Labeled data" পড়লে বুঝবেন প্রতিটা sample-এর এই উত্তর-কলামটা পূরণ করা আছে। "Unlabeled data" মানে সেই কলামটা নেই বা ফাঁকা — আবেদনকারীর তথ্য আছে, কিন্তু ফলাফলটা নেই।
গাণিতিকভাবে, একটা sample-এর feature গুলো যদি vector হয়, তাহলে তার label লেখা হয় :
প্রতিটা labeled sample এরকম একটা জোড়া — প্রশ্ন আর তার উত্তর, একসাথে বাঁধা। একটা supervised training set আসলে এরকম জোড়ার একটা লম্বা তালিকা ছাড়া কিছু না।
Label-কে আকাশ থেকে নেমে আসা চূড়ান্ত সত্য ভেবে ফেলা খুব সহজ। কিন্তু তা না — একজন মানুষ, একটা বিজনেস প্রসেস, বা একটা অটোমেটেড নিয়ম এগুলো বানিয়েছে। একজন রেডিওলজিস্ট একটা স্ক্যানে "টিউমার" লেখেন। একজন সাপোর্ট এজেন্ট একটা টিকিটে "বিলিং সমস্যা" ট্যাগ দেন। কখনো তাড়াহুড়ো হয়, কখনো দুজন বিশেষজ্ঞ ভিন্নমত পোষণ করেন, কখনো লেবেলিংয়ের গাইডলাইনটাই অস্পষ্ট ছিল। ভুল label দিয়ে ট্রেইন করা মডেল নিষ্ঠার সাথে সেই একই ভুলটাই শিখবে। মডেল খারাপ পারফর্ম করলে label-এর মান যাচাই করা সবচেয়ে কাজের কাজগুলোর একটা — অথচ এটাই সবচেয়ে বেশি বাদ পড়ে যায়।
Feature সাধারণত এমনিতেই তৈরি হয়ে যায় — ব্যাংক আয় আর চাকরির ইতিহাস এমনিতেই রাখে, কারণ ওদের দরকার। কিন্তু label প্রায়ই ইচ্ছা করে বানাতে হয়, যোগ্য কাউকে দিয়ে, একটা একটা করে। এই অসামঞ্জস্যটাই semi-supervised আর self-supervised learning থাকার পুরো কারণ, যেটা আগের চ্যাপ্টারে দেখেছেন।
এবার এমন একটা পার্থক্য, যেটায় অনেকেই গুলিয়ে ফেলেন — কারণ দুটো শব্দ খুব কাছাকাছি বসে আছে: label আর target variable।
Target variable হলো কলামটা — যে জিনিসটা আপনি ঠিক করেছেন আপনার মডেল প্রেডিক্ট করবে। লোন টেবিলে target variable হলো "শোধ করেছে?" — ধারণা হিসেবে, প্রতিটা আবেদনকারীর জন্য যেটা প্রেডিক্ট করা হচ্ছে।
আর label হলো ওই কলামের একটামাত্র ঘর — একটা নির্দিষ্ট sample-এর জন্য জানা নির্দিষ্ট উত্তর। ৩ নম্বর আবেদনকারীর label হলো "না"।
মানে: target variable হলো আপনি dataset-কে যে প্রশ্নটা করছেন। আর label গুলো হলো সেই প্রশ্নের আলাদা আলাদা উত্তর, প্রতি সারিতে একটা। দৈনন্দিন কথায় মানুষ দুটোকে মিলিয়ে ফেলে, আর বেশিরভাগ সময় তাতে সমস্যাও হয় না। কিন্তু কোনটা কোনটা জানা থাকলে ডকুমেন্টেশন আর পেপার পড়া অনেক সহজ হয়ে যায়।
| Feature | Target variable | |
|---|---|---|
| জিনিসটা কী | ইনপুট কলাম — sample সম্পর্কে যা আপনি জানেন | আউটপুট কলাম — যা আপনি প্রেডিক্ট করতে চান |
| চিহ্ন | ||
| আরও যে নামে ডাকা হয় | Attribute, input variable, predictor, independent variable | Label column, output variable, response, dependent variable |
| প্রতি dataset-এ কয়টা | সাধারণত অনেকগুলো (প্রায়ই শত বা হাজার) | সাধারণত ঠিক একটা |
| প্রেডিকশনের সময় হাতে থাকে? | হ্যাঁ — এটাই ট্রেইন করা মডেলকে দেওয়া হয় | না — এটাই তো মডেলের কাছে চাওয়া হচ্ছে |
শেষ সারিটায় একটু থামুন, কারণ বাস্তবে ওটাই সবচেয়ে গুরুত্বপূর্ণ। ট্রেইন করা লোন মডেল যখন লাইভে যায়, একজন নতুন আবেদনকারী আসে — আপনার কাছে তার বয়স, আয়, চাকরির বছর, চলমান লোন সব আছে, কিন্তু "শোধ করেছে?" নেই, কারণ সেটা তো এখনো ঘটেইনি। এটাই তো মডেলের পুরো উদ্দেশ্য। ট্রেইনিংয়ের সময় ওই কলামটা ছিল যাতে মডেল সেখান থেকে শিখতে পারে; প্রেডিকশনের সময় ওটা থাকে না, আর মডেল সেটাই বলে দেয়।
ধরুন কেউ ট্রেইনিং ডেটায় loan_closure_reason নামে একটা কলাম যোগ করল, যার মান "পুরো শোধ" বা "খেলাপি হিসেবে বাতিল"। ট্রেইনিং accuracy লাফ দিয়ে ৯৯% হয়ে গেল, সবাই খুশি। তারপর প্রোডাকশনে মডেল পুরোপুরি ফেল করল — কারণ ওই কলামটা তো লোন শেষ হওয়ার পরে পূরণ হয়, তাই নতুন আবেদনকারীর জন্য ওটা কখনোই থাকে না। মডেল শোধ করার প্রেডিকশন শেখেনি; সে শিখেছিল এমন একটা কলাম থেকে উত্তরটা পড়ে নিতে, যেটা আসল সময়ে থাকবেই না।
এটার নাম data leakage, আর বাস্তব ML প্রজেক্টে এটা সবচেয়ে কমন গুরুতর ভুলগুলোর একটা। ধরার পরীক্ষাটা খুব সহজ, আর প্রতিটা feature-এ প্রয়োগ করার মতো: যে মুহূর্তে প্রেডিকশন করতে হবে, সেই মুহূর্তে কি এই মানটা আমার হাতে থাকবে? না হলে ওটা বাদ দিতেই হবে।
Target variable-এর ধরনটাই আবার ঠিক করে দেয় আপনার সমস্যাটা কী ধরনের — যেটা সরাসরি আগের চ্যাপ্টারের সাথে জুড়ে যায়:
| Target variable যদি হয়… | সমস্যার ধরন | উদাহরণ |
|---|---|---|
| একটা নির্দিষ্ট সেট থেকে একটা ক্যাটাগরি | Classification | শোধ করেছে? (হ্যাঁ/না), ছবির সংখ্যা (০–৯), ইমেইল (স্প্যাম/নট-স্প্যাম) |
| একটা কন্টিনিউয়াস সংখ্যা | Regression | বাড়ির দাম, আগামীকালের তাপমাত্রা, মিনিটে ডেলিভারি টাইম |
| একেবারেই অনুপস্থিত | Unsupervised learning | আগে থেকে ঠিক করা গ্রুপ ছাড়াই কাস্টমার সেগমেন্টেশন |
এতক্ষণ আপনি একটা টেবিল কল্পনা করছিলেন। এবার সেই ছবিটা ঘুরিয়ে দেখুন, কারণ একই ডেটাকে দেখার আরেকটা উপায় আছে — আর ওই উপায়টাই মেশিন লার্নিংয়ের বেশিরভাগ ভিজ্যুয়াল ইনটুইশনের দরজা খুলে দেয়।
লোন dataset থেকে শুধু দুইটা feature নিন: বয়স আর মাসিক আয়। একটা গ্রাফ আঁকুন, যেখানে x-অক্ষে বয়স আর y-অক্ষে আয়। প্রতিটা আবেদনকারী — মানে প্রতিটা sample — তার দুইটা মান অনুযায়ী একটা বিন্দু হয়ে বসে যাবে। ৪৫,০০০ আয় করা ২৮ বছর বয়সী মানুষটা বসবে (২৮, ৪৫০০০) জায়গায়।
এই দ্বিমাত্রিক তলটাই হলো feature space: feature-এর মানগুলোর সব সম্ভাব্য কম্বিনেশনের স্পেস, যেখানে প্রতিটা sample একটা বিন্দু।
এটা পড়ুন এভাবে: "প্রতিটা sample হলো -মাত্রিক বাস্তব স্পেসের একটা বিন্দু," যেখানে হলো feature-এর সংখ্যা। দুইটা feature মানে একটা তলের উপর বিন্দু ()। তিনটা feature মানে ত্রিমাত্রিক আয়তনে ভাসমান বিন্দু ()। আর ৭৮৪টা feature — আমাদের হাতে লেখা সংখ্যার ছবিটা — মানে -এর বিন্দু, যেটা কেউ কল্পনা করতে পারে না, কিন্তু গণিতটা হুবহু একইভাবে কাজ করে।
এই দ্বিতীয় দৃষ্টিভঙ্গিটার দরকার কী? কারণ এটা শেখার প্রক্রিয়াটাকে জ্যামিতিতে বদলে দেয়, আর জ্যামিতি এমন জিনিস যেটা নিয়ে আপনি চোখে দেখে চিন্তা করতে পারেন।
Scatter plot-টার দিকে তাকালে সম্ভবত খেয়াল করবেন, "শোধ করেছে" বিন্দুগুলো আর "খেলাপি" বিন্দুগুলো মোটামুটি আলাদা এলাকায় বসে আছে — বেশি বয়স আর বেশি আয়ের লোকেরা উপরে-ডানে জড়ো হয়েছে। এই দুই দল যদি স্পেসের আলাদা আলাদা অংশে থাকে, তাহলে মডেলের কাজটা হয়ে যায় একদম নির্দিষ্ট আর চোখে দেখার মতো: এমন একটা সীমানা খুঁজে বের করো যেটা এদের আলাদা করে। এটা কোনো উপমা না। একটা classifier আক্ষরিক অর্থেই এটাই হিসাব করে, আর এ কারণেই সামনের decision boundaries আর linear separability চ্যাপ্টারগুলো পুরোপুরি এই ছবিটার উপর দাঁড়িয়ে আছে।
Feature space-এর দৃষ্টিভঙ্গি "similarity" কথাটাকেও একটা নির্দিষ্ট মানে দেয়: দুইটা sample একই রকম মানে তাদের বিন্দু দুটো কাছাকাছি। এই একটামাত্র আইডিয়া অবাক করার মতো অনেক ML-এর পেছনে কাজ করে — clustering কাছাকাছি বিন্দুগুলোকে গ্রুপ করে, nearest-neighbor classifier একটা নতুন বিন্দুর label ঠিক করে তার সবচেয়ে কাছের চেনা বিন্দুগুলো দেখে, আর রেকমেন্ডেশন সিস্টেম এমন জিনিস সাজেস্ট করে যেগুলোর বিন্দু আপনার পছন্দের জিনিসগুলোর কাছাকাছি।
বাস্তবে সবাই একসাথে দুই-তিনটা feature প্লট করে ইনটুইশন তৈরি করে, ভালোমতো জেনেই যে মডেল আসলে শত শত মাত্রার এমন একটা স্পেসে কাজ করছে যেটা কল্পনাই করা যায় না। এটাই স্বাভাবিক। কৌশলটা হলো 2D-তে চিন্তা করা, আর বিশ্বাস রাখা যে গণিতটা — দূরত্ব, সীমানা, দিক — উঁচু মাত্রায়ও হুবহু একইভাবে খাটে।
Dimensionality মানে শুধু আপনার dataset-এ কতগুলো feature আছে, লেখা হয় (কখনো ) দিয়ে। লোন টেবিলে । ২৮×২৮ সাদাকালো ছবিতে । জিন এক্সপ্রেশনের একটা dataset-এ হয়তো ।
শুনতে নিছক হিসাবরক্ষণের সংখ্যা মনে হয়। কিন্তু তা না — এটা একটা dataset-এর সবচেয়ে ফলপ্রসূ বৈশিষ্ট্যগুলোর একটা, কারণ এই সংখ্যাটা বড় হলে অদ্ভুত সব জিনিস ঘটতে শুরু করে।
সবাই ভাবে: feature বেশি মানে তথ্য বেশি, মানে মডেল ভালো। একটা নির্দিষ্ট সীমা পর্যন্ত কথাটা ঠিক, তারপর ব্যাপারটা তীব্রভাবে উল্টে যায়।
ডেটা ছড়িয়ে পাতলা হয়ে যায়
মাত্রার সাথে সাথে আয়তন এক্সপোনেনশিয়ালি বাড়ে। একটা feature-কে ১০ ভাগে ভাগ করলে ঢেকে ফেলতে লাগে ~১০টা sample; ১০টা feature হলে একই ঘনত্বে ঢাকতে লাগবে ১০^১০টা। বাস্তব dataset এর ধারেকাছেও যায় না, তাই উঁচু মাত্রায় আপনার sample গুলো বিশাল, প্রায় ফাঁকা একটা স্পেসে পাতলা হয়ে ছড়িয়ে থাকে, মাঝখানে বড় বড় অচেনা ফাঁক নিয়ে।
দূরত্বের মানে হারিয়ে যায়
খুব উঁচু মাত্রায়, সবচেয়ে কাছের দুই বিন্দুর দূরত্ব আর সবচেয়ে দূরের দুই বিন্দুর দূরত্ব কাছাকাছি চলে আসতে থাকে — সবাই সবার থেকে প্রায় সমান দূরে। যেহেতু "একই রকম মানে কাছাকাছি" ধারণাটার উপরই clustering আর nearest-neighbor দাঁড়িয়ে, তাই এটা শুরু হলে ওই পদ্ধতিগুলো খারাপভাবে ভেঙে পড়ে।
Overfitting সহজ হয়ে যায়
Sample-এর তুলনায় feature যথেষ্ট বেশি হলে, মডেল সবসময়ই এমন কোনো কম্বিনেশন খুঁজে পাবে যেটা নিছক কাকতালীয়ভাবে ট্রেইনিং ডেটাকে নিখুঁতভাবে আলাদা করে ফেলে — যে noise ঘটনাচক্রে মিলে গেছে। সে শেখে না, মুখস্থ করে, আর নতুন ডেটায় ধসে পড়ে। এটাকেই overfitting নামে পরের একটা চ্যাপ্টারে পাবেন।
সবকিছু ধীর হয়ে যায়
বেশি feature মানে বেশি প্যারামিটার জমা রাখা, প্রতি প্রেডিকশনে বেশি হিসাব, আর বেশি ট্রেইনিং টাইম ও মেমোরি। কখনো কখনো সবার আগে যে বাস্তব সীমাটা কামড় দেয় সেটা নিছক খরচ।
এই সমস্যাগুলোকে একসাথে বলা হয় curse of dimensionality — একটা নাটকীয় নাম, কিন্তু ব্যাপারটা সত্যি: একটা সীমার পর feature যোগ করলে মডেল ভালো না হয়ে খারাপ হয়, যদি না সাথে অনেক বেশি ডেটাও যোগ করেন।
কমন একটা গাইডলাইন হলো feature-এর চেয়ে sample উল্লেখযোগ্যভাবে বেশি থাকা উচিত — ৫০টা feature আর ৬০টা sample মানে বিপদ ডেকে আনা, আর ৫০টা feature আর ৫০,০০০ sample মানে আরামদায়ক অবস্থা। এটাকে আইন না ভেবে একটা সন্দেহের পরীক্ষা হিসেবে নিন: আসল দরকারটা নির্ভর করে আপনার feature গুলোতে কতটা সত্যিকারের সিগন্যাল আছে আর নিচের প্যাটার্নটা কতটা জটিল তার উপর। তবে যদি -এর কাছাকাছি হয়, তাহলে যেকোনো ভালো ফলাফল দেখলেই সন্দেহ করুন।
তাহলে dimensionality বেশি হয়ে গেলে আসলে কী করবেন? দুই ধরনের উপায় আছে:
Feature selection
মূল feature গুলোর একটা অংশ রেখে বাকিগুলো বাদ দিন — যেগুলো কম তথ্য বহন করে বা একে অপরের নকল, সেগুলো ফেলে দিন। যেগুলো রাখলেন সেগুলো অপরিবর্তিত থাকে, তাই তাদের মানে বোঝাও সহজ থাকে।
Feature extraction
মূল feature গুলো মিশিয়ে ছোট একটা নতুন feature সেট বানান (PCA আর autoencoder এই কাজটাই করে)। সাধারণত শুধু বাছাই করার চেয়ে বেশি তথ্য ধরে রাখে, কিন্তু নতুন feature গুলো গাণিতিক মিশ্রণ — এদের আর সহজ ভাষায় কোনো মানে থাকে না।
দুটোই পড়ে dimensionality reduction-এর ভেতরে, যেটার সাথে আগের চ্যাপ্টারে unsupervised learning টাস্ক হিসেবে অল্প পরিচয় হয়েছিল। এখন আপনি ঠিক বুঝতে পারছেন কেন এটা দরকার: এটাই curse of dimensionality-র সরাসরি জবাব।
অনেক সম্ভাব্য মান আছে এমন একটা categorical feature-কে one-hot encode করলে কারও চোখে না পড়েই বিপুলভাবে ফুলে যেতে পারে। ৫০০টা শহর ঢাকা একটা "শহর" কলাম হয়ে যায় ৫০০টা কলাম। এরকম তিন-চারটা categorical কলামে করলে পরিপাটি ২০-feature-এর dataset চুপচাপ ২,০০০-feature-এর হয়ে যায় — আর উপরের সবগুলো সমস্যাও সাথে চলে আসে।
শব্দগুলো মাথায় গেঁথে যায় অনেক সহজে, যখন একই চারটা আইডিয়া — sample, feature, label, target variable — সত্যিই ভিন্ন ভিন্ন ধরনের ডেটায় বসিয়ে দেখা যায়। নিচে পাঁচটা উদাহরণ, ইচ্ছা করেই এমন বেছে নেওয়া যেগুলো উপর থেকে দেখতে একেবারেই আলাদা।
ক্লাসিক MNIST dataset: হাতে লেখা সংখ্যার ৭০,০০০টা ছোট সাদাকালো ছবি, প্রতিটা ২৮×২৮ পিক্সেল।
| ধারণা | এখানে সেটা কী |
|---|---|
| Sample | একটা সংখ্যার একটা ছবি |
| Features | ৭৮৪টা সংখ্যা — ২৮×২৮ প্রতিটা পিক্সেলের উজ্জ্বলতা (০–২৫৫), একটা সারিতে সমতল করে বসানো |
| Label | আসলে যে সংখ্যাটা লেখা: ০, ১, ২, … ৯ |
| Target variable | "এটা কোন সংখ্যা?" |
| Dimensionality | |
| Sample size | |
| সমস্যার ধরন | Classification (১০টা ক্লাস) |
খেয়াল করার মতো জিনিস: ওই ৭৮৪টা feature কেউ হাতে ডিজাইন করেনি। "২১৯ নম্বর পিক্সেলের উজ্জ্বলতা" মানুষের কাছে অর্থহীন, কিন্তু কাঁচা পিক্সেল গ্রিডটাই মডেলের কাজ চালানোর জন্য যথেষ্ট — নেটওয়ার্ক নিজেই এই কাঁচা feature থেকে ভেতরে ভেতরে কাজের feature বানিয়ে নেয়।
| ধারণা | এখানে সেটা কী |
|---|---|
| Sample | বিক্রি হয়ে যাওয়া একটা বাড়ি |
| Features | আয়তন (বর্গফুট), বেডরুম সংখ্যা, বাথরুম সংখ্যা, বিল্ডিংয়ের বয়স, তলা, মেইন রোড থেকে দূরত্ব, এলাকার নাম |
| Label | আসল বিক্রয়মূল্য, যেমন ৮৫,০০,০০০ টাকা |
| Target variable | "এই প্রপার্টিটা কত টাকায় বিক্রি হবে?" |
| Dimensionality | (এনকোডিংয়ের আগে; "এলাকার নাম" one-hot হলে বেড়ে যায়) |
| সমস্যার ধরন | Regression (কন্টিনিউয়াস আউটপুট) |
এখানে feature-এর ধরনগুলো মেশানো: আয়তন continuous, বেডরুম count, এলাকার নাম nominal categorical। বাস্তব পাইপলাইনে মডেল ডেটা দেখার আগেই সংখ্যাগুলো scale করতে হবে আর categorical-টা encode করতে হবে।
| ধারণা | এখানে সেটা কী |
|---|---|
| Sample | একটা ইমেইল |
| Features | টেক্সট থেকে বের করা সংখ্যা — শব্দের গণনা বা ফ্রিকোয়েন্সি, সন্দেহজনক বাক্যাংশের উপস্থিতি, লিংকের সংখ্যা, প্রেরকের রেপুটেশন, ALL-CAPS-এর অনুপাত |
| Label | স্প্যাম নাকি নট-স্প্যাম |
| Target variable | "এই ইমেইলটা কি স্প্যাম?" |
| Dimensionality | প্রায়ই কয়েক হাজার (ভোকাবুলারির প্রতি শব্দে একটা feature) |
| সমস্যার ধরন | Binary classification |
টেক্সটেই "সবকিছুকে টেবিলে বদলাও" ধাপটা সবচেয়ে স্পষ্ট দেখা যায়। ইমেইল নিজে সংখ্যা না, তাই শেখা শুরুর আগেই একটা রূপান্তর ধাপ (bag-of-words, TF-IDF, বা শেখা embedding) সেটাকে একটা সারিতে বদলে দেয়। খুব বেশি dimensionality-রও এটা স্বাভাবিক আবাসস্থল — আর curse of dimensionality-র স্বাদ পাওয়ার স্বাভাবিক জায়গা।
| ধারণা | এখানে সেটা কী |
|---|---|
| Sample | একজন রোগীর একটা ভিজিট |
| Features | বয়স, রক্তচাপ, ব্লাড সুগার, BMI, কোলেস্টেরল, ধূমপানের অভ্যাস, পারিবারিক ইতিহাস |
| Label | ৫ বছরের মধ্যে ডায়াবেটিস হয়েছে: হ্যাঁ / না |
| Target variable | "এই রোগীর কি ডায়াবেটিস হবে?" |
| সমস্যার ধরন | Binary classification |
এই উদাহরণটার সাথে একটা সতর্কবার্তা আছে যেটা গেঁথে নেওয়া দরকার। ধরুন কেউ currently_taking_diabetes_medication কলামটা feature হিসেবে ঢুকিয়ে দিল। Accuracy দেখতে অসাধারণ লাগবে — আর মডেলটা হবে সম্পূর্ণ অকেজো, কারণ ওই তথ্যটা তো ডায়াগনোসিসের পরেই জানা যায়। একদম বইয়ের উদাহরণের মতো data leakage, আর ঠিক এমন জায়গায় যেখানে ভুলের দাম সবচেয়ে বেশি।
| ধারণা | এখানে সেটা কী |
|---|---|
| Sample | একজন কাস্টমার |
| Features | মোট খরচ, কেনাকাটার ফ্রিকোয়েন্সি, গড় বাস্কেট সাইজ, শেষ কেনাকাটার পর কত দিন, কোন প্রোডাক্ট ক্যাটাগরি কিনেছে |
| Label | নেই |
| Target variable | নেই |
| সমস্যার ধরন | Unsupervised (clustering) |
শেষ উদাহরণটা আছে একটা কথা বোঝানোর জন্য: sample, feature, feature space, dimensionality — সবগুলো এখানেও পুরোপুরি খাটে। শুধু label কলাম আর target variable-টাই নেই। ওই অনুপস্থিতিটাই একে unsupervised বানায় — আর এটা দেখায় যে এই চ্যাপ্টারের বেশিরভাগ শব্দই আসলে ডেটার গঠন নিয়ে, কেউ উত্তর দিয়ে রেখেছে কিনা তার উপর নির্ভর করে না।