Machine Learning cho người mới bắt đầu: Từ lý thuyết đến thực hành với scikit-learn

Artificial Intelligence tutorial - IT technology blog
Artificial Intelligence tutorial - IT technology blog

Bối cảnh — Tại sao DevOps cũng cần biết Machine Learning

Nói thật là trước đây mình cũng không mặn mà lắm với ML. Cứ nghĩ đó là việc của data scientist, còn mình chỉ lo deploy và monitor là đủ. Nhưng rồi có một sprint cần tích hợp tính năng dự đoán churn khách hàng vào pipeline, và mình là người phải wrap cái model đó thành REST API rồi đẩy lên production. Lúc đó mới thấm: không hiểu ML hoạt động ra sao, mình không giải thích được tại sao model cho kết quả kỳ lạ, không biết cần monitor cái gì, và không biết khi nào nên retrain.

Machine Learning thực ra không huyền bí như nhiều người nghĩ. Ý tưởng cốt lõi rất đơn giản: cho máy tính học từ dữ liệu để đưa ra dự đoán. Thay vì viết rule cứng kiểu if email chứa "giảm giá" then spam, ta dùng dữ liệu lịch sử để máy tự tìm pattern.

Ba loại ML phổ biến nhất:

  • Supervised learning: Học từ data có nhãn (label). Ví dụ: dự đoán giá nhà, phân loại email spam.
  • Unsupervised learning: Tự tìm pattern trong data không có nhãn. Ví dụ: clustering nhóm khách hàng theo hành vi mua sắm.
  • Reinforcement learning: Agent học qua thử-sai, nhận reward/penalty. Ứng dụng trong game AI, robot điều hướng tự động.

Nếu bạn đang bắt đầu, hãy focus vào supervised learning trước — kết quả đo được rõ ràng, tooling hoàn thiện, và tài liệu nhiều hơn hẳn so với hai loại kia.

Cài đặt môi trường ML

Yêu cầu hệ thống

Python 3.9+ là đủ để bắt đầu. Dùng virtualenv ngay từ đầu — nghe nhỏ nhặt nhưng sẽ cứu bạn khỏi đống conflict package giữa các project về sau.

# Tạo virtualenv
python3 -m venv ml-env
source ml-env/bin/activate  # Linux/macOS
# ml-env\Scripts\activate   # Windows

# Cài các thư viện cần thiết
pip install scikit-learn pandas numpy matplotlib joblib

Kiểm tra cài đặt

import sklearn
import pandas as pd
import numpy as np

print(f"scikit-learn: {sklearn.__version__}")
print(f"pandas: {pd.__version__}")
print(f"numpy: {np.__version__}")

Chạy không lỗi là ổn. Mình đang dùng scikit-learn 1.4.x trên production — API ổn định, hiếm có breaking change giữa các minor version.

Xây dựng model đầu tiên — Classification cơ bản

Mình dùng dataset Iris — 150 mẫu hoa với 4 features (chiều dài/rộng cánh hoa và đài hoa), phân vào 3 loài. Không thực tế lắm nhưng đủ để hiểu toàn bộ flow mà không bị lạc vào data cleaning.

Load và khám phá data

from sklearn.datasets import load_iris
import pandas as pd

# Load dataset
iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df['target'] = iris.target
df['species'] = df['target'].map({0: 'setosa', 1: 'versicolor', 2: 'virginica'})

print(df.head())
print(df.describe())
print(df['species'].value_counts())

Output hiện ra đúng 50 samples mỗi loài — dataset cân bằng hoàn hảo, không cần xử lý gì thêm. Trong thực tế thì đừng mơ được như vậy, nhưng đó là câu chuyện của feature engineering.

Chia train/test split

Bước này cực kỳ quan trọng và người mới hay bỏ qua nhất. Nếu train và evaluate trên cùng một data, model sẽ “nhớ” data đó và báo kết quả tốt giả tạo — gọi là overfitting. Sau đó deploy ra production mới té ngửa.

from sklearn.model_selection import train_test_split

X = iris.data   # Features (4 cột số)
y = iris.target # Labels (0, 1, 2)

# 80% train, 20% test — random_state để kết quả reproducible
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)

print(f"Train size: {len(X_train)}")  # 120
print(f"Test size: {len(X_test)}")    # 30

Tham số stratify=y đảm bảo tỷ lệ class trong train và test set giống nhau. Quan trọng đặc biệt khi data imbalanced — ví dụ dataset có 90% class 0, không stratify thì test set có thể toàn class 0 và accuracy báo 90% trong khi model chưa học được gì.

Train model với Random Forest

Mình chọn Random Forest không phải vì tên nghe hay, mà vì nó robust, ít cần tuning, và thường baseline đã đạt trên 90% mà không cần tinh chỉnh gì nhiều. Lý tưởng để bắt đầu.

from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, classification_report

# Khởi tạo model
model = RandomForestClassifier(n_estimators=100, random_state=42)

# Train — chỉ cần 1 dòng
model.fit(X_train, y_train)

# Predict trên test set
y_pred = model.predict(X_test)

# Đánh giá
print(f"Accuracy: {accuracy_score(y_test, y_pred):.2%}")
print("\nClassification Report:")
print(classification_report(y_test, y_pred, target_names=iris.target_names))

Kết quả thường đạt ~97% accuracy trên Iris. Nhưng đừng nhìn mỗi accuracy — classification_report mới quan trọng hơn vì nó breakdown precision/recall/f1 từng class riêng. Trong thực tế, data imbalanced gần như là mặc định, và accuracy một mình thì dễ đánh lừa lắm.

Lưu model và Monitoring trên production

Serialize model để dùng lại

Train xong rồi thì cần serialize — không thể mỗi lần deploy lại ngồi train từ đầu. Với scikit-learn, joblib nhanh hơn pickle cho các object có numpy array lớn bên trong.

import joblib

# Lưu model
joblib.dump(model, 'iris_model.pkl')
print("Model saved!")

# Load lại trong production code
loaded_model = joblib.load('iris_model.pkl')

# Test predict với data mới
sample = [[5.1, 3.5, 1.4, 0.2]]  # Đây là Setosa
prediction = loaded_model.predict(sample)
probability = loaded_model.predict_proba(sample)

print(f"Predicted: {iris.target_names[prediction[0]]}")
print(f"Confidence: {probability.max():.2%}")

Log prediction để monitor

Đây là bài học đắt nhất mình từng học. Team mình deploy model xong rồi… quên luôn. Sau 3 tháng accuracy tụt từ 94% xuống 71% vì data distribution thay đổi theo mùa — hiện tượng gọi là data drift. Mất cả tuần điều tra mới tìm ra nguyên nhân. Từ đó mình log mọi prediction:

import json
from datetime import datetime

def log_prediction(input_data, prediction, confidence, model_version="1.0"):
    """Log prediction để monitor và phát hiện drift sau này"""
    log_entry = {
        "timestamp": datetime.utcnow().isoformat(),
        "model_version": model_version,
        "input": input_data,
        "prediction": int(prediction),
        "confidence": float(confidence),
    }
    # Append vào JSONL file — dễ parse sau này
    with open("prediction_logs.jsonl", "a") as f:
        f.write(json.dumps(log_entry) + "\n")
    return log_entry

# Usage
log_prediction(
    input_data=[5.1, 3.5, 1.4, 0.2],
    prediction=0,
    confidence=0.98
)

Phát hiện data drift đơn giản

Khi có đủ prediction logs, mình so sánh distribution của input hiện tại với lúc train để bắt drift sớm:

import numpy as np

def check_feature_drift(reference_data, new_data, threshold=0.1):
    """So sánh mean của từng feature, phát hiện drift"""
    ref_mean = np.mean(reference_data, axis=0)
    new_mean = np.mean(new_data, axis=0)
    
    # Normalize bằng std của reference data
    drift = np.abs(ref_mean - new_mean) / (np.std(reference_data, axis=0) + 1e-8)
    
    feature_names = iris.feature_names
    for i, d in enumerate(drift):
        status = "WARNING" if d > threshold else "OK"
        print(f"[{status}] {feature_names[i]}: drift={d:.3f}")
    
    return drift

# Chạy định kỳ mỗi tuần
check_feature_drift(X_train, X_test)

Function này chạy cron mỗi Chủ Nhật trên production của mình. Drift vượt ngưỡng 0.2 là tự động tạo ticket retrain — khỏi cần canh thủ công.

Bước tiếp theo sau bài này

Nắm được flow rồi, đây là lộ trình tiếp theo mình recommend:

  1. Thực hành dataset thực tế: Kaggle có Titanic, House Prices — phù hợp để luyện feature engineering với data messy hơn Iris nhiều.
  2. Cross-validation: Dùng cross_val_score thay vì train/test split một lần — đánh giá model ít bị ảnh hưởng bởi may rủi của cách chia data.
  3. Feature engineering: Xử lý missing values, encoding categorical, scaling — chiếm 80% công sức trong dự án thực tế, phần model training chỉ là 20% còn lại.
  4. Hyperparameter tuning: GridSearchCV hoặc RandomizedSearchCV để tối ưu tham số — RandomizedSearchCV nhanh hơn nhiều khi search space lớn.
  5. MLflow: Version control cho model và experiment tracking — bắt buộc khi làm theo team hoặc chạy nhiều thử nghiệm song song.

ML không đòi bạn phải giỏi toán hay data science thuần túy. Quan trọng là biết bài toán mình đang giải là gì, chọn đúng metric, và nhớ rằng model deploy xong không phải là hết việc. Phần còn lại? Mở terminal lên và bắt đầu thôi.

Share: