import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
Học giám sát (Supervised Learning) và Loss Function¶
Mục tiêu trong nhiệm vụ học tập có giám sát (supervised learning) là tạo ra một mô hình (model) mà chúng tôi có thể sử dụng để dự đoán giá trị của một nhãn (hoặc phản hồi) (a label (or response)) $y$ các giá trị đã cho cho một tập hợp các tính năng (hoặc bộ dự đoán) (features (or predictors)), $x^{(1)}, x^{(2)}, ..., x^{(p)}$. Mô hình này thường được đại diện bởi một hàm predict().
Khi chúng tôi chọn một thuật toán học tập (learning algorithm), chúng tôi đang chọn một cách hiệu quả một lớp mô hình mà chúng tôi sẽ xem xét cho nhiệm vụ cụ thể của chúng tôi. Tập hợp các mô hình được phép này được gọi là không gian giả thuyết (hypothesis space) của chúng tôi. Thuật toán học tập của chúng tôi sẽ tìm kiếm trong không gian giả thuyết để tìm ra mô hình hoạt động tốt nhất trên dữ liệu đào tạo của chúng tôi (training data). Để xác định mô hình nào từ không gian giả thuyết (hypothesis space) là "tốt nhất", chúng ta cần cung cấp thuật toán học tập với một phương pháp cho điểm các mô hình khác nhau. Phương pháp tính điểm như vậy được gọi là hàm mục tiêu (objective function). Một hàm mục tiêu lấy một mô hình và một tập dữ liệu làm đầu vào và tạo ra một điểm số làm đầu ra của nó. Nếu một hàm mục tiêu được xác định theo cách sao cho điểm thấp hơn sẽ tốt hơn, thì chúng ta gọi nó là hàm loss. Mục tiêu của thuật toán học là giảm thiểu sự mất mát của nó trên dữ liệu đào tạo.
Chúng tôi sẽ minh họa các khái niệm này bằng thuật toán học hồi quy tuyến tính.
Hồi quy tuyến tính đơn giản (Simple Linear Regresion)¶
Trong một nhiệm vụ hồi quy tuyến tính đơn giản, chúng tôi có một đặc điểm duy nhất, x, từ đó chúng tôi muốn dự đoán một nhãn liên tục, có giá trị thực y.
- Giả sử rằng tập huấn luyện của chúng ta có $n$ quan sát (observations).
- Biểu thị các giá trị quan sát của đối tượng huấn luyện (dự đoán) (training feature (predictor)) là $x_1, x_2, ..., x_n$.
- Biểu thị các giá trị quan sát của nhãn (biến phản hồi) (label (response variable)) là $y_1, y_2, ..., y_n$.
- Chúng tôi giả định rằng mô hình của chúng tôi có dạng sau: $\large \hat{y} = \hat{\beta}_0 + \hat{\beta}_1 x$.
- Trong mô hình trên, $\hat{\beta}_0$ and $\hat\beta_1$ là các tham số mô hình (model parameters) được học từ dữ liệu đào tạo (training data).
- $\hat{y}$ đại diện cho giá trị dự đoán của $y$ với một giá trị nào đó là $x$.
Đào tạo Mô hình (Training the Model)¶
- Gọi $b_0$ và $b_1$ là một cặp giá trị tham số (không nhất thiết phải tối ưu (not necessarily optimal)) được sử dụng để xác định mô hình $\large \hat{y} = {b}_0 + {b}_1 x$.
- Đối với mỗi quan sát huấn luyện $(x_i, y_i)$, hãy đặt $\large\hat{y}_i = b_0 + b_1 x_i$.
- Với mỗi $i$, hãy tính sai số (còn lại) (error (residual)) $\large\hat{e}_i = \hat{y}_i - y_i$.
- Mục tiêu của thuật toán là tìm các giá trị tham số giảm thiểu hàm mất mát Tổng bình phương (find the parameter values that minimize the Sum of Squared Errors loss function), được cho bởi: $ \large SSE = \sum \hat{e}_i^2 $
- Chúng tôi sẽ biểu thị các giá trị tham số tối ưu bằng $\hat{\beta}_0$ and $\hat{\beta}_1$.
%matplotlib inline
%run -i snippets/snippet04.py
<Figure size 396x396 with 0 Axes>
SLR với Scikit-Learn¶
Scikit-Learn là một thư viện chứa các triển khai của nhiều thuật toán học máy, cũng như các công cụ hữu ích để đánh giá mô hình, xử lý dữ liệu và tạo tập dữ liệu tổng hợp. Chúng tôi sẽ sử dụng gói này rộng rãi trong lớp này.
Trong bài học này, chúng tôi sẽ minh họa cách sử dụng Scikit-Learn để xây dựng mô hình hồi quy tuyến tính. Chúng tôi bắt đầu bằng cách tạo lại tập dữ liệu được sử dụng trong bản demo ở trên.
# Generate Data
np.random.seed(164) #tạo ra bộ số ngẫu nhiên nhưng giống nhau
x = np.random.uniform(low=0, high=10, size=12)
#print("x:",x)
y = 5 + 1.4 * x + np.random.normal(loc=0, scale=2.5, size=12)
#print("y:",y)
# The features need to be stored in a 2D array or DataFrame
X = x.reshape(12,1)
print(X.shape)
print(y.shape)
(12, 1) (12,)
Bây giờ chúng ta sẽ sử dụng lớp LinearRegression từ Scikit-Learn để tạo mô hình SLR.
from sklearn.linear_model import LinearRegression
# We create an instance of the LinearRegression() class.
# Then we call its fit() method.
mod = LinearRegression()
mod.fit(X,y)
# We print the model parameters.
print('Intercept:', mod.intercept_)
print('Slope:', mod.coef_)
Intercept: 7.175724099149425 Slope: [1.10640235]
Chúng tôi sẽ vẽ tập dữ liệu, cùng với đường biểu diễn mô hình.
b = mod.intercept_
m = mod.coef_[0]
plt.close()
plt.scatter(x,y)
plt.plot([0,10],[m*0 + b, m*10 + b], c='r')
plt.xlim([0,10])
plt.ylim([0,25])
plt.xlabel('x')
plt.ylabel('y')
plt.show()
Tạo Dự đoán (Generating Predictions)¶
Mô hình Scikit-Learn được trang bị một phương pháp predict có thể được sử dụng để tạo dự đoán (generate predictions). Chúng tôi sẽ sử dụng phương pháp này để tìm các giá trị y được dự đoán cho mô hình của chúng tôi chox = 2, x = 5 vàx = 8.
Xnew = np.array([2, 5, 8])
print(Xnew.shape)
(3,)
Hàm dự đoán yêu cầu một mảng 2D làm đầu vào, vì vậy chúng tôi sẽ định hình lại Xnew.
Xnew = Xnew.reshape((3,1))
print(Xnew.shape)
(3, 1)
print(mod.predict(Xnew))
[ 9.38852881 12.70773587 16.02694293]
Chấm điểm Mô hình (Scoring the Model)¶
Chúng tôi biết rằng các giá trị tham số đã được chọn để giảm thiểu SSE cho dữ liệu đào tạo đã cho. Hãy tính SSE cho mô hình chúng ta đã tạo. Điều này sẽ yêu cầu chúng tôi sử dụng phương pháp predict được tích hợp trong mô hình của chúng tôi.
y_hat = mod.predict(X)
residuals = y - y_hat
SSE = np.sum(residuals**2)
print('Training SSE:', SSE)
Training SSE: 29.739546986084278
r-Squared¶
Khi làm việc với hồi quy tuyến tính, các giá trị tham số tối ưu được xác định bằng cách tối thiểu hóa hàm mục tiêu SSE. Tuy nhiên, một giá trị khác thường được sử dụng để đánh giá chất lượng của mô hình hồi quy (regression model). Phương pháp tính điểm thay thế này được gọi là giá trị r-squared value. Nó được định nghĩa như sau:
$ \large SST = \sum (y_i - \bar y ) ^2 $
$ \large SSE = \sum \hat{e}_i^2 = \sum (y_i - \hat {y}_i ) ^2 $
$ \large r^2 = 1 - \frac{SSE}{SST}$
Vì SST là một hằng số cho dữ liệu đào tạo được cung cấp, việc giảm thiểu SSE tương đương với việc tối đa hóa $r^2$. Điểm do $r^2$ cung cấp có hai lợi thế so với SSE:
- Giá trị $r^2$ được "chuẩn hóa" ("normalized") để luôn nằm trong khoảng từ 0 đến 1. Giá trị gần bằng 1 cho biết rằng mô hình của chúng tôi cung cấp dữ liệu rất phù hợp.
- Giá trị $r^2$ có cách diễn giải hữu ích không có trong SSE. Chúng ta có thể coi $r^2$ là báo cáo tỷ lệ phương sai trong các nhãn huấn luyện đã được mô hình của chúng ta tính đến.
Bây giờ chúng tôi sẽ tính trực tiếp giá trị $r^2$ cho mô hình của chúng tôi.
SST = np.sum((y - np.mean(y))**2)
r2 = 1 - SSE / SST
print(r2)
0.7298814238421224
Các đối tượng Scikit-Learn LinearRegression không có thuộc tínhr_squared, nhưng chúng có chứa một phương thức gọi là score có thể được sử dụng để tính $r^2$.
print(mod.score(X,y))
0.7298814238421224
Multiple Regression¶
Trong một nhiệm vụ hồi quy tuyến tính nhiều, chúng tôi có một số tính năng, $X = [x^{(1)}, x^{(2)}, ..., x^{(p)}]$, từ đó chúng tôi muốn dự đoán một nhãn liên tục, có giá trị thực y.
- Giả sử rằng tập huấn luyện của chúng ta có $n$ quan sát.
- Biểu thị giá trị của các tính năng đào tạo cho số quan sát $i$ as $X_i = [x^{(1)}_i, x^{(2)}_i, ..., x^{(p)}_i]$.
- Biểu thị giá trị của nhãn để quan sát $i$ as $y_i$.
- Chúng tôi giả định rằng mô hình của chúng tôi có dạng sau: $\large \hat{y} = \hat{\beta}_0 + \hat{\beta}_1 x^{(1)} + \hat{\beta}_2 x^{(2)} ... + \hat{\beta}_p x^{(p)}$.
- Trong mô hình trên, $\hat{\beta}_0$, $\hat{\beta}_1$, ..., $\hat{\beta}_p$ là các tham số mô hình được học từ dữ liệu huấn luyện.
- $\hat{y}$ rđại diện cho giá trị dự đoán của $y$ với một số vectơ đầu vào $X = [x^{(1)}, x^{(2)}, ..., x^{(p)}]$.
Training the Model¶
- Let $b_0, b_1, ..., b_p$ là một bộ giá trị tham số (không nhất thiết phải tối ưu) được sử dụng để xác định một mô hình $\large \hat{y} = {b}_0 + {b}_1 x^{(1)} + {b}_2 x^{(2)} + ... + {b}_p x^{(p)}$.
- Đối với mỗi quan sát đào tạo $(x_i, y_i)$, let $\large\hat{y}_i = {b}_0 + {b}_1 x^{(1)}_i + {b}_2 x^{(2)}_i + ... + {b}_p x^{(p)}_i$.
- Đối với mỗi $i$, hãy tính sai số (còn lại) (error (residual)) $\large\hat{e}_i = \hat{y}_i - y_i$.
- Mục tiêu của thuật toán là tìm các giá trị tham số tối thiểu hóa hàm mục tiêu Tổng của lỗi bình phương, được cho bởi: $ \large SSE = \sum \hat{e}_i^2 $
- Chúng tôi sẽ biểu thị các giá trị tham số tối ưu bằng $\hat{\beta}_0$, $\hat{\beta}_1$, ..., $\hat{\beta}_p$.
Ví dụ với Dữ liệu Tổng hợp¶
Chúng tôi sẽ tạo một tập dữ liệu tổng hợp để minh họa cách hoạt động của hồi quy bội.
np.random.seed(1)
n = 200
x1 = np.random.uniform(0, 10, n)
x2 = np.random.uniform(0, 10, n)
y = 7 + 1.3 * x1 + 2.5 * x2 + np.random.normal(0, 3, n)
df = pd.DataFrame({'x1':x1, 'x2':x2, 'y':y})
df.head()
| x1 | x2 | y | |
|---|---|---|---|
| 0 | 4.170220 | 9.501761 | 38.139430 |
| 1 | 7.203245 | 5.566532 | 30.126983 |
| 2 | 0.001144 | 9.156063 | 27.714854 |
| 3 | 3.023326 | 6.415662 | 24.366173 |
| 4 | 1.467559 | 3.900077 | 18.250087 |
Chúng ta có thể sử dụng lớp LinearRegression từ Scikit-Learn để tạo nhiều mô hình hồi quy.
X = np.hstack([x1.reshape(n,1), x2.reshape(n,1)])
print(X.shape)
mlr = LinearRegression()
mlr.fit(X,y)
print('\nModel intercept:', mlr.intercept_)
print('\nModel coefficients:', mlr.coef_)
print('\nr-Squared:', mlr.score(X,y))
(200, 2) Model intercept: 6.536812277597992 Model coefficients: [1.37737604 2.50605913] r-Squared: 0.8721337623707668
Ví dụ: Dự đoán Giá trị Nhà Trung bình (Predicting Median Home Value)¶
Trong ví dụ này, chúng tôi sẽ làm việc với tập dữ liệu "Nhà ở Boston". Bộ dữ liệu này chứa dữ liệu cho 506 vùng điều tra dân số của Boston từ cuộc điều tra dân số năm 1970.
Tập dữ liệu chứa 19 phần thông tin sau cho mỗi đường điều tra dân số:
town- tên thị trấntract- đường điều tra dân sốlon- kinh độ của đường điều tra dân sốlat- vĩ độ của đường điều tra dân sốmedv- giá trị trung bình của những ngôi nhà có chủ sở hữu tính bằng USD 1000cmedv- giá trị trung bình đã hiệu chỉnh của những ngôi nhà có chủ sở hữu tính bằng USD 1000crim- tỷ lệ tội phạm bình quân đầu người theo thị trấnzn- tỷ lệ đất ở được quy hoạch cho các lô trên 25,000 sq.ftindus- tỷ lệ mẫu đất kinh doanh không bán lẻ trên mỗi thị trấnchas- Biến giả Charles River (= 1 nếu đường giới hạn sông; 0 nếu ngược lại)nox- nồng độ oxit nitric (phần trên 10 triệu)rm- số lượng phòng trung bình trên một ngôi nhàage- tỷ lệ căn hộ có chủ sở hữu được xây dựng trước năm 1940dis- khoảng cách có trọng số đến năm trung tâm việc làm Bostonrad- chỉ số khả năng tiếp cận các đường cao tốc xuyên tâmtax- thuế suất thuế tài sản toàn giá trị trên 10.000 USDptratio- tỷ lệ học sinh-giáo viên theo thị trấnb- 1000(B - 0.63)^2 trong đó B là tỷ lệ người da đen theo thị trấnlstat- phần trăm tình trạng thấp hơn của dân số
Chúng tôi sẽ bắt đầu bằng cách nhập tập dữ liệu từ tệp văn bản, và sau đó xem 10 hàng đầu tiên.
df = pd.read_csv('data/BostonHousingV2.txt', sep='\t')
df.head(n=10)
| town | tract | lon | lat | medv | cmedv | crim | zn | indus | chas | nox | rm | age | dis | rad | tax | ptratio | b | lstat | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | Nahant | 2011 | -70.9550 | 42.2550 | 24.0 | 24.0 | 0.00632 | 18.0 | 2.31 | 0 | 0.538 | 6.575 | 65.2 | 4.0900 | 1 | 296 | 15.3 | 396.90 | 4.98 |
| 1 | Swampscott | 2021 | -70.9500 | 42.2875 | 21.6 | 21.6 | 0.02731 | 0.0 | 7.07 | 0 | 0.469 | 6.421 | 78.9 | 4.9671 | 2 | 242 | 17.8 | 396.90 | 9.14 |
| 2 | Swampscott | 2022 | -70.9360 | 42.2830 | 34.7 | 34.7 | 0.02729 | 0.0 | 7.07 | 0 | 0.469 | 7.185 | 61.1 | 4.9671 | 2 | 242 | 17.8 | 392.83 | 4.03 |
| 3 | Marblehead | 2031 | -70.9280 | 42.2930 | 33.4 | 33.4 | 0.03237 | 0.0 | 2.18 | 0 | 0.458 | 6.998 | 45.8 | 6.0622 | 3 | 222 | 18.7 | 394.63 | 2.94 |
| 4 | Marblehead | 2032 | -70.9220 | 42.2980 | 36.2 | 36.2 | 0.06905 | 0.0 | 2.18 | 0 | 0.458 | 7.147 | 54.2 | 6.0622 | 3 | 222 | 18.7 | 396.90 | 5.33 |
| 5 | Marblehead | 2033 | -70.9165 | 42.3040 | 28.7 | 28.7 | 0.02985 | 0.0 | 2.18 | 0 | 0.458 | 6.430 | 58.7 | 6.0622 | 3 | 222 | 18.7 | 394.12 | 5.21 |
| 6 | Salem | 2041 | -70.9360 | 42.2970 | 22.9 | 22.9 | 0.08829 | 12.5 | 7.87 | 0 | 0.524 | 6.012 | 66.6 | 5.5605 | 5 | 311 | 15.2 | 395.60 | 12.43 |
| 7 | Salem | 2042 | -70.9375 | 42.3100 | 27.1 | 22.1 | 0.14455 | 12.5 | 7.87 | 0 | 0.524 | 6.172 | 96.1 | 5.9505 | 5 | 311 | 15.2 | 396.90 | 19.15 |
| 8 | Salem | 2043 | -70.9330 | 42.3120 | 16.5 | 16.5 | 0.21124 | 12.5 | 7.87 | 0 | 0.524 | 5.631 | 100.0 | 6.0821 | 5 | 311 | 15.2 | 386.63 | 29.93 |
| 9 | Salem | 2044 | -70.9290 | 42.3160 | 18.9 | 18.9 | 0.17004 | 12.5 | 7.87 | 0 | 0.524 | 6.004 | 85.9 | 6.5921 | 5 | 311 | 15.2 | 386.71 | 17.10 |
Hãy kiểm tra các kích thước của DataFrame.
print(df.shape)
(506, 19)
Chúng tôi sẽ sử dụng tập dữ liệu này cho một nhiệm vụ hồi quy, trong đó chúng tôi sẽ cố gắng dự đoán nhãn cmedv bằng cách sử dụng 13 cột cuối cùng làm các tính năng. Bây giờ chúng ta sẽ chuẩn bị mảng tính năng và nhãn của chúng ta.
X = df.iloc[:,6:].values
y = df.iloc[:,5].values
print(X.shape)
print(y.shape)
(506, 13) (506,)
Để đo lường mức độ mô hình của chúng tôi tổng quát hóa thành dữ liệu mới tốt như thế nào, chúng tôi sẽ tạo một phân đoạn đào tạo / kiểm tra dữ liệu của chúng tôi.
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1)
print(X_train.shape)
print(X_test.shape)
(404, 13) (102, 13)
Bây giờ chúng ta sẽ sử dụng lớp LinearRegression để tạo mô hình của chúng ta. Chúng tôi sẽ sử dụng phương pháp score của mô hình được đào tạo của chúng tôi để tính toán giá trị bình phương r (r-Squared) trên tập huấn luyện của chúng tôi (training set), cũng như trên tập kiểm tra của chúng tôi (test set).
model = LinearRegression()
model.fit(X_train, y_train)
print("Training r-Squared:", model.score(X_train, y_train))
print("Testing r-Squared: ", model.score(X_test, y_test))
Training r-Squared: 0.7341832055169145 Testing r-Squared: 0.7639579157366432
Đối tượng mô hình có các thuộc tính chứa các giá trị tham số tối ưu xác định mô hình của chúng ta.
np.set_printoptions(precision=6, suppress=True)
print(model.intercept_)
print(model.coef_)
42.761131545077376 [ -0.110315 0.06 0.021576 2.134697 -19.522247 3.075544 0.004304 -1.536018 0.303108 -0.011639 -0.950799 0.0072 -0.551868]
Sử dụng Tập hợp con các Tính năng Có sẵn (Available Features)¶
Thường là không thể sử dụng tất cả các tính năng có thể có sẵn cho bạn trong một nhiệm vụ học tập có giám sát. Một số lý do tại sao bạn có thể muốn xem xét sử dụng một tập hợp con các tính năng có sẵn là:
- Sử dụng quá nhiều tính năng có thể dẫn đến quá phù hợp (over-fitting).
- Một số tính năng có thể không liên quan.
- Một số tính năng có thể bị thừa (redundant).
- Có quá nhiều tính năng có thể có tác động tiêu cực đến khả năng diễn giải của mô hình của bạn.
- Có thể tốn kém hoặc tốn thời gian để thu thập giá trị cho một số tính năng nhất định.
Hãy đào tạo mô hình MLR thứ hai trên dữ liệu này, nhưng lần này chỉ sử dụng các tính năng rm,ptratio và lstat.
df.iloc[:, [11,16,18]].head()
| rm | ptratio | lstat | |
|---|---|---|---|
| 0 | 6.575 | 15.3 | 4.98 |
| 1 | 6.421 | 17.8 | 9.14 |
| 2 | 7.185 | 17.8 | 4.03 |
| 3 | 6.998 | 18.7 | 2.94 |
| 4 | 7.147 | 18.7 | 5.33 |
Xs = df.iloc[:,[11,16,18]].values
print(Xs.shape)
(506, 3)
Xs_train, Xs_test, y_train, y_test = train_test_split(Xs, y, test_size=0.2, random_state=1)
model_s = LinearRegression()
model_s.fit(Xs_train, y_train)
print("Training r-Squared:", model_s.score(Xs_train, y_train))
print("Testing r-Squared: ", model_s.score(Xs_test, y_test))
Training r-Squared: 0.6739085856095928 Testing r-Squared: 0.6958714532115466
print(model_s.intercept_)
print(model_s.coef_)
23.92724415645076 [ 3.795969 -0.952999 -0.597414]
No comments:
Post a Comment