Ridge, Lasso, Elastic Net
Mục tiêu
Phần tiêu đề “Mục tiêu”Sau bài này, bạn sẽ:
- Hiểu regularization là cộng vào hàm mất mát một khoản phạt cho trọng số lớn, và vì sao điều đó làm đa thức bậc cao bớt overfitting.
- Tự dẫn được nghiệm dạng đóng (closed-form solution) của hồi quy Ridge (Ridge regression) từ phương trình chuẩn.
- Giải thích được vì sao Lasso đưa nhiều hệ số về đúng 0 còn Ridge thì không, bằng một ví dụ một biến và bằng hình học.
- Cài đặt được Ridge, Lasso, Elastic Net trong scikit-learn có chuẩn hóa đặc trưng (feature standardization), đổi đúng sang
alpha, và chọn bằng kiểm định chéo (cross-validation).
Cần biết trước
Phần tiêu đề “Cần biết trước”- Overfitting và Underfitting, thuộc phần Học máy (Đã học)
Trực giác
Phần tiêu đề “Trực giác”Nhớ lại Chi ở bài trước: đường bậc 15 của Chi đi qua đúng cả 16 điểm train, nhưng giữa các điểm thì vọt lên, cắm xuống. Bài trước chữa bằng cách hạ bậc xuống 3. Bài này thử cách thứ ba đã hẹn: giữ nguyên bậc 15, nhưng không cho đường cong uốn tùy thích.
Đường bậc 15 uốn được như vậy nhờ các hệ số lớn tới hàng chục tỉ, đổi dấu xen kẽ: số hạng này kéo đường lên rất mạnh, số hạng kế bên kéo xuống gần mạnh như thế. Tại 16 điểm train, các lực kéo triệt tiêu nhau gần như hoàn hảo; giữa các điểm, chỉ lệch nhau một chút là đường vọt khỏi khung. Đường cong mềm bậc 3 của Bình không cần hệ số lớn như thế. Vậy hệ số khổng lồ là triệu chứng của overfitting.
Hãy tưởng tượng mỗi hệ số phải đóng thuế theo độ lớn của nó. Mô hình phải cân giữa đi gần các điểm train (MSE nhỏ) và giữ hệ số nhỏ (thuế ít). Hệ số chỉ để uốn theo một hạt nhiễu thì không đáng tiền thuế. Còn hai câu hỏi:
- Thuế bao nhiêu? Quá nhẹ thì vẫn overfitting. Quá nặng thì mọi hệ số bị ép về gần 0, đường gần như nằm ngang: underfitting. Mức thuế là con số bạn phải chọn.
- Tính thuế thế nào? Theo bình phương hệ số (Ridge) hay trị tuyệt đối (Lasso). Lasso đưa nhiều hệ số về đúng 0, Ridge thì không.
Dữ liệu vẫn là 24 điểm của bài trước: 16 điểm train để khớp, 8 điểm test để chấm.
Xem bảng 24 điểm
| x | y |
|---|---|
| 0.03 | 0.15 |
| 0.12 | 1.06 |
| 0.15 | 0.84 |
| 0.23 | 0.96 |
| 0.26 | 0.83 |
| 0.35 | 0.94 |
| 0.41 | 0.30 |
| 0.47 | −0.09 |
| 0.51 | −0.17 |
| 0.60 | −0.32 |
| 0.64 | −0.68 |
| 0.73 | −0.84 |
| 0.77 | −0.28 |
| 0.85 | −0.82 |
| 0.90 | −0.53 |
| 0.98 | −0.02 |
| x | y |
|---|---|
| 0.06 | 0.33 |
| 0.18 | 0.66 |
| 0.32 | 0.93 |
| 0.43 | 0.43 |
| 0.55 | −0.42 |
| 0.67 | −1.11 |
| 0.80 | −1.18 |
| 0.94 | −0.45 |
Bài toán của bài này là: giữ đa thức bậc 15, cộng vào MSE một khoản phạt cho hệ số lớn, rồi chọn mức phạt bằng dữ liệu, sao cho đường cong mềm vừa đủ để đoán tốt điểm mới.
Lý thuyết
Phần tiêu đề “Lý thuyết”Hàm mục tiêu có phạt
Phần tiêu đề “Hàm mục tiêu có phạt”Mô hình vẫn là đa thức bậc 15, tức hồi quy tuyến tính trên đặc trưng: . Hàm mất mát vẫn là MSE trên điểm train. Regularization thay việc làm nhỏ bằng việc làm nhỏ một hàm mục tiêu (objective function) , gồm cộng một khoản phạt:
- là hệ số phạt (penalty strength), một siêu tham số. cho lại bình phương tối thiểu thường, tức đường bậc 15 của Chi.
- là bình phương của chuẩn L2 (L2 norm), tức bình phương độ dài vectơ . là chuẩn L1 (L1 norm). Vì vậy Ridge còn gọi là phạt L2, Lasso là phạt L1.
- Hệ số tự do (bias, còn gọi là intercept) không bị phạt. chỉ dời cả đường lên xuống, không làm đường uốn. Phạt sẽ kéo đường về phía một cách vô cớ.
Ridge do Hoerl và Kennard đề xuất (1970). Lasso của Tibshirani (1996) viết tắt “least absolute shrinkage and selection operator”: vừa co (shrinkage) hệ số, vừa chọn đặc trưng.
Chuẩn hóa đặc trưng trước khi phạt
Phần tiêu đề “Chuẩn hóa đặc trưng trước khi phạt”Khoản phạt đối xử mọi như nhau, nhưng độ lớn của phụ thuộc đơn vị của đặc trưng. Đổi từ mét sang centimét, cột số lớn lên 100 lần, phải nhỏ đi 100 lần, nên phạt nhỏ đi 10 000 lần. Chỉ vì đổi đơn vị mà mô hình khớp ra khác.
Cách chữa là chuẩn hóa đặc trưng: , với , là trung bình và độ lệch chuẩn của trên tập train (StandardScaler). Mọi đặc trưng khi đó có trung bình 0, độ lệch chuẩn 1, nên bị phạt công bằng. Với đa thức, , và từ đây là hệ số của , không còn của .
Ridge: nghiệm dạng đóng
Phần tiêu đề “Ridge: nghiệm dạng đóng”Gọi là ma trận có phần tử ở hàng , cột là . Khác bài Hồi quy tuyến tính, không có cột số 1, vì được tính riêng. Mỗi cột có trung bình 0 nên tổng bằng 0: , với là vectơ toàn số 1. Hàm mục tiêu của Ridge là:
Bước 1: tìm . Khoản phạt không chứa , nên đạo hàm riêng theo giống bài Hồi quy tuyến tính: . Cho nó bằng 0 rồi thay :
Mỗi tổng theo cột bằng 0 vì cột đã trừ trung bình. Vậy luôn bằng của tập train, với mọi .
Bước 2: thay vào. Đặt (nhãn đã trừ trung bình). Khi đó , và hàm mục tiêu chỉ còn theo :
Bước 3: đạo hàm theo , cho bằng 0. Như bài Hồi quy tuyến tính, đạo hàm riêng của phần MSE theo là hàng của . Đạo hàm của là , xếp lại thành :
Bước 4: gom về một vế.
Dòng đầu nhân hai vế với rồi phá ngoặc. Dòng thứ hai chuyển sang phải và viết , với là ma trận đơn vị (identity matrix) . Dòng thứ ba đặt ra ngoài. Cuối cùng, , nên:
So với phương trình chuẩn, chỉ khác số cộng vào đường chéo. Số nhỏ này đổi hẳn tình thế:
- Luôn có nghiệm duy nhất khi . Với mọi , , nên ma trận khả nghịch, kể cả khi các cột cộng tuyến (collinearity) hay có ít mẫu hơn đặc trưng.
- Đây là trong code.
Ridgecủa scikit-learn làm nhỏ , tức khi , nên code viếtRidge(alpha=m * lam).
Vì sao hệ số co lại: ví dụ một biến
Phần tiêu đề “Vì sao hệ số co lại: ví dụ một biến”Xét một đặc trưng đã chuẩn hóa , nên . Gọi và . Khai triển MSE theo :
Dòng đầu khai triển và đưa ra ngoài các tổng. Dòng thứ hai dùng và định nghĩa của . Dòng cuối dùng . Vì không chứa , MSE là parabol theo với đáy ở , nghiệm khi không phạt.
Với Ridge, làm nhỏ . Đạo hàm theo cho bằng 0:
Ridge chia cho : hệ số nhỏ lại, giữ dấu, nhưng không bao giờ bằng đúng 0 (trừ khi ).
Khi có nhiều đặc trưng, Ridge co mạnh nhất theo những hướng mà dữ liệu “nói” ít nhất. Các cột gần như trùng nhau ( và có hệ số tương quan 0.9996), nên “tăng thật nhiều, giảm thật nhiều” là một hướng mà đổi theo nó thì dự đoán đổi rất ít. Các hệ số hàng chục tỉ sinh ra theo những hướng như vậy, và một chút phạt rất nhỏ đã đủ dập chúng.
Vì sao Lasso cho hệ số đúng bằng 0
Phần tiêu đề “Vì sao Lasso cho hệ số đúng bằng 0”Ví dụ một biến. Với Lasso, làm nhỏ . Hàm gãy góc ở 0, nên xét từng phía:
- : đạo hàm là , bằng 0 khi . Chỉ hợp lệ khi kết quả dương, tức .
- : đạo hàm là , cho . Hợp lệ khi .
- Khi : bên phải 0 đạo hàm luôn dương, bên trái 0 đạo hàm luôn âm. Hàm tăng khi rời 0 theo cả hai hướng, nên nhỏ nhất tại .
Lasso trừ một lượng cố định khỏi độ lớn của rồi cắt ở 0, gọi là soft-thresholding. So hai cách với :
| Ridge: | Lasso | |
|---|---|---|
| 0.2 | 0.25 | 0.2 |
| 0.4 | 0.2143 | 0.1 |
| 1 | 0.15 | 0 |
Gốc rễ nằm ở độ dốc của khoản phạt gần 0. Phạt Ridge có độ dốc , sát 0 thì gần như phẳng, nên dữ liệu kéo yếu mấy cũng đưa được ra khỏi 0. Phạt Lasso có độ dốc ngay cả sát 0: lực kéo của dữ liệu () phải thắng thì mới rời 0.
Hình học. Có thể chứng minh rằng với mỗi có một “ngân sách” sao cho bài toán có phạt cùng nghiệm với bài toán: làm MSE nhỏ nhất, với điều kiện độ lớn của không vượt quá . Với hai trọng số, vùng cho phép của Ridge, , là hình tròn; của Lasso, , là hình thoi có bốn đỉnh trên hai trục. Đường đồng mức của MSE là những elip quanh nghiệm bình phương tối thiểu. Khi nghiệm đó nằm ngoài vùng cho phép, phình elip ra tới khi chạm vùng: điểm chạm là nghiệm.
Hình tròn không có góc nhô ra, nên điểm chạm thường có cả hai tọa độ khác 0. Hình thoi có đỉnh nhọn nằm đúng trên các trục, và elip rất dễ chạm ở một đỉnh, nơi một tọa độ bằng 0. Với 15 trọng số, “hình thoi” có rất nhiều đỉnh và cạnh như vậy, nên nhiều hệ số bằng 0 cùng lúc: mô hình thưa (sparse).
Lasso không có nghiệm dạng đóng. scikit-learn giải bằng coordinate descent: lần lượt cập nhật từng hệ số, mỗi lần dùng phép soft-thresholding ở trên.
Elastic Net
Phần tiêu đề “Elastic Net”Elastic Net (Zou và Hastie, 2005) cộng cả hai khoản phạt:
là Lasso, là Ridge. Khi vài đặc trưng tương quan rất mạnh, như và , Lasso thường giữ một cái, bỏ cái kia khá tùy ý. Phần L2 chia trọng số đều hơn giữa các đặc trưng giống nhau, phần L1 vẫn cho hệ số đúng 0. Đổi lại, có hai siêu tham số phải chọn. ElasticNet viết chúng thành alpha và l1_ratio (cách đổi ở comment của ô code thứ ba).
Chọn λ
Phần tiêu đề “Chọn λ” là siêu tham số, nên chọn như chọn bậc ở bài trước: thử một lưới (thường cách nhau theo lũy thừa của 10), giữ mức có MSE kiểm định chéo nhỏ nhất, khớp lại trên cả tập train, rồi chấm tập test một lần. Đặt StandardScaler trong pipeline, để mỗi lần khớp nó chỉ học từ phần đang dùng để khớp.
Giới hạn
Phần tiêu đề “Giới hạn”- Không thắng được việc chọn đúng mô hình. Ở bộ dữ liệu này, Ridge và Lasso bậc 15 vẫn kém đa thức bậc 3 (cuối mục Ví dụ code).
- chọn ra dao động khi dữ liệu ít (ô code thứ ba).
- Lasso chọn đặc trưng khá tùy ý khi chúng tương quan mạnh. Đừng coi tập nó giữ lại là “đặc trưng quan trọng thật”.
- Không chỉ cho hồi quy tuyến tính. Hồi quy logistic và mạng nơ-ron cũng phạt trọng số (phạt L2 ở đó thường gọi là weight decay).
Minh họa
Phần tiêu đề “Minh họa”Hình dưới vẽ điểm train (chấm đặc), điểm test (vòng rỗng) và đa thức bậc 15 khớp với hệ số phạt . Thanh trượt đổi qua 17 mức: 0, rồi . Hai nút Ridge và Lasso đổi kiểu phạt, giữ nguyên . Bên dưới là hai MSE, số hệ số bằng đúng 0 (vòng “0” trên biểu đồ cột) và 15 cột hệ số . Hãy thử:
- Lúc đầu là Ridge, : đường bậc 15 của bài trước, MSE test 133.20, cả 15 cột vượt khung.
- Kéo tới : MSE train 0.0491, MSE test 0.0894, nhỏ nhất trên thanh trượt (dấu ✓). Mọi cột nằm trong khung.
- Bấm Lasso: MSE train 0.0314, MSE test 0.0851, và 10/15 hệ số bằng đúng 0, chỉ còn .
- Kéo tới : Ridge có MSE train 0.3148, MSE test 0.4750, underfitting. Lasso có cả 15 hệ số bằng 0, đường nằm ngang ở .
Dấu ✓ nhìn vào tập test, việc mà khi làm thật bạn không được làm. Phần Lasso của hình được tính sẵn bằng một cách giải chính xác, vì ở rất nhỏ coordinate descent hội tụ rất chậm.
- Điểm train
- Điểm test
- Đa thức bậc 15 đã khớp
- Vượt khung (trị tuyệt đối lớn hơn 10)
Overfitting: phạt quá nhẹ, hệ số rất lớn và đường cong uốn theo cả nhiễu, MSE test lớn.
16 điểm train, x từ 0.03 tới 0.98, đi theo một vòng sóng: lên gần 1 khi x từ 0.1 tới 0.35, xuống gần −1 khi x từ 0.7 tới 0.85, rồi về gần 0. Các điểm lệch khỏi dạng sóng vì có nhiễu. 8 điểm test nằm xen giữa các điểm train, theo cùng dạng sóng.
Mỗi cột là hệ số wₖ của đặc trưng xᵏ đã chuẩn hóa, k từ 1 đến 15. Cột hướng lên là hệ số dương, hướng xuống là hệ số âm.
Ví dụ code
Phần tiêu đề “Ví dụ code”Ba ô dưới đây chạy độc lập. Ô chạy đầu tiên lâu hơn một chút, vì trình duyệt phải tải thêm scikit-learn. Mọi ô dùng cùng pipeline: PolynomialFeatures tạo các cột , StandardScaler chuẩn hóa chúng, rồi tới mô hình có phạt. model[-1] là bước cuối, có coef_ (các ) và intercept_ ().
Ridge với vài mức λ
Phần tiêu đề “Ridge với vài mức λ”Ô đầu tiên khớp Ridge với năm mức , in hai MSE, hệ số lớn nhất về trị tuyệt đối, và .
Ridge trên đa thức bậc 15
import numpy as npfrom sklearn.linear_model import Ridgefrom sklearn.metrics import mean_squared_errorfrom sklearn.pipeline import make_pipelinefrom sklearn.preprocessing import PolynomialFeatures, StandardScaler
# 24 điểm tự sinh từ y = sin(2πx) cộng nhiễu: 16 điểm train, 8 điểm test.# dataset: sine-trainx_train = np.array([0.03, 0.12, 0.15, 0.23, 0.26, 0.35, 0.41, 0.47, 0.51, 0.6, 0.64, 0.73, 0.77, 0.85, 0.9, 0.98])y_train = np.array([0.15, 1.06, 0.84, 0.96, 0.83, 0.94, 0.3, -0.09, -0.17, -0.32, -0.68, -0.84, -0.28, -0.82, -0.53, -0.02])# dataset: sine-testx_test = np.array([0.06, 0.18, 0.32, 0.43, 0.55, 0.67, 0.8, 0.94])y_test = np.array([0.33, 0.66, 0.93, 0.43, -0.42, -1.11, -1.18, -0.45])
m = len(x_train) # 16 điểm trainfor lam in [1e-12, 1e-8, 1e-3, 1e-1, 10]: # Ridge của scikit-learn không chia tổng bình phương cho m, # nên phải đặt alpha = m * lambda để khớp hàm mục tiêu của bài. model = make_pipeline(PolynomialFeatures(15, include_bias=False), StandardScaler(), Ridge(alpha=m * lam)) model.fit(x_train[:, None], y_train) # chỉ học từ tập train tr = mean_squared_error(y_train, model.predict(x_train[:, None])) te = mean_squared_error(y_test, model.predict(x_test[:, None])) w = model[-1].coef_ # 15 trọng số của các đặc trưng đã chuẩn hóa b = model[-1].intercept_ # hệ số tự do, không bị phạt print(f"lambda = {lam:g}: MSE train = {tr:.4f}, test = {te:.4f}, " f"max |w| = {np.abs(w).max():.2f}, b = {b:.4f}")Lần chạy đầu cần tải Python, khoảng 10 MB.
Chỉ đã kéo MSE test từ khoảng 133 xuống 0.5375, hệ số lớn nhất từ hàng chục tỉ còn 26594.49: đó là các “hướng mà dữ liệu nói ít”. Ở , MSE test nhỏ nhất (0.0894) và hệ số lớn nhất chỉ còn 2.75. Ở , MSE train 0.3148, gần gấp đôi đường thẳng bậc 1 của bài trước (0.1663): underfitting. MSE train tăng dần theo , còn MSE test giảm rồi tăng: hình chữ U như khi đổi bậc, chỉ là trục ngang đảo chiều. ở cả năm mức, đúng bằng , như Bước 1.
Lasso và các hệ số bằng 0
Phần tiêu đề “Lasso và các hệ số bằng 0”Ô thứ hai khớp Lasso với ba mức , đếm số hệ số bằng đúng 0 (w == 0) và in các còn giữ lại. Cuối ô là Ridge ở để so sánh.
Lasso: đếm hệ số bằng 0
import numpy as npfrom sklearn.linear_model import Lasso, Ridgefrom sklearn.metrics import mean_squared_errorfrom sklearn.pipeline import make_pipelinefrom sklearn.preprocessing import PolynomialFeatures, StandardScaler
# 24 điểm tự sinh từ y = sin(2πx) cộng nhiễu: 16 điểm train, 8 điểm test.# dataset: sine-trainx_train = np.array([0.03, 0.12, 0.15, 0.23, 0.26, 0.35, 0.41, 0.47, 0.51, 0.6, 0.64, 0.73, 0.77, 0.85, 0.9, 0.98])y_train = np.array([0.15, 1.06, 0.84, 0.96, 0.83, 0.94, 0.3, -0.09, -0.17, -0.32, -0.68, -0.84, -0.28, -0.82, -0.53, -0.02])# dataset: sine-testx_test = np.array([0.06, 0.18, 0.32, 0.43, 0.55, 0.67, 0.8, 0.94])y_test = np.array([0.33, 0.66, 0.93, 0.43, -0.42, -1.11, -1.18, -0.45])
def fit(model): # Đa thức bậc 15, chuẩn hóa đặc trưng, rồi mô hình có phạt. pipe = make_pipeline(PolynomialFeatures(15, include_bias=False), StandardScaler(), model) return pipe.fit(x_train[:, None], y_train)
for lam in [1e-3, 1e-2, 1e-1]: # Lasso của scikit-learn có thêm 1/2 ở trước MSE, nên alpha = lambda / 2. model = fit(Lasso(alpha=lam / 2, max_iter=100_000, tol=1e-6)) tr = mean_squared_error(y_train, model.predict(x_train[:, None])) te = mean_squared_error(y_test, model.predict(x_test[:, None])) w = model[-1].coef_ kept = np.flatnonzero(w) + 1 # bậc k của các hệ số khác 0 print(f"lambda = {lam:g}: MSE train = {tr:.4f}, test = {te:.4f}") print(f" zeros = {np.sum(w == 0)}/15, kept k = {kept.tolist()}")
# So sánh: Ridge cùng lambda = 0.001 không đưa hệ số nào về đúng 0.w = fit(Ridge(alpha=len(x_train) * 1e-3))[-1].coef_print(f"ridge 0.001: zeros = {np.sum(w == 0)}/15, " f"min |w| = {np.abs(w).min():.2f}")Lần chạy đầu cần tải Python, khoảng 10 MB.
- Ở , Lasso có MSE test 0.0851, nhỉnh hơn Ridge cùng mức (0.0894), và chỉ giữ 5 hệ số: . Ở còn 4, ở còn 3 (lý thuyết không bảo đảm lúc nào cũng tăng như vậy).
- Ridge cùng mức 0.001 có 0/15 hệ số bằng 0; nhỏ nhất là 0.07, nhỏ nhưng khác 0.
Các được giữ đổi khá tùy ý (4 và 9, rồi 6 và 7), vì các cột gần như trùng nhau: đó là lý do của Elastic Net. Ô không dùng từ trở xuống, vì ở đó coordinate descent không kịp hội tụ (hộp thứ ba ở mục Lỗi hay gặp).
Chọn λ bằng kiểm định chéo
Phần tiêu đề “Chọn λ bằng kiểm định chéo”Ô thứ ba chọn chỉ bằng 16 điểm train, với KFold(n_splits=4, shuffle=True, random_state=0) như bài trước. Ridge thử từ tới 10. Lasso và Elastic Net () chỉ thử 0.01 và 0.1, vì ở 0.001 Lasso không hội tụ kịp trong các fold. alpha của Ridge giữ là cả trong các fold chỉ có 12 điểm, như RidgeCV vẫn làm, nên thật trong fold là . Thử với alpha vẫn chọn cùng mức.
Chọn λ bằng kiểm định chéo
import numpy as npfrom sklearn.linear_model import ElasticNet, Lasso, Ridgefrom sklearn.metrics import mean_squared_errorfrom sklearn.model_selection import KFold, cross_val_scorefrom sklearn.pipeline import make_pipelinefrom sklearn.preprocessing import PolynomialFeatures, StandardScaler
# dataset: sine-trainx_train = np.array([0.03, 0.12, 0.15, 0.23, 0.26, 0.35, 0.41, 0.47, 0.51, 0.6, 0.64, 0.73, 0.77, 0.85, 0.9, 0.98])y_train = np.array([0.15, 1.06, 0.84, 0.96, 0.83, 0.94, 0.3, -0.09, -0.17, -0.32, -0.68, -0.84, -0.28, -0.82, -0.53, -0.02])# dataset: sine-testx_test = np.array([0.06, 0.18, 0.32, 0.43, 0.55, 0.67, 0.8, 0.94])y_test = np.array([0.33, 0.66, 0.93, 0.43, -0.42, -1.11, -1.18, -0.45])
# Ridge giữ alpha = 16 * lambda cả trong fold 12 điểm (như RidgeCV).makers = { "ridge": lambda lam: Ridge(alpha=len(x_train) * lam), "lasso": lambda lam: Lasso(alpha=lam / 2, max_iter=100_000, tol=1e-6), # lambda_1 = lambda_2 = lam: alpha = lam/2 + lam, l1_ratio = (lam/2)/alpha "enet": lambda lam: ElasticNet(alpha=1.5 * lam, l1_ratio=1 / 3, max_iter=100_000, tol=1e-6),}cv = KFold(n_splits=4, shuffle=True, random_state=0) # chỉ chia tập trainfor name, make in makers.items(): # Lasso ở 0.001 không hội tụ kịp trong các fold: bắt đầu từ 0.01. lams = 10.0 ** np.arange(-6, 2) if name == "ridge" else [0.01, 0.1] pipes, cv_mse = {}, {} for lam in lams: pipes[lam] = make_pipeline(PolynomialFeatures(15, include_bias=False), StandardScaler(), make(lam)) scores = cross_val_score(pipes[lam], x_train[:, None], y_train, cv=cv, scoring="neg_mean_squared_error") cv_mse[lam] = -scores.mean() print(f"{name} lambda = {lam:g}: CV MSE = {cv_mse[lam]:.4f}") best = min(cv_mse, key=cv_mse.get) # Chọn xong mới khớp lại trên cả tập train, chấm một lần trên test. model = pipes[best].fit(x_train[:, None], y_train) te = mean_squared_error(y_test, model.predict(x_test[:, None])) print(f" best: lambda = {best:g}, test MSE = {te:.4f}, " f"zeros = {np.sum(model[-1].coef_ == 0)}")Lần chạy đầu cần tải Python, khoảng 10 MB.
Kiểm định chéo chọn Ridge (MSE kiểm định chéo 0.1605), cho MSE test 0.1747. Nó không chọn , mức tốt nhất trên tập test ở ô đầu: ở đó MSE kiểm định chéo là 0.3409, lớn gấp đôi.
Vì sao lệch nhau? Điểm test nằm xen giữa điểm train (từ tới ), nên không bắt đường cong đoán ở chỗ trống. Kiểm định chéo thì có: fold giữ lại hay bắt đa thức bậc 15 phải ngoại suy (extrapolation), fold giữ lại cả lẫn để trống từ 0.77 tới 0.98. Ở đó, đường phạt nhẹ vung mạnh: khi giữ lại , bình phương sai số tại điểm này là 0.88 với , chỉ 0.02 với . Nên ở đây kiểm định chéo nghiêng về phạt nặng. Nó vẫn là cách đúng: 0.0894 lạc quan vì đã nhìn tập test để chọn, còn 0.1747 thì trung thực.
Lasso chọn : MSE test 0.1341, 11 hệ số bằng 0. Elastic Net cũng chọn , MSE kiểm định chéo 0.1696 (Lasso là 0.1765), MSE test 0.1481, và chỉ 6 hệ số bằng 0, vì phần L2 chia trọng số cho các cột giống nhau thay vì bỏ hẳn chúng.
Vậy regularization có đáng không?
Phần tiêu đề “Vậy regularization có đáng không?”| Mô hình | chọn bằng | MSE test |
|---|---|---|
| Bậc 15, không phạt | khoảng 133 | |
| Bậc 3, không phạt | kiểm định chéo (bài trước) | 0.0754 |
| Ridge bậc 15, | nhìn tập test (không được làm) | 0.0894 |
| Lasso bậc 15, | nhìn tập test (không được làm) | 0.0851 |
| Ridge bậc 15, | kiểm định chéo | 0.1747 |
| Lasso bậc 15, | kiểm định chéo | 0.1341 |
| Elastic Net bậc 15, | kiểm định chéo | 0.1481 |
Nói thẳng: ở bộ dữ liệu này, chọn đúng bậc 3 vẫn tốt nhất. Ngay cả ở mức tốt nhất trên lưới, chọn bằng tập test, Ridge kém bậc 3 khoảng 19%, Lasso khoảng 13%. Ridge với khoảng , giữa hai nấc của lưới, cho khoảng 0.085, vẫn kém khoảng 12%. Quy luật thật rất gần một đa thức bậc 3, nên “chọn bậc” là đúng núm vặn cho bài toán này. Vậy vì sao vẫn cần regularization?
- Không phải dò từng tập đặc trưng. Ở đây các đặc trưng có thứ tự tự nhiên, nên thử bậc 1 tới 15 là đủ. Với 50 đặc trưng như diện tích, số phòng, khoảng cách tới trung tâm, không có “bậc” để dò, còn số tập con là , tức hơn một triệu tỉ. là một núm duy nhất cho mọi đặc trưng.
- Chặn thảm họa. Từ khoảng 133 xuống 0.1747 chỉ bằng một tham số, kể cả khi kiểm định chéo chọn thận trọng.
- Lasso tự chọn đặc trưng, và kiểm định chéo có thể chọn cùng lúc cả bậc lẫn .
Lỗi hay gặp
Phần tiêu đề “Lỗi hay gặp”Kiểm tra nhanh
Phần tiêu đề “Kiểm tra nhanh”Tóm tắt và đọc thêm
Phần tiêu đề “Tóm tắt và đọc thêm”Ý chính:
- Regularization làm nhỏ MSE cộng một khoản phạt: Ridge , Lasso , Elastic Net cả hai; không bị phạt. nhỏ quá là overfitting, lớn quá là underfitting.
- Ridge: , (đặc trưng đã chuẩn hóa). Mọi hệ số co lại nhưng không về đúng 0.
- Lasso trừ một lượng cố định rồi cắt ở 0 (một biến: khi ), nên cho mô hình thưa. Hình thoi L1 có đỉnh trên các trục, hình tròn L2 thì không.
- Chuẩn hóa đặc trưng trong pipeline. Đổi đúng sang
alpha(Ridge: , Lasso: ). Chọn bằng kiểm định chéo, kể cả khi nó thận trọng hơn mức tốt nhất trên tập test.
Đọc thêm:
- Vũ Hữu Tiệp (2017). Machine Learning cơ bản, Bài 15: Overfitting, mục regularization. Tiếng Việt, giới thiệu L2 (weight decay), L1 và Elastic Net. Ký hiệu: là số mẫu, là hàm mất mát.
- scikit-learn developers (2007–2026). scikit-learn 1.8 User Guide: Linear Models, các mục Ridge, Lasso và Elastic-Net. Hàm mục tiêu chính xác của từng lớp, để đổi
alphacho đúng. - James, G., Witten, D., Hastie, T., Tibshirani, R. (2013). An Introduction to Statistical Learning (PDF), bản 1, chương 6: Linear Model Selection and Regularization. Ký hiệu khác: là số mẫu, là số đặc trưng, là trọng số.
- Tibshirani, R. (1996). Regression Shrinkage and Selection via the Lasso. Journal of the Royal Statistical Society: Series B 58(1), 267–288. Bài báo đề xuất Lasso.
- Hoerl, A. E., Kennard, R. W. (1970). Ridge Regression: Biased Estimation for Nonorthogonal Problems. Technometrics 12(1), 55–67. Và Zou, H., Hastie, T. (2005). Regularization and Variable Selection via the Elastic Net. Journal of the Royal Statistical Society: Series B 67(2), 301–320. Hai bài báo đề xuất Ridge và Elastic Net.
Trình duyệt đang chặn lưu dữ liệu. Tiến độ sẽ mất khi bạn tải lại trang.
Nội dung theo giấy phép CC BY-NC-SA 4.0. Mã nguồn theo giấy phép MIT.Giới thiệu