ML 3 — Hồi quy tuyến tính & logistic
ML 3 — Hồi quy tuyến tính & logistic
Sau khi đã làm sạch dữ liệu và tạo đặc trưng ở bài Feature engineering, giờ là lúc gặp hai mô hình nền tảng nhất của machine learning: hồi quy tuyến tính (linear regression) để dự đoán một con số, và hồi quy logistic (logistic regression) để phân loại và ước lượng xác suất.
Đừng để chữ "cơ bản" đánh lừa. Trong rất nhiều bài toán thực tế — đặc biệt là những lĩnh vực cần giải thích được như tín dụng, bảo hiểm, y tế — hai mô hình này không phải là "đồ chơi khởi động" mà là lựa chọn cuối cùng đưa vào production. Logistic regression chính là xương sống của phần lớn scorecard tín dụng (xem Credit scorecard) đang chạy tại các ngân hàng ngày nay. Lý do: chúng vừa đủ mạnh, cực nhanh, và quan trọng nhất là bạn có thể giải thích cho hội đồng rủi ro vì sao model quyết định như vậy.
Đây là danh mục AI. Các đoạn code Python trong bài là minh hoạ để bạn nắm hình dạng API scikit-learn, không phải sandbox chạy trực tiếp.
1. Bức tranh chung: hai anh em cùng một gốc
Cả hai mô hình đều bắt đầu từ cùng một ý tưởng: kết hợp tuyến tính các đặc trưng đầu vào.
$$ z = w_1 x_1 + w_2 x_2 + \dots + w_n x_n + b $$
Trong đó x là các đặc trưng (features), w là trọng số (weights/coefficients) mà model học được, và b là hệ số chặn (intercept/bias). Sự khác biệt duy nhất nằm ở cái gì xảy ra sau khi tính z:
- Linear regression: dùng thẳng
zlàm kết quả → dự đoán một số thực (giá nhà, doanh thu, dư nợ). - Logistic regression: đẩy
zqua hàm sigmoid → ép về khoảng (0, 1) → diễn giải thành xác suất của lớp dương (khách vỡ nợ hay không).
Vì phần "học" chỉ là tìm bộ w, b tốt nhất, nên hai model chia sẻ chung cả cách huấn luyện (tối thiểu hoá một hàm mất mát bằng gradient descent) lẫn cách chống overfitting (regularization). Hiểu một cái là hiểu gần hết cái kia.
2. Linear regression — dự đoán một con số
2.1. Mô hình và hàm mất mát MSE
Với linear regression, dự đoán là ŷ = w·x + b. Ta cần một thước đo "sai bao nhiêu". Thước đo kinh điển là MSE (Mean Squared Error) — trung bình bình phương sai số:
$$ \text{MSE} = \frac{1}{m}\sum_{i=1}^{m}(\hat{y}_i - y_i)^2 $$
Bình phương có hai tác dụng: (1) sai số âm và dương không triệt tiêu nhau, (2) phạt nặng những sai số lớn (một điểm lệch 10 bị phạt gấp 100 lần điểm lệch 1). Đây cũng là điểm yếu — MSE rất nhạy với outlier, nên bước làm sạch ở bài trước rất quan trọng.
2.2. Nghiệm đóng (OLS) vs Gradient Descent
Có hai cách tìm w, b tối ưu:
-
Nghiệm đóng — OLS (Ordinary Least Squares): linear regression đơn giản có công thức toán học giải trực tiếp
w = (XᵀX)⁻¹Xᵀy. Đây chính là cáiLinearRegressioncủa scikit-learn dùng mặc định — không cần lặp, cho kết quả chính xác trong một bước. Hạn chế: phép nghịch đảo ma trận tốn kém khi số đặc trưng rất lớn, và không ổn định khi các đặc trưng tương quan mạnh (collinearity). -
Gradient descent: đi từng bước nhỏ xuống dốc hàm mất mát (mục 4). Chậm hơn cho bài toán nhỏ nhưng mở rộng tốt cho dữ liệu khổng lồ và là cách duy nhất khả thi cho các model phức tạp hơn.
2.3. Các giả định (và vì sao chúng quan trọng)
Linear regression "cổ điển" đi kèm một số giả định. Bạn không cần thuộc lòng, nhưng cần biết để đọc kết quả cho đúng:
- Tuyến tính: quan hệ giữa x và y gần đường thẳng. Nếu thực tế cong, model sẽ khớp kém (trừ khi bạn tự tạo feature bậc 2, tương tác... ở bài FE).
- Độc lập giữa các quan sát.
- Phương sai đều (homoscedasticity): độ phân tán của sai số không đổi theo x.
- Sai số phân phối gần chuẩn (quan trọng cho suy diễn thống kê hơn là dự đoán).
- Không đa cộng tuyến gắt giữa các đặc trưng — nếu có, hệ số trở nên bất ổn và khó diễn giải.
2.4. Đánh giá: R² và RMSE
Sau khi train, ta đánh giá bằng:
- R² (hệ số xác định): tỉ lệ phương sai của y được model giải thích, từ 0 đến 1 (càng gần 1 càng tốt; có thể âm nếu model tệ hơn cả việc đoán trung bình).
- RMSE (Root Mean Squared Error): căn của MSE — cùng đơn vị với y, nên dễ diễn giải ("model sai trung bình khoảng X triệu đồng").
Chi tiết về cách chọn và bẫy của các chỉ số này nằm ở bài Đánh giá mô hình.
# (minh hoạ) Linear regression với scikit-learn
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
import numpy as np
# X: đặc trưng (diện tích, số phòng, khoảng cách trung tâm...)
# y: giá nhà
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
model = LinearRegression() # mặc định dùng OLS (nghiệm đóng)
model.fit(X_train, y_train)
y_pred = model.predict(X_test) # dự đoán số thực
rmse = np.sqrt(mean_squared_error(y_test, y_pred))
print("RMSE:", rmse)
print("R2 :", r2_score(y_test, y_pred))
# Diễn giải hệ số
for name, coef in zip(feature_names, model.coef_):
print(f"{name:20s}: {coef:+.3f}")
print("intercept:", model.intercept_)
3. Logistic regression — phân loại & xác suất
3.1. Từ số thực sang xác suất: hàm sigmoid
Với bài toán phân loại nhị phân (0/1, vỡ nợ / không vỡ nợ), ta không muốn một số bất kỳ mà muốn một xác suất trong khoảng (0, 1). Hàm sigmoid làm chính xác điều đó:
$$ \sigma(z) = \frac{1}{1 + e^{-z}} $$
- Khi
zrất lớn → σ tiến về 1. - Khi
zrất nhỏ (âm nhiều) → σ tiến về 0. - Khi
z = 0→ σ = 0.5.
Kết quả p = σ(w·x + b) được hiểu là "xác suất mẫu này thuộc lớp dương". Muốn ra nhãn, ta so với ngưỡng (mặc định 0.5): p ≥ 0.5 → lớp 1, ngược lại lớp 0. Ngưỡng này có thể và nên điều chỉnh tuỳ bài toán (ví dụ ngân hàng có thể hạ ngưỡng để bắt được nhiều khách rủi ro hơn).
3.2. Hàm mất mát: Log loss (Cross-entropy)
Không dùng MSE cho phân loại. Thay vào đó là log loss (còn gọi binary cross-entropy):
$$ \mathcal{L} = -\frac{1}{m}\sum_{i=1}^{m}\Big[ y_i \log(p_i) + (1-y_i)\log(1-p_i) \Big] $$
Ý tưởng: nếu mẫu thực sự là lớp 1 (y=1) mà model dự đoán p gần 0, thì log(p) rất âm → phạt cực nặng. Log loss "trừng phạt sự tự tin sai lầm", đẩy model đưa ra xác suất có hiệu chỉnh tốt (well-calibrated).
3.3. Decision boundary tuyến tính
Vì z = w·x + b là tuyến tính, ranh giới quyết định (nơi p = 0.5, tức z = 0) là một đường thẳng / mặt phẳng. Điều này nghĩa là logistic regression chỉ tách được các lớp bằng ranh giới thẳng. Với dữ liệu quấn xoắn phi tuyến, nó bó tay — trừ khi bạn tự thêm feature phi tuyến, hoặc chuyển sang cây & ensemble.
3.4. Đa lớp: softmax và OvR
Cho nhiều hơn 2 lớp, scikit-learn hỗ trợ:
- Multinomial (softmax): tổng quát hoá sigmoid, tính xác suất cho tất cả các lớp sao cho tổng bằng 1. Đây là mặc định của
LogisticRegressionhiện nay. - OvR (One-vs-Rest): huấn luyện một bộ phân loại nhị phân cho mỗi lớp ("lớp này vs tất cả còn lại").
3.5. predict vs predict_proba
Đây là điểm cực kỳ hữu ích trong thực tế:
predict()→ trả về nhãn (0 hoặc 1).predict_proba()→ trả về xác suất cho từng lớp.
Trong tín dụng, chính cái xác suất này là PD (Probability of Default) — xác suất khách vỡ nợ. Nó không chỉ dùng để phân loại mà còn để xếp hạng và tính điểm khách hàng, làm nền cho toàn bộ scorecard (xem Credit scorecard).
# (minh hoạ) Logistic regression + predict_proba
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import make_pipeline
# Luôn scale trước khi regularize (mục 5)
clf = make_pipeline(
StandardScaler(),
LogisticRegression(C=1.0, max_iter=1000) # C: nghịch đảo cường độ phạt
)
clf.fit(X_train, y_train)
labels = clf.predict(X_test) # nhãn 0/1
proba = clf.predict_proba(X_test)[:, 1] # xác suất lớp 1 = PD
print("Nhãn dự đoán :", labels[:5])
print("Xác suất PD :", proba[:5].round(3))
4. Gradient descent — cỗ máy học chung
Gradient descent là thuật toán tối ưu đứng sau việc "học" của cả hai model (và gần như mọi model ML/deep learning). Ý tưởng như đứng trên sườn đồi trong sương mù, muốn xuống thung lũng thấp nhất (nơi loss nhỏ nhất):
- Bắt đầu với
w, bngẫu nhiên. - Tính gradient — đạo hàm của loss theo từng tham số (cho biết hướng dốc lên).
- Bước một bước ngược hướng gradient (đi xuống):
w ← w − η · ∇L. - Lặp lại đến khi loss gần như không giảm nữa (hội tụ).
Trong đó η (learning rate) là độ dài bước:
- Quá lớn → nhảy vọt qua đáy, dao động hoặc phân kỳ.
- Quá nhỏ → hội tụ chậm lê thê.
Về cách quét dữ liệu, có ba biến thể chính:
- Batch GD: dùng toàn bộ dữ liệu mỗi bước — ổn định nhưng chậm với dữ liệu lớn.
- SGD (Stochastic GD): mỗi bước dùng một mẫu — rất nhanh, nhiễu, dễ thoát cực tiểu cục bộ.
- Mini-batch: dùng một lô nhỏ — dung hoà và phổ biến nhất.
May mắn là hàm loss của linear và logistic regression đều lồi (convex), nên gradient descent chắc chắn tìm được cực tiểu toàn cục — không lo mắc kẹt cực tiểu cục bộ như các mạng nơ-ron.
5. Regularization — chống overfitting
5.1. Vấn đề
Overfitting là khi model học thuộc lòng cả nhiễu trong dữ liệu train — biểu hiện qua hệ số phình to bất thường. Nó khớp train rất đẹp nhưng dự đoán tệ trên dữ liệu mới. Giải pháp: thêm một thành phần phạt vào hàm loss để "ghìm" các hệ số nhỏ lại.
5.2. L2 (Ridge) — co hệ số
Thêm phạt bằng tổng bình phương các hệ số:
$$ \text{Loss} + \alpha \sum w_j^2 $$
L2 kéo mọi hệ số về gần 0 nhưng hiếm khi bằng đúng 0. Nó "làm mượt", giảm ảnh hưởng của đa cộng tuyến, giữ lại tất cả đặc trưng nhưng với trọng số khiêm tốn hơn. scikit-learn: Ridge (cho hồi quy).
5.3. L1 (Lasso) — đưa hệ số về 0
Thêm phạt bằng tổng giá trị tuyệt đối:
$$ \text{Loss} + \alpha \sum |w_j| $$
Đặc tính hình học của L1 khiến nó đẩy hẳn một số hệ số về đúng 0 → tự động chọn đặc trưng (feature selection). Rất hữu ích khi bạn có hàng trăm feature và muốn model tự loại bớt cái vô dụng. scikit-learn: Lasso.
5.4. Elastic Net — kết hợp cả hai
ElasticNet trộn cả L1 và L2, điều khiển bằng tham số l1_ratio (0 = thuần Ridge, 1 = thuần Lasso). Nó lấy được tính chọn feature của Lasso lẫn sự ổn định của Ridge, đặc biệt tốt khi nhiều feature tương quan.
5.5. Tham số cường độ: C vs alpha
Đây là chỗ dễ nhầm giữa các API scikit-learn:
- Trong
Ridge/Lasso/ElasticNet: dùngalpha— alpha lớn = phạt mạnh (hệ số co nhiều). - Trong
LogisticRegression: dùngC— là nghịch đảo cường độ phạt, nên C nhỏ = phạt mạnh, C lớn = phạt nhẹ.
5.6. Vì sao phải scale trước khi regularize
Phạt L1/L2 dựa trên độ lớn hệ số. Nếu một đặc trưng có đơn vị lớn (ví dụ thu nhập tính bằng đồng, cỡ hàng triệu) và một đặc trưng khác nhỏ (số năm làm việc), thì hệ số của chúng ở thang khác nhau, và hình phạt sẽ bất công — đè bẹp feature này, buông lỏng feature kia. Vì vậy luôn chuẩn hoá (StandardScaler) trước khi dùng model có regularization. Đây là lý do ở bài Feature engineering ta nhấn mạnh scaling.
# (minh hoạ) Ridge và Lasso
from sklearn.linear_model import Ridge, Lasso
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import make_pipeline
# Ridge (L2): co đều hệ số, giữ hết feature
ridge = make_pipeline(StandardScaler(), Ridge(alpha=1.0))
ridge.fit(X_train, y_train)
# Lasso (L1): một số hệ số bị đưa về 0 → chọn feature
lasso = make_pipeline(StandardScaler(), Lasso(alpha=0.1))
lasso.fit(X_train, y_train)
lasso_model = lasso.named_steps["lasso"]
n_zero = (lasso_model.coef_ == 0).sum()
print(f"Lasso đã loại {n_zero}/{len(lasso_model.coef_)} đặc trưng")
6. Diễn giải hệ số — thế mạnh chí mạng
Đây là lý do lớn nhất khiến giới quản lý rủi ro yêu hai model này.
Với linear regression (khi feature đã scale): hệ số cho biết "khi feature này tăng 1 độ lệch chuẩn, y thay đổi bao nhiêu đơn vị". Dấu cho biết hướng tác động (+ tăng, − giảm), độ lớn cho biết mức quan trọng tương đối.
Với logistic regression: hệ số nằm ở thang log-odds. Muốn diễn giải trực quan, ta lấy exp(hệ số) = odds ratio (tỉ số chênh):
- Feature tăng 1 đơn vị → odds của biến cố được nhân với
exp(w). exp(w) > 1→ làm tăng khả năng xảy ra biến cố;exp(w) < 1→ làm giảm.
Ví dụ: một hệ số 0.7 tương ứng odds ratio exp(0.7) ≈ 2.0, nghĩa là mỗi đơn vị tăng của feature làm odds vỡ nợ tăng gấp đôi. Câu này một chuyên viên tín dụng nghe là hiểu ngay — điều mà một mạng nơ-ron sâu không bao giờ nói được.
Chính khả năng "chỉ tận tay từng yếu tố đẩy điểm lên/xuống" khiến logistic regression trở thành tiêu chuẩn vàng cho credit scorecard ở ngân hàng: nó vừa đáp ứng yêu cầu minh bạch với cơ quan quản lý, vừa cho phép giải thích với khách hàng vì sao đơn vay bị từ chối.
# (minh hoạ) Odds ratio từ hệ số logistic
import numpy as np
logreg = clf.named_steps["logisticregression"]
for name, coef in zip(feature_names, logreg.coef_[0]):
print(f"{name:20s} coef={coef:+.3f} odds_ratio={np.exp(coef):.2f}")
7. Khi nào dùng — và khi nào không
Nên dùng khi:
- Quan hệ giữa feature và target gần tuyến tính.
- Bạn cần giải thích quyết định (tín dụng, bảo hiểm, y tế, pháp lý).
- Cần một baseline mạnh để so sánh: luôn bắt đầu bằng linear/logistic trước khi thử model phức tạp. Rất thường xuyên, baseline này đã đủ tốt.
- Dữ liệu ít, cần model ổn định, huấn luyện siêu nhanh, dễ triển khai.
Hạn chế cần biết:
- Không tự bắt được phi tuyến hay tương tác giữa các biến — trừ khi bạn tự tạo feature (bậc cao, tương tác, binning...). Đây là ranh giới tự nhiên dẫn ta sang cây & ensemble, vốn tự động bắt phi tuyến.
- Nhạy với outlier (nhất là linear + MSE) và đa cộng tuyến.
Use case thực tế
Logistic cho PD / scorecard (ngân hàng). Một mô hình chấm điểm tín dụng điển hình dùng logistic regression: đầu vào là các biến đã được WoE-hoá (thu nhập, lịch sử trả nợ, số khoản vay đang có...), đầu ra predict_proba chính là PD. PD sau đó được ánh xạ sang điểm số và hạng khách hàng. Model được ưa chuộng vì mỗi hệ số → một điểm cộng/trừ minh bạch, kiểm toán được, và ổn định qua thời gian. Xem chi tiết ở Credit scorecard.
Linear cho dự báo. Dự báo doanh thu chi nhánh theo mùa vụ, ước lượng dư nợ kỳ tới, dự đoán số lượng giao dịch — những bài toán có xu hướng gần tuyến tính và cần một con số kèm mức "sai trung bình" (RMSE) dễ giải thích cho lãnh đạo.
Ghi nhớ
- Linear:
y = w·x + b, loss MSE, đầu ra số thực; đánh giá bằng R², RMSE. - Logistic: đẩy
w·x+bqua sigmoid → xác suất; loss log loss; ranh giới quyết định tuyến tính;predict_proba= PD. - Gradient descent tối thiểu hoá loss; chỉnh learning rate; loss lồi → hội tụ về cực tiểu toàn cục.
- Regularization: L2 (Ridge) co hệ số, L1 (Lasso) đưa hệ số về 0 (chọn feature), Elastic Net kết hợp.
alphalớn hoặcCnhỏ = phạt mạnh. Luôn scale trước khi regularize. - Diễn giải: dấu + độ lớn (đã scale); logistic dùng odds ratio = exp(hệ số).
- Chọn hai model này khi cần giải thích được và làm baseline — nền tảng không thể thiếu trước khi bước sang cây & ensemble và đánh giá mô hình.
Bài viết liên quan
Phân biệt AI/ML/DL, các kiểu học máy, quy trình ML end-to-end và thuật ngữ nền tảng.
Chất lượng dữ liệu, xử lý thiếu/ngoại lai, mã hoá, chuẩn hoá, tạo đặc trưng và tránh data leakage.
Mô hình ngôn ngữ lớn hoạt động ra sao, token, context window, tham số sinh, và kỹ thuật viết prompt.
Retrieval-Augmented Generation, vector database, tool calling, agent và MCP để xây ứng dụng LLM thực tế.