Mục lục
- Mục tiêu bài học và mở Module 3
- Linear Regression là gì
- Single feature — phương trình đường thẳng
- Diễn giải hình học của w và b
- Multiple features — dạng vector
- Loss function — MSE
- Tìm parameter tối ưu — OLS closed-form
- Tìm parameter tối ưu — Gradient Descent
- Các giả định của Linear Regression
- Khi nào nên dùng Linear Regression
- Giới hạn cần biết
- Use case thực tế
- Regression vs Classification
- Demo công thức với data đơn giản
- Code Python — implement từ list thuần
- Bài tập thực hành
- Bài tiếp theo
Mục tiêu bài học và mở Module 3
Module 2 đã xong: bạn đã biết split dataset, scale feature số, encode feature categorical, xử lý outlier và đóng gói tất cả vào Pipeline. Đầu ra của pipeline là một ma trận số X sạch — sẵn sàng đưa vào model.
Module 3 bắt đầu với regression: bài toán dự đoán giá trị liên tục (giá nhà, doanh số, nhiệt độ, điểm thi). Model đầu tiên — và cũng là model tham chiếu cho mọi model sau — là Linear Regression.
Sau bài này, bạn sẽ:
- Viết được phương trình Linear Regression cho 1 feature và n feature.
- Hiểu ý nghĩa hình học của
w(slope) vàb(intercept). - Biết MSE đóng vai trò gì và vì sao là loss mặc định.
- Phân biệt hai cách tìm parameter: OLS closed-form và Gradient Descent.
- Liệt kê được 4 giả định của Linear Regression và hệ quả nếu violate.
- Cài đặt được Linear Regression 1 feature bằng list thuần Python (không sklearn).
Sklearn sẽ vào ở Bài 16. Bài này tập trung vào công thức và ý nghĩa — nền tảng để hiểu mọi model regression còn lại.
Linear Regression là gì
Linear Regression là model dự đoán giá trị liên tục (real-valued target) từ một hoặc nhiều feature, với giả định: target là tổ hợp tuyến tính của các feature cộng với một số hạng tự do.
"Tuyến tính" ở đây có nghĩa kỹ thuật: tuyến tính theo parameter. Mỗi feature được nhân với một weight, các tích cộng lại, cộng thêm bias. Không có lũy thừa, không có nhân chéo, không có hàm phi tuyến quanh feature.
Output của model là một số thực ŷ — ước lượng của target thật y. Model học bằng cách điều chỉnh weight và bias sao cho ước lượng gần với target trên dataset huấn luyện. Cách định nghĩa "gần" chính là loss function, sẽ bàn ở mục 6.
Linear Regression có 2 đặc tính khiến nó đáng học trước mọi model khác:
- Closed-form solution tồn tại: với loss MSE, có công thức ma trận tính trực tiếp parameter tối ưu — không cần iterate.
- Diễn giải được: mỗi weight
w_itrả lời câu hỏi "featurex_ităng 1 đơn vị thìydự đoán đổi bao nhiêu, khi các feature khác giữ nguyên".
Single feature — phương trình đường thẳng
Trường hợp đơn giản nhất: 1 feature x, 1 target y. Model là một đường thẳng trong mặt phẳng:
Trong đó:
- \( \hat{y} \) — giá trị dự đoán (đọc là "y hat").
- \( w \) — weight, còn gọi là hệ số góc (slope) hoặc coefficient.
- \( b \) — bias, còn gọi là intercept — giá trị \( \hat{y} \) khi \( x = 0 \).
- \( x \) — feature đầu vào.
Phương trình này chính là phương trình đường thẳng từ toán phổ thông \( y = ax + b \), chỉ đổi ký hiệu để khớp với quy ước ML: w thay cho a, và thêm dấu mũ trên y để phân biệt giá trị dự đoán với giá trị thực.
"Học" một Linear Regression 1 feature có nghĩa: tìm cặp số \( (w, b) \) sao cho đường thẳng đi gần nhất các điểm dữ liệu — định nghĩa "gần nhất" sẽ làm rõ ở mục 6.
Diễn giải hình học của w và b
Vẽ trục x là feature, trục y là target. Mỗi sample (x_i, y_i) là một điểm. Mục tiêu của Linear Regression: tìm đường thẳng "best fit" — đường thẳng tổng sai số nhỏ nhất giữa giá trị dự đoán trên đường và giá trị thực tế của điểm.
Vai trò của \( w \):
- \( w > 0 \) — đường dốc lên:
xtăng thìŷtăng. Quan hệ thuận. - \( w < 0 \) — đường dốc xuống:
xtăng thìŷgiảm. Quan hệ nghịch. - \( w = 0 \) — đường ngang:
xkhông ảnh hưởngŷ. Feature không có giá trị dự đoán tuyến tính. - \( |w| \) lớn — đường dốc đứng, một thay đổi nhỏ của
xkéo theo thay đổi lớn củaŷ.
Vai trò của \( b \): dịch đường lên/xuống. b chính là giao điểm của đường thẳng với trục y (tại x = 0). Trong nhiều bài toán thực tế, x = 0 không có ý nghĩa (vd diện tích nhà = 0), nên giá trị b đứng riêng không quan trọng — nhưng nó vẫn cần thiết để đường thẳng đặt đúng chỗ.
Nhớ: nếu bỏ b (đặt cứng b = 0), đường thẳng phải đi qua gốc toạ độ — đây là ràng buộc rất mạnh và thường sai. Mặc định luôn giữ b tự do.
Multiple features — dạng vector
Dataset thật ít khi có 1 feature. Với n feature \( x_1, x_2, \ldots, x_n \), model trở thành:
\[ \hat{y} = w_1 x_1 + w_2 x_2 + \ldots + w_n x_n + b \]Mỗi feature có weight riêng. Tổng các tích cộng bias ra prediction.
Gói gọn lại dưới dạng vector: đặt \( \mathbf{w} = [w_1, w_2, \ldots, w_n]^T \) và \( \mathbf{x} = [x_1, x_2, \ldots, x_n]^T \), thì:
\[ \hat{y} = \mathbf{w}^T \mathbf{x} + b \]Đây là dot product giữa vector weight và vector feature, cộng bias. Notation này tiện cho 2 lý do:
- Đại số tuyến tính (đã học ở Series 1): mọi tính chất của dot product áp dụng được.
- Code:
w @ x + btrong NumPy / PyTorch là một dòng, không cần loop trên từng feature.
Hình học: với n = 2, model là một mặt phẳng trong không gian 3D (\( x_1, x_2, \hat{y} \)). Với n tổng quát, model là một siêu phẳng (hyperplane) trong không gian \( (n+1) \) chiều. Khái niệm "đường thẳng" tổng quát hoá lên thành hyperplane, nhưng tính chất tuyến tính theo parameter vẫn giữ nguyên.
Loss function — MSE
Để "học", model cần một thước đo định lượng độ tệ của một cặp parameter \( (\mathbf{w}, b) \). Đó là loss function. Loss mặc định của Linear Regression là Mean Squared Error (MSE):
\[ L(\mathbf{w}, b) = \frac{1}{n} \sum_{i=1}^n (y_i - \hat{y}_i)^2 = \frac{1}{n} \sum_{i=1}^n \left( y_i - (\mathbf{w}^T \mathbf{x}_i + b) \right)^2 \]Trong đó n là số sample, \( y_i \) là target thực, \( \hat{y}_i \) là prediction.
Bản chất MSE đã học ở Series 1 B26. Ngắn gọn ba lý do dùng MSE cho Linear Regression:
- Bình phương — phạt sai số lớn nặng hơn sai số nhỏ (1 sai số 10 đơn vị = 100 sai số 1 đơn vị về tổng phạt). Phù hợp khi outlier hiếm và cần dự đoán đúng đa số.
- Trung bình — chuẩn hoá theo kích thước dataset; loss của 1000 sample không tự nhiên to gấp 100 lần loss của 10 sample.
- Khả vi mọi nơi và lồi — gradient đẹp, có cực tiểu toàn cục duy nhất → đảm bảo tìm được optimum (xem mục 7–8).
Lưu ý: MSE rất nhạy outlier (1 sai số 100 đơn vị = 10.000 vào loss). Khi data nhiều outlier, đổi sang MAE (Mean Absolute Error) hoặc Huber loss; sẽ bàn ở Bài 17.
Tìm parameter tối ưu — OLS closed-form
Mục tiêu: tìm \( \mathbf{w}, b \) tối thiểu hoá \( L(\mathbf{w}, b) \). Vì MSE lồi và khả vi, có hai con đường: closed-form và iterative.
OLS (Ordinary Least Squares) là cách closed-form. Gói bias vào weight bằng thủ thuật: thêm cột toàn 1 vào ma trận thiết kế X (kích thước n × (d+1) nếu data có d feature). Đặt \( \mathbf{w}' = [w_1, \ldots, w_d, b]^T \). Loss viết gọn:
Lấy gradient theo \( \mathbf{w}' \), cho bằng 0, giải ra:
\[ \hat{\mathbf{w}'} = (X^T X)^{-1} X^T \mathbf{y} \]Công thức này gọi là normal equation. Đây là nghiệm đúng của bài toán — không có sai số do iterate.
Ưu điểm:
- 1 phép tính, không cần tune learning rate hay số epoch.
- Nghiệm tối ưu chính xác (tuỳ độ ổn định số học).
Yêu cầu và hạn chế:
- \( X^T X \) phải khả nghịch — đồng nghĩa các cột feature độc lập tuyến tính. Nếu có multicollinearity hoàn hảo (vd 2 feature trùng nhau, hoặc OHE không drop "first" với linear regression), ma trận singular → công thức không tính được. Sklearn dùng pseudo-inverse để tránh lỗi nhưng coefficient không identifiable.
- Chi phí tính \( (X^T X)^{-1} \) là \( O(d^3) \). Với d vài chục → vài trăm feature thì OK; d hàng chục nghìn → rất chậm và tốn RAM.
- Cần load toàn bộ
Xvào RAM — không phù hợp dataset streaming hoặc rất lớn.
Trong thực tế sklearn không nhân (X^T X)^{-1} trực tiếp — nó dùng SVD decomposition ổn định số học hơn. Kết quả về mặt toán học vẫn là OLS.
Tìm parameter tối ưu — Gradient Descent
Cách thứ hai: Gradient Descent (đã học Series 1 B27). Tóm tắt: bắt đầu từ một \( \mathbf{w} \) ngẫu nhiên, lặp cập nhật theo hướng ngược gradient của loss đến khi hội tụ:
\[ \mathbf{w} \leftarrow \mathbf{w} - \eta \, \nabla_{\mathbf{w}} L \]Với \( \eta \) là learning rate (bước cập nhật) và \( \nabla_{\mathbf{w}} L \) là gradient của loss theo weight.
Với MSE và Linear Regression, gradient có dạng đóng:
\[ \nabla_{\mathbf{w}} L = -\frac{2}{n} X^T (\mathbf{y} - X \mathbf{w}) \]Ưu điểm so với OLS:
- Không cần nghịch đảo ma trận — scale tốt khi n hoặc d rất lớn.
- Có biến thể mini-batch và stochastic (
SGDRegressor) cập nhật từng batch nhỏ — chạy được với data không vừa RAM. - Áp dụng được cho bất cứ model nào có loss khả vi — không chỉ Linear Regression.
Hạn chế:
- Phải tune \( \eta \): quá lớn → diverge, quá nhỏ → hội tụ chậm.
- Nghiệm là xấp xỉ, phụ thuộc số iteration và tiêu chí dừng.
- Với feature chưa scale, GD hội tụ rất chậm hoặc lệch — đây là một lý do quan trọng để làm Module 2 trước.
Quy tắc chọn:
- Dataset n < 10⁵, d < 10³ → OLS (sklearn
LinearRegression) nhanh và chính xác. - Dataset rất lớn, streaming, hoặc cần online learning → GD (
SGDRegressor, hoặc tự viết).
Các giả định của Linear Regression
Linear Regression không chỉ là phương trình — nó đi kèm 4 giả định về data. Các giả định này quan trọng cho inference (test giả thuyết, confidence interval, p-value), ít quan trọng hơn cho predict.
- Linearity — quan hệ giữa feature và target thật sự là tuyến tính (hoặc tuyến tính sau biến đổi như log, sqrt). Nếu quan hệ thật là bậc 2 hoặc parabola, Linear Regression sẽ underfit.
- Independence — các sample độc lập với nhau. Giả định này thường vỡ với time series (sample t phụ thuộc t-1) → cần model riêng cho chuỗi thời gian.
- Homoscedasticity — phương sai của residual (\( y - \hat{y} \)) không đổi theo \( x \). Nếu phương sai phình to khi \( x \) tăng (heteroscedasticity), MSE đánh giá sai trọng số các vùng → coefficient bị thiên lệch về vùng phương sai lớn.
- Normality — residual phân phối chuẩn. Cần thiết để tính p-value và confidence interval cho coefficient. Không bắt buộc cho prediction.
Khi violate: model vẫn predict được, nhưng các con số "thống kê" đi kèm (p-value, CI) không tin được. Diagnosis thông thường:
- Plot residual theo \( \hat{y} \) — nếu thấy hình "phễu" → heteroscedasticity.
- Plot residual theo từng feature — nếu thấy hình cong → quan hệ phi tuyến, cần thêm term polynomial.
- Q-Q plot residual — kiểm tra normality.
- Durbin–Watson test — kiểm tra autocorrelation của residual.
Khi nào nên dùng Linear Regression
- Quan hệ feature–target gần tuyến tính — sau khi inspect bằng scatter plot hoặc correlation matrix.
- Cần diễn giải — mỗi coefficient trả lời câu hỏi "tăng 1 unit feature thì target đổi bao nhiêu". Quan trọng trong các domain regulated (tài chính, y tế, bảo hiểm).
- Dataset nhỏ–trung bình — Linear Regression chỉ học d + 1 parameter, ít overfit hơn model phức tạp khi data ít.
- Baseline — luôn nên fit Linear Regression trước khi thử model phức tạp. Nếu Random Forest / XGBoost / NN không vượt được baseline đáng kể, vấn đề thường ở feature chứ không phải model.
- Cần inference — khi đề bài là "feature nào ảnh hưởng mạnh nhất?" thay vì "predict giá trị mới", Linear Regression với p-value của
statsmodelslà lựa chọn chuẩn.
Giới hạn cần biết
- Không fit được quan hệ phi tuyến — không thể nắm được parabola, exponential, sin/cos. Giải pháp: thêm feature dẫn xuất (\( x^2, x^3, \log x, \sqrt{x} \)) hoặc dùng Polynomial Regression (Bài 20). Polynomial Regression vẫn là Linear Regression — chỉ khác ở chỗ feature đã được biến đổi trước.
- Rất nhạy với outlier — vì MSE phạt sai số bình phương, 1 outlier kéo lệch đường thẳng. Giải pháp: dùng MAE/Huber, hoặc xử lý outlier trước (Bài 12).
- Multicollinearity — feature tương quan cao làm
X^T Xgần singular. Coefficient không ổn định: thay đổi nhỏ ở data có thể đảo dấu coefficient. Giải pháp: Ridge / Lasso (Bài 21) — thêm regularization để ổn định. - Không capture được interaction — model giả định feature đóng góp độc lập. Nếu \( y \) thật phụ thuộc \( x_1 \cdot x_2 \), phải tự thêm cột interaction.
- Extrapolation nguy hiểm — đường thẳng kéo dài vô tận. Predict với \( x \) ngoài range train có thể cho giá trị vô lý.
Use case thực tế
- Giá nhà ~ diện tích, số phòng, khoảng cách trung tâm — bài toán mẫu của mọi khoá ML. Mỗi coefficient nói "thêm 1 m² thì giá tăng bao nhiêu triệu".
- Doanh số ~ marketing spend từng kênh — Linear Regression đa biến cho marketing mix modelling. Coefficient là marginal ROI theo kênh.
- Điểm thi ~ giờ học, giờ ngủ, số buổi vắng — bài toán giáo dục cổ điển, dataset có sẵn trong scikit-learn examples.
- Baseline cho time-series forecasting — fit Linear Regression theo trend + dummy variables cho mùa vụ. Tốt cho dự báo ngắn hạn với data có xu hướng tuyến tính.
- Calibration model output — đôi khi output của model phức tạp lệch hệ thống; fit thêm 1 Linear Regression nhỏ \( \hat{y}_{calib} = a \hat{y} + b \) để hiệu chỉnh.
Regression vs Classification
Hai nhóm bài toán supervised khác nhau ở kiểu của target:
- Regression: \( y \) liên tục — số thực, có thứ tự và khoảng cách. Vd: giá, doanh số, điểm.
- Classification: \( y \) rời rạc — nhãn thuộc tập hữu hạn. Vd: spam/ham, loài hoa, chữ số 0–9.
Linear Regression giải bài đầu. Bài thứ hai có model riêng — Logistic Regression (Bài 22) — và đây là điểm hay gây nhầm: Logistic Regression có chữ "Regression" trong tên nhưng giải classification. Lý do: nó dùng phương trình tuyến tính \( \mathbf{w}^T \mathbf{x} + b \) bên trong, sau đó bọc qua hàm sigmoid để ra xác suất trong khoảng \( [0, 1] \).
Quy tắc dễ nhớ: nhìn vào \( y \). Liên tục → regression model. Rời rạc → classification model. Không phán đoán qua tên model.
Demo công thức với data đơn giản
Hai ví dụ minh hoạ trực tiếp công thức closed-form cho 1 feature. Với 1 feature, OLS rút gọn thành:
\[ w = \frac{\sum_{i=1}^n (x_i - \bar{x})(y_i - \bar{y})}{\sum_{i=1}^n (x_i - \bar{x})^2}, \quad b = \bar{y} - w \bar{x} \]Trong đó \( \bar{x}, \bar{y} \) là mean của x và y.
Ví dụ 1 — data thẳng hoàn hảo. Ba điểm \( (1, 2), (2, 4), (3, 6) \). Tất cả thẳng hàng, đường thật đi qua gốc với slope 2.
Tính:
- \( \bar{x} = 2, \bar{y} = 4 \).
- Tử số: \( (1-2)(2-4) + (2-2)(4-4) + (3-2)(6-4) = 2 + 0 + 2 = 4 \).
- Mẫu số: \( (1-2)^2 + (2-2)^2 + (3-2)^2 = 1 + 0 + 1 = 2 \).
- \( w = 4 / 2 = 2 \), \( b = 4 - 2 \cdot 2 = 0 \).
Kết quả \( \hat{y} = 2x + 0 \) — đường khớp tuyệt đối, MSE = 0.
Ví dụ 2 — data có nhiễu. Ba điểm \( (1, 2.1), (2, 3.9), (3, 6.2) \). Đường thật quanh \( y = 2x \) nhưng không khớp hoàn toàn.
Tính:
- \( \bar{x} = 2, \bar{y} = (2.1 + 3.9 + 6.2)/3 \approx 4.0667 \).
- Tử số: \( (-1)(2.1 - 4.0667) + (0)(3.9 - 4.0667) + (1)(6.2 - 4.0667) = 1.9667 + 0 + 2.1333 = 4.1 \).
- Mẫu số: \( 1 + 0 + 1 = 2 \).
- \( w = 4.1 / 2 = 2.05 \), \( b = 4.0667 - 2.05 \cdot 2 = -0.0333 \).
Kết quả \( \hat{y} = 2.05 x - 0.0333 \). Model tìm được đường gần nhất theo MSE — không khớp tuyệt đối nhưng tổng bình phương sai số nhỏ nhất.
Code Python — implement từ list thuần
Implement Linear Regression 1 feature bằng Python list thuần — không NumPy, không sklearn. Mục tiêu: thấy rõ công thức biến thành code.
def fit_linear_regression(x, y):
"""OLS 1 feature, dùng công thức closed-form."""
n = len(x)
x_mean = sum(x) / n
y_mean = sum(y) / n
numerator = sum((x[i] - x_mean) * (y[i] - y_mean) for i in range(n))
denominator = sum((x[i] - x_mean) ** 2 for i in range(n))
if denominator == 0:
raise ValueError("Tất cả x giống nhau, không định nghĩa được slope")
w = numerator / denominator
b = y_mean - w * x_mean
return w, b
def predict(x, w, b):
return [w * xi + b for xi in x]
def mse(y_true, y_pred):
n = len(y_true)
return sum((y_true[i] - y_pred[i]) ** 2 for i in range(n)) / n
# Test ví dụ 1: data thẳng hoàn hảo
x1 = [1, 2, 3]
y1 = [2, 4, 6]
w1, b1 = fit_linear_regression(x1, y1)
print(f"Vi du 1: w={w1}, b={b1}")
print(f" MSE: {mse(y1, predict(x1, w1, b1)):.6f}")
# Vi du 1: w=2.0, b=0.0
# MSE: 0.000000
# Test ví dụ 2: data có nhiễu
x2 = [1, 2, 3]
y2 = [2.1, 3.9, 6.2]
w2, b2 = fit_linear_regression(x2, y2)
print(f"Vi du 2: w={w2:.4f}, b={b2:.4f}")
print(f" MSE: {mse(y2, predict(x2, w2, b2)):.6f}")
# Vi du 2: w=2.0500, b=-0.0333
# MSE: 0.005000
Preview Bài 16 — verify với sklearn:
import numpy as np
from sklearn.linear_model import LinearRegression
X = np.array([[1], [2], [3]]) # sklearn cần X shape (n, d)
y = np.array([2.1, 3.9, 6.2])
model = LinearRegression()
model.fit(X, y)
print(f"sklearn: w={model.coef_[0]:.4f}, b={model.intercept_:.4f}")
# sklearn: w=2.0500, b=-0.0333
print(model.predict(np.array([[4]]))) # [8.1667]
Kết quả khớp công thức tự cài. Sklearn đứng giữa với bạn để xử lý n feature, dataset lớn, sparse input và edge cases về ổn định số học — nhưng bản chất toán vẫn là OLS bạn vừa code.
Bài tập thực hành
Bài 1 — Tính bằng tay. Dataset "hours studied vs exam score":
hours = [2, 3, 5, 7, 9]
score = [50, 60, 70, 85, 95]
Yêu cầu: tính \( \bar{x}, \bar{y} \), sau đó tính \( w \) và \( b \) bằng công thức closed-form (không dùng sklearn). Viết ra phương trình \( \hat{y} \) cuối cùng.
Bài 2 — Verify với sklearn. Dùng cùng data ở Bài 1, fit LinearRegression của sklearn. So sánh model.coef_[0] với \( w \) bạn tự tính, model.intercept_ với \( b \). Sai khác có nên có không? Tại sao?
Bài 3 — Diễn giải coefficient. Với \( w \) và \( b \) ở Bài 1, trả lời:
- Học thêm 1 giờ kỳ vọng tăng bao nhiêu điểm?
- Nếu không học giờ nào (\( x = 0 \)), model dự đoán điểm bao nhiêu? Con số này có hợp lý trong thực tế không?
- Predict điểm cho học sinh học 6 giờ. Predict điểm cho học sinh học 20 giờ — có nên tin con số này không?
Bài 4 — MSE và outlier. Thêm 1 outlier vào dataset Bài 1: hours = [..., 4], score = [..., 30] (học 4 giờ nhưng được 30 điểm — có thể vì lý do khác). Refit và so sánh \( w, b \) mới với cũ. Quan sát: outlier kéo đường về phía nào? Vì sao MSE bị "lừa"?
Bài 5 — Gradient Descent. Implement fit_linear_regression_gd(x, y, lr=0.01, epochs=1000) dùng GD thay vì closed-form. Khởi tạo \( w = 0, b = 0 \), cập nhật theo công thức gradient. So sánh kết quả với bài 1 — có khớp không? Thử các lr khác nhau (0.001, 0.01, 0.1, 1.0), quan sát hội tụ.
Gợi ý đáp án Bài 3: với hours = [2, 3, 5, 7, 9], score = [50, 60, 70, 85, 95] → \( w \approx 6.357, b \approx 37.5 \). Học thêm 1 giờ tăng ~6.36 điểm. Tại \( x = 0 \), model dự đoán 37.5 điểm — về mặt thống kê chỉ là intercept khớp đường thẳng; thực tế "không học" hiếm khi sinh ra điểm cao như vậy, đây là cảnh báo về extrapolation ngoài range train. Học 6 giờ → \( \hat{y} \approx 75.6 \) điểm, OK vì 6 nằm trong khoảng [2, 9]. Học 20 giờ → \( \hat{y} \approx 164.6 \) điểm — không tin được, ngoài thang điểm 100.
Bài tiếp theo
Bài 16: Train Linear Regression với sklearn — code đầu tiên — chuyển công thức của bài này thành code production: LinearRegression.fit(), đọc coef_ và intercept_, predict trên test set, và đặt model vào Pipeline cùng preprocessor đã build ở Bài 14.
Tài liệu tham khảo
- scikit-learn — Linear Models: Ordinary Least Squares
- scikit-learn — LinearRegression API reference
- scikit-learn — SGDRegressor cho Gradient Descent
- statsmodels — Linear Regression với p-value và confidence interval
- Wikipedia — Ordinary Least Squares
- Wikipedia — Gauss–Markov theorem (giả định của OLS)
- Gareth James et al. — An Introduction to Statistical Learning (Chương 3: Linear Regression)
