অধ্যায় 6 · প্রজেক্ট ও পরের ধাপ
Python থেকে মেশিন লার্নিং: আপনার প্রথম মডেল
- পৃষ্ঠা 21 / 22
- 7 মিনিট পড়া
আগের পাতায় রিভিউ দুইভাবে শ্রেণিবিভাগ করেছেন: নিজের লেখা কিওয়ার্ড নিয়ম দিয়ে, আর একটা ল্যাঙ্গুয়েজ মডেল দিয়ে। মেশিন লার্নিং হলো তৃতীয় উপায়, আর আধুনিক AI-এর পেছনের মূল ধারণা: নিয়ম নিজে না লিখে কম্পিউটারকে অনেক উত্তরসহ উদাহরণ দেখান, আর একটা অ্যালগরিদম আপনার হয়ে নিয়ম খুঁজে নেয়। বড় ল্যাঙ্গুয়েজ মডেলও এই একই ধারণা, বিশাল মাপে। এই পাতায় NumPy আর pandas-এর শেখা সবকিছু কাজে লাগিয়ে ক্লাসিক মেশিন লার্নিংয়ের মানক Python লাইব্রেরি scikit-learn দিয়ে আপনার প্রথম মডেলগুলো ট্রেন করবেন।
যে শব্দগুলো লাগবে
| শব্দ | মানে | নিচের উদাহরণে |
|---|---|---|
ফিচার (X) | মডেল যে ইনপুটগুলো দেখে | একটা ফুলের চারটা মাপ |
লেবেল / টার্গেট (y) | যে উত্তর অনুমান করতে শিখতে হবে | তিনটা প্রজাতির কোনটা |
ট্রেনিং (fit) | উদাহরণ থেকে অ্যালগরিদমকে প্যাটার্ন খুঁজতে দেওয়া | উত্তরসহ ১২০টা ফুল |
প্রেডিকশন (predict) | শেখা জিনিস নতুন ইনপুটে ব্যবহার | কখনো না দেখা ৩০টা ফুল |
| ক্লাসিফিকেশন / রিগ্রেশন | একটা শ্রেণি / একটা সংখ্যা অনুমান | প্রজাতি একটা শ্রেণি |
উদাহরণের সাথে উত্তর থাকলে সেটা সুপারভাইজড লার্নিং — সবচেয়ে প্রচলিত ধরন। উত্তর ছাড়া ডেটার ভেতরে দল খোঁজা হলো আনসুপারভাইজড লার্নিং।
ধাপ ১: ডেটা দেখা
python -m pip install scikit-learn দিয়ে ইনস্টল করুন (পুরো পাতার জন্য আগের পাতার একটা নোটবুক ভালো জায়গা)। scikit-learn-এর সাথে অনুশীলনের ছোট ডেটাসেট আসে। ক্লাসিক ডেটাসেটটায় ১৫০টা আইরিস ফুলের মাপ:
from sklearn.datasets import load_iris
iris = load_iris(as_frame=True)
df = iris.frame # একটা pandas DataFrame
print(df.shape)
print(df.head(3).to_string())
print(iris.target_names.tolist())
print(df["target"].value_counts().sort_index().tolist())(150, 5)
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) target
0 5.1 3.5 1.4 0.2 0
1 4.9 3.0 1.4 0.2 0
2 4.7 3.2 1.3 0.2 0
['setosa', 'versicolor', 'virginica']
[50, 50, 50]১৫০টা সারি, চারটা মাপের কলাম আর একটা target কলাম: তিন প্রজাতির জন্য 0, 1 বা 2, প্রতিটা ৫০টা করে। শ্রেণিগুলো এভাবে সমান হলে accuracy পড়া সহজ।
ধাপ ২: ভাগ, ট্রেন, অনুমান, মাপা
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
iris = load_iris(as_frame=True)
df = iris.frame
X = df.drop(columns="target") # ফিচার: চারটা মাপ
y = df["target"] # লেবেল: 0, 1 বা 2
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
print(X_train.shape, X_test.shape)
model = DecisionTreeClassifier(max_depth=3, random_state=42)
model.fit(X_train, y_train) # ট্রেনিং সেট থেকে শেখা
predictions = model.predict(X_test) # যে ফুল কখনো দেখেনি, তার অনুমান
print(predictions[:10])
print(y_test.to_numpy()[:10])
print(f"accuracy: {accuracy_score(y_test, predictions):.2f}")
new_flower = pd.DataFrame([[5.0, 3.4, 1.5, 0.2]], columns=X.columns)
print(iris.target_names[model.predict(new_flower)[0]])(120, 4) (30, 4)
[0 2 1 1 0 1 0 0 2 1]
[0 2 1 1 0 1 0 0 2 1]
accuracy: 0.97
setosatrain_test_splitট্রেনিংয়ের আগে ২০% সারি — ৩০টা ফুল — লুকিয়ে রাখে।random_state=42এলোমেলো করাটা প্রতিবার একই রাখে (পাতা ৯);stratify=yদুই অংশেই তিন প্রজাতির অনুপাত একই রাখে।fitমডেলকে শুধু ১২০টা ট্রেনিং সারিতে ট্রেন করে। একটা ডিসিশন ট্রি হ্যাঁ/না প্রশ্নের একটা সারি শেখে, যেমন "পাপড়ি কি ২.৫ সেমির চেয়ে ছোট?"।predictলুকানো ৩০টা ফুলের উত্তর দেয়। প্রথম দশটা অনুমান আসল লেবেলের সাথে হুবহু মেলে।- Accuracy হলো সঠিক উত্তরের অনুপাত: 0.97 মানে ৩০টার মধ্যে ২৯টা।
scikit-learn-এর প্রতিটা মডেল একইভাবে চলে: বানান, fit(X_train, y_train), তারপর predict(X) বা score(X, y)। এই ধরনটা একবার শিখলে শত শত অ্যালগরিদম ব্যবহার করতে পারবেন।
ধাপ ৩: টেস্ট সেট কেন জরুরি — ওভারফিটিং
ডেটা লুকানোর দরকারই বা কেন? কারণ একটা মডেল দেখা ডেটায় নিখুঁত হয়েও নতুন ডেটায় ব্যর্থ হতে পারে। দেখুন ট্রির গভীরতা — কতগুলো প্রশ্ন করতে পারবে — দুটো স্কোর কীভাবে বদলায়:
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
X, y = load_iris(return_X_y=True, as_frame=True)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
for depth in [1, 3, None]:
model = DecisionTreeClassifier(max_depth=depth, random_state=42).fit(X_train, y_train)
print(f"max_depth={depth}: train {model.score(X_train, y_train):.2f}, test {model.score(X_test, y_test):.2f}")max_depth=1: train 0.67, test 0.67
max_depth=3: train 0.98, test 0.97
max_depth=None: train 1.00, test 0.93- গভীরতা ১ খুবই সরল: দুটোতেই 0.67। এটা আন্ডারফিটিং।
- গভীরতার সীমা নেই এমন মডেল ট্রেনিং ডেটায় নিখুঁত 1.00 পায় — প্রতিটা ফুল মুখস্থ করে ফেলেছে — তবু টেস্ট সেটে গভীরতা ৩-এর চেয়ে খারাপ করে। এটা ওভারফিটিং, পাতা ১৫-এর ট্রেনিং-কার্ভ চার্টে যা দেখেছেন সেটাই।
- এখানে গভীরতা ৩ সবচেয়ে ভালো: নতুন ডেটাতেও পুরোনোর প্রায় সমান ভালো।
এখান থেকে নিয়ম: যে ডেটায় মডেল ট্রেন হয়েছে, সেই ডেটায় কখনো মডেল বিচার করবেন না। আসল ব্যবহারে কেমন করবে, তা বলে শুধু টেস্ট স্কোর।
ধাপ ৪: পাইপলাইন দিয়ে মডেল তুলনা
অনেক অ্যালগরিদম ভালো চলে যখন প্রতিটা ফিচার একই মাপকাঠিতে থাকে। পাইপলাইন একটা প্রিপ্রসেসিং ধাপ আর একটা মডেলকে জুড়ে একটা অবজেক্ট বানায়, যার তবু fit আর predict আছে, তাই স্কেলিং শেখা হয় শুধু ট্রেনিং ডেটা থেকে:
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
X, y = load_iris(return_X_y=True, as_frame=True)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
models = {
"decision tree": DecisionTreeClassifier(max_depth=3, random_state=42),
"logistic regression": make_pipeline(StandardScaler(), LogisticRegression()),
"nearest neighbours": make_pipeline(StandardScaler(), KNeighborsClassifier(n_neighbors=5)),
}
for name, model in models.items():
model.fit(X_train, y_train)
print(f"{name:20} {model.score(X_test, y_test):.2f}")decision tree 0.97
logistic regression 0.93
nearest neighbours 0.93৩০টা টেস্ট ফুলে একটা ভুল মানে 0.03-এর পার্থক্য, তাই এই তিনটা আসলে প্রায় সমান ভালো। এত ছোট ডেটাসেটে ছোট ফারাক থেকে বেশি কিছু ধরে নেবেন না — হাতেগোনা কয়েকটা উদাহরণে প্রম্পট বা LLM তুলনা করার সময়ও ঠিক একই শিক্ষা।
ধাপ ৫: প্রথম টেক্সট ক্লাসিফায়ার
মডেলের দরকার সংখ্যা, তাই আগে টেক্সটকে সংখ্যায় বদলাতে হয়। TfidfVectorizer শব্দ গুনে সেটা করে (আর যে শব্দ সব জায়গায় থাকে তার গুরুত্ব কমিয়ে দেয়)। আগের পাতার রিভিউ সমস্যায় এটা:
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import make_pipeline
reviews = [
"great sound and battery", "love it, works perfectly", "excellent quality, fast delivery",
"very happy with this keyboard", "amazing value for money", "good product, would buy again",
"broke after two days", "terrible support, never again", "stopped charging, very poor",
"arrived late and damaged", "waste of money", "bad quality, keys stopped working",
]
labels = ["positive"] * 6 + ["negative"] * 6
model = make_pipeline(TfidfVectorizer(), LogisticRegression())
model.fit(reviews, labels)
new_reviews = ["the battery is great", "poor quality, it broke", "fast delivery, happy"]
for text, label in zip(new_reviews, model.predict(new_reviews)):
print(f"{label:9} <- {text}")positive <- the battery is great
negative <- poor quality, it broke
positive <- fast delivery, happyআসল ব্যবহারের জন্য বারোটা উদাহরণ একেবারেই যথেষ্ট নয় — মডেল শুধু দেখা শব্দগুলো চেনে — কিন্তু প্রোডাকশনের টেক্সট ক্লাসিফায়ার দেখতে ঠিক এরকমই। ল্যাঙ্গুয়েজ মডেলের এমবেডিং (পাতা ১৩) টেক্সটকে সংখ্যায় বদলানোর অনেক সমৃদ্ধ উপায়, আর সেগুলো এই একই scikit-learn মডেলে দেওয়া যায়।
মেশিন লার্নিংয়ের কাজের ধারা
ডেটা → পরিষ্কার ও খোঁজাখুঁজি → ফিচার (X) আর লেবেল (y) → ট্রেন/টেস্ট ভাগ
→ ট্রেন অংশে fit → টেস্ট অংশে মূল্যায়ন → উন্নতি → নতুন ডেটায় ব্যবহারপ্রথম দিন থেকেই যে তিনটা ভুল এড়াবেন:
- ট্রেনিং ডেটাতেই টেস্ট। সবসময় দারুণ দেখায়, কিছুই বলে না।
- লিকেজ: টেস্ট সেট বা উত্তরের তথ্য ফিচারে চুপিসারে ঢুকে পড়া — যেমন ভাগ করার আগে পুরো ডেটাসেটের পরিসংখ্যান দিয়ে স্কেল করা। সাধারণ ক্ষেত্রগুলো পাইপলাইন ঠেকায়।
- অসম ডেটায় accuracy-তে ভরসা। ৯৫% ইমেইল স্প্যাম না হলে, সবসময় "স্প্যাম না" বলা মডেল 0.95 পায় আর পুরোপুরি অকেজো। প্রতিটা শ্রেণি আলাদা করে দেখুন।
এরপর কোথায়
এই মডেলগুলো কেন কাজ করে — ভেক্টর, দূরত্ব, সম্ভাবনা, গড় আর বিস্তার — তা বুঝতে Level 0-এর পরের বিষয় গণিত ও পরিসংখ্যানের মৌলিক বিষয়। Level 0-এর পরে ML ও ডেটা পথ এই মডেলগুলোর গভীরে যায়, আর AI ইঞ্জিনিয়ার পথ এগুলো LLM-এর পাশাপাশি ব্যবহার করে।
নিজে চেষ্টা করুন
test_sizeবদলে 0.3 আরrandom_stateবদলে 7 করুন। স্কোর বদলায় কি? এতে কেন মনে হয় যে একটা ভাগে বেশি ভরসা করা ঠিক না?sklearn.datasetsথেকেload_wineলোড করে ধাপ ১ থেকে ৪ আবার করুন।- টেক্সট ক্লাসিফায়ারে নিজের দশটা রিভিউ যোগ করুন (ইংরেজি বা বাংলায়) আর পাঁচটা নতুন রিভিউতে পরখ করুন।