MLOps/MLOps-এর ভিত্তি/Lesson 02
Experiment tracking
প্রতিটা training run-এর parameter আর metric লিখে রাখা, যাতে পরে তুলনা করা যায় আর সবচেয়ে ভালোটা খুঁজে পাওয়া যায়। JSON Lines দিয়ে নিজের ছোট tracker বানাও, আর দেখো MLflow একই কাজ কীভাবে করে।
- সময়
- 24 মিনিট
- Exercise
- 1
- Challenge
- 1
- Quiz
- 3 প্রশ্ন
সহজ ভাষায়
তুমি একটা model নিয়ে পরীক্ষা করছ। max_depth=3 দিলে ৭৯%, তারপর নতুন feature যোগ করলে ৮১%, learning rate বদলালে... এক সপ্তাহ পরে আর মনে থাকে না কোনটা কী ছিল।
Experiment tracking মানে প্রতিটা training run-এর একটা খাতা:
run params metrics
1 max_depth=2 train 0.80 test 0.78
2 max_depth=4 train 0.85 test 0.80
3 max_depth=10 train 1.00 test 0.74 ← overfit
কেন দরকার?
- তুলনা: কোন setting আসলে ভালো?
- পুনরুৎপাদন: "৮১%-এর model-টা আবার বানাও।" কোন setting দিয়ে বানানো হয়েছিল?
- দলের কাজ: অন্যরা দেখতে পারে কী কী চেষ্টা হয়েছে, তাই একই কাজ দুবার হয় না
- Audit: Production-এর model কোথা থেকে এসেছে, তার প্রমাণ
JSON Lines: সবচেয়ে সহজ tracker
প্রতি লাইনে একটা JSON object। নতুন run মানে শুধু একটা লাইন যোগ:
একটা আসল sweep
একটা parameter-এর অনেকগুলো মান চেষ্টা করাকে বলে sweep। Built-in dataset দিয়ে:
Depth বাড়লে train accuracy বাড়তে বাড়তে প্রায় ১০০%-এ পৌঁছায়। কিন্তু test accuracy সবচেয়ে বেশি হয় অগভীর tree-তে (এই split-এ depth 2), তারপর আর বাড়ে না, বরং কমে। Tracker ছাড়া এই pattern দেখতে প্রতিবার নতুন করে চালাতে হতো।
Run-গুলো তুলনা করা
(প্রতিটা run আলাদা পরিবেশে চলে, তাই এখানে file-এর লাইনগুলো সরাসরি লিখে দিলাম।) pd.json_normalize nested dict-কে column বানায় (params.max_depth, metrics.test_acc)। তারপর pandas-এর সব কৌশল ব্যবহার করা যায়।
Exercise
Exercise
একটা run log করো
log_run(path, params, metrics) লেখো। এটা একটা JSON Lines file-এ (প্রতি লাইনে একটা JSON object) নতুন লাইন যোগ করবে:
{"run": n, "params": {...}, "metrics": {...}}
n হলো run নম্বর: file-এ আগে যতগুলো লাইন ছিল, তার পরের সংখ্যা। প্রথম run 1। File না থাকলে নিজেই তৈরি হবে। Function n return করবে।
Quiz
Challenge
Challenge
Sweep চালাও, সেরাটা বের করো
দুটো কাজ:
best_run(path, metric, mode="max")— JSON Lines file পড়েmetrics[metric]অনুযায়ী সেরা run-এর dict return করবে।mode="min"হলে সবচেয়ে ছোটটা (যেমন loss)। সমান হলে আগের run।
students_clean.csvদিয়ে একটা sweep চালাও। X =study_hours,attendance; y =passed।train_test_split(test_size=0.25, random_state=42)দিয়ে ভাগ করো।max_depth1 থেকে 6 পর্যন্ত প্রতিটার জন্যDecisionTreeClassifier(max_depth=d, random_state=0)train করো। প্রতিটা runlog_run-এর মতো করে"sweep.jsonl"-এ লেখো: params{"max_depth": d}, metrics{"train_acc", "test_acc"}। তারপরbest = best_run("sweep.jsonl", "test_acc")।
বাস্তবে কোথায় ব্যবহার হয়?
MLflow একই কাজ করে, সাথে একটা web UI দেয় যেখানে run তুলনা আর graph দেখা যায়:
import mlflow
with mlflow.start_run():
mlflow.log_param("max_depth", 4)
model = DecisionTreeClassifier(max_depth=4).fit(X_train, y_train)
mlflow.log_metric("test_acc", model.score(X_test, y_test))
mlflow.sklearn.log_model(model, "model")
(তোমার computer-এ: pip install mlflow, তারপর mlflow ui। Browser-এ সব run দেখা যাবে।) এখানে log_param আর log_metric হলো তোমার log_run-এরই ভালো সংস্করণ। Weights & Biases-ও একই ধারণায় কাজ করে, শুধু cloud-এ।
Interview প্রশ্ন
- Beginner: Experiment tracking কেন দরকার?
- Intermediate: একটা run-এর জন্য কী কী metadata রাখবে, যাতে সেটা পুরোপুরি পুনরায় তৈরি করা যায়?
- Advanced: অনেকগুলো sweep-এ test set দেখে model বাছাই করলে কী সমস্যা হয়? এটা কীভাবে এড়াবে?
এরপর কী?
সেরা run পাওয়া গেল। এখন model-টা save করে রাখতে হবে, version নম্বর দিতে হবে, আর পরে ঠিক সেই model-টাই load করতে হবে। পরের lesson: Model versioning।