Tổng số lượt xem trang

Chủ Nhật, 13 tháng 8, 2017

[Intro ML with Python] LINEAR MODELS (MÔ HÌNH TUYẾN TÍNH)

Các mô hình tuyến tính [1] là một trong các mô hình được sử dụng nhiều trong thực tế, và đã được được nghiên cứu rộng rãi trong vài thập kỷ qua, với căn nguyên tồn tại hơn một trăm năm.
Các mô hình tuyến tính là các mô hình tạo ra một dự đoán sử dụng một hàm tuyến tính của các đặc tính đầu vào, chúng tôi sẽ giải thích dưới đây qua nội dung được dịch từ cuốn Introduction to Machine Learning with Python: A Guide for Data Scientists [2].

Linear model for regression (Mô hình hồi quy tuyến tính):

Đối với hồi quy, cách thức dự đoán chung cho một mô hình tuyến tính sẽ như sau:

y^ = w[0]*x[0] + w[1]*x[1] + ... + w[p]*x[p] + b\text{ (1) linear regression}


Ở đây, x[0] đến x[p] biểu thị các đặc tính (features) (ở đây số đặc tính là p) của một điểm dữ liệu, w b là các tham số (paramters) của mô hình được học, Và y^ là dự đoán mà mô hình tạo ra.

Đối với tập dữ liệu có một đặc tính duy nhất, đây là điều bạn có thể nhớ là phương trình của một đường thẳng, toán học ở trung học.

Ở đây, w[0] là độ nghiêng (slope), và b là độ lệch trục y (y-axis offset).
Để có thêm nhiều đặc tính, w chứa các điểm nghiêng (slopes) dọc theo mỗi trục đặc tính. Ngoài ra, bạn có thể nghĩ đến dự đoán được đưa ra như là một trọng số của các tính năng đầu vào, với các trọng số (có thể số âm) được đưa ra bởi các mục của w.

Cố gắng tìm hiểu các tham số w[0] b trên tập dữ liệu sóng một chiều của chúng tôi có thể chỉ ra dòng sau:
mglearn.plots.plot_linear_regression_wave()


w[0]: 0.393906 b: -0.031804

Chúng tôi thêm một tọa độ chéo (coordinate cross) vào biểu đồ (plot) để làm cho nó dễ dàng hơn để hiểu về đường thẳng.
Nhìn vào w[0] chúng ta thấy rằng độ nghiêng khoảng 0.4, mà chúng ta có thể xác nhận bằng mắt trong biểu đồ trên. Ngưỡng chặn là nơi mà đường dự báo nên vượt qua trục y, hơi thấp hơn 0, và bạn cũng có thể xác nhận trong hình ảnh.

Các mô hình hồi quy tuyến tính có thể được mô tả như là các mô hình hồi quy mà dự đoán là một đường thẳng cho đơn đặc tính, một mặt phẳng khi sử dụng hai đặc tính hoặc một siêu mặt phẳng  khi có thêm nhiều đặc tính.

Nếu bạn so sánh các dự đoán được thực hiện bởi đường kẻ màu đỏ với các kết quả được thực hiện bởi KNeigh-borsRegressor trong hình nearest_neighbor_regression (trong bài trước), bằng cách sử dụng một đường thẳng để dự đoán có vẻ rất hạn chế. Dường như tất cả các chi tiết tinh tế của dữ liệu bị mất.

Theo nghĩa này là đúng. Đây là một giả định mạnh mẽ (và có phần không thực tế) rằng mục tiêu y là sự kết hợp tuyến tính của các đặc tính. Nhưng nhìn vào dữ liệu một chiều đưa ra một quan điểm hơi lệch . Đối với bộ dữ liệu có nhiều đặc tính, các mô hình tuyến tính có thể rất mạnh. Đặc biệt, nếu bạn có nhiều đặc tính hơn các điểm huấn luyện dữ liệu, bất kỳ mục tiêu y nào cũng có thể được mô hình hóa một cách hoàn hảo (trên tập huấn luyện) như một hàm tuyến tính (ghi chú này rất dễ dàng để xem nếu bạn biết một số đại số tuyến tính).

Có rất nhiều mô hình tuyến tính khác nhau cho hồi quy. Sự khác biệt giữa các mô hình này là như thế nào mô hình tham số wb được rút ra từ dữ liệu huấn luyện, và làm thế nào mô hình phức tạp có thể được kiểm soát. Bây giờ chúng ta sẽ đi qua các mô hình hồi quy tuyến tính phổ biến nhất.

Linear Regression aka Ordinary Least Squares (Phương pháp bình phương nhỏ nhất):

Hồi quy tuyến tính hoặc Phương pháp bình phương nhỏ nhất (OLS) là đơn giản và là
phương pháp hồi quy tuyến tính cổ điển nhất.
Hồi quy tuyến tính tìm các tham số wb để giảm thiểu sai số bình phương trung bình giữa các dự đoán và mục tiêu hồi quy đích thực y trên tập huấn luyện. Các lỗi bình phương trung bình là tổng các chênh lệch bình phương giữa dự đoán và giá trị đích thực. Hồi quy tuyến tính không có tham số, đó là một lợi ích, nhưng nó cũng không có cách nào để kiểm soát mô hình phức tạp.

Dưới đây là đoạn code mà tạo ra mô hình bạn có thể thấy trong hình XX.

  1. from sklearn.linear_model import LinearRegression
  2. X, y = mglearn.datasets.make_wave(n_samples=60)
  3. X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)
  4. lr = LinearRegression().fit(X_train, y_train)
Các tham số theo độ nghiêng w, cũng được gọi là trọng số hoặc hệ số coefficients) được lưu trữ trong coef_attribute, trong khi bù đắp hoặc hệ số chặn (intercept) b được lưu trữ trong intercept_attribute. [Chú ý: bạn có thể nhận thấy kỳ lạ bởi dấu gạch dưới. Scikit-learn luôn luôn lưu trữ bất cứ thứ gì có nguồn gốc từ dữ liệu huấn luyện trong các thuộc tính kết thúc bằng dấu gạch dưới. Đó là để tách chúng ra khỏi các tham số được thiết lập bởi người dùng.]
  1. print("lr.coef_: %s" % lr.coef_)
  2. print("lr.intercept_: %s" % lr.intercept_)
  3. lr.coef_: [ 0.39390555]
  4. lr.intercept_: -0.0318043430268

Các intercept_attribute luôn luôn là một số float duy nhất, trong khi coef_attribute là một mảng numpy với một mục cho mỗi tính năng đầu vào. Vì chúng ta chỉ có một tính năng đầu vào trong tập dữ liệu, lr.coef_only có một mục duy nhất.
Chúng ta hãy nhìn vào huấn luyện và thành quả:


  1. print("training set score: %f" % lr.score(X_train, y_train))
  2. print("test set score: %f" % lr.score(X_test, y_test))

training set score: 0.670089
test set score: 0.659337

$R^2$ khoảng 0,66 không phải là rất tốt, nhưng chúng ta có thể thấy rằng điểm số về đào tạo và thử nghiệm thiết lập rất gần nhau. Điều này có nghĩa chúng ta có khả năng underfitting, không overfitting. Đối với tập dữ liệu một chiều này, có rất ít nguy cơ overfitting, là mô hình rất đơn giản (hoặc hạn chế).
Tuy nhiên, với bộ dữ liệu cao hơn (có nghĩa là một số lượng lớn các tính năng), mô hình tuyến tính trở nên mạnh hơn, và có một cơ hội cao hơn overfitting.
Chúng ta hãy xem cách LinearRegression thực hiện trên một tập dữ liệu phức tạp hơn, như bộ dữ liệu  Boston Housing. Hãy nhớ rằng tập dữ liệu này có 506 mẫu và 105 đặc tính.
Chúng tôi nạp dữ liệu và chia nó thành một huấn luyện và một bộ kiểm tra. Sau đó, chúng tôi xây dựng mô hình hồi quy tuyến tính như trước đây:
  1. X, y = mglearn.datasets.load_extended_boston()
  2. X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
  3. lr = LinearRegression().fit(X_train, y_train)

Khi so sánh các tập huấn luyện và điểm tập kiểm tra, chúng tôi thấy rằng chúng tôi dự đoán rất chính xác trên tập huấn luyện, nhưng $R^2$ trên tập kiểm tra là tồi tệ hơn nhiều:

  1. print("training set score: %f" % lr.score(X_train, y_train))
  2. print("test set score: %f" % lr.score(X_test, y_test))
training set score: 0.952353
test set score: 0.605775

Đây là một dấu hiệu rõ ràng về sự quá tải (overfitting), và do đó chúng ta nên cố gắng tìm ra một mô hình cho phép chúng ta kiểm soát sự phức tạp.
Một trong những lựa chọn phổ biến nhất để hồi quy tuyến tính chuẩn là Ridge regression, mà chúng ta sẽ xem xét tiếp theo.

Ridge regression (Hồi quy dạng sóng):

Hồi quy Ridge( hồi quy dạng sóng) cũng là một mô hình hồi quy tuyến tính, do đó, công thức mà nó sử dụng để đưa ra dự đoán vẫn là Công thức (1), giống như phương pháp bình phương nhỏ nhất. Trong hồi quy Ridge, các hệ số được lựa chọn không chỉ để họ dự đoán tốt về dữ liệu huấn luyện mà còn có một hạn chế bổ sung. Chúng ta muốn độ lớn của các hệ số càng nhỏ càng tốt; Nói cách khác, tất cả các mục của w nên gần tới 0.
Theo trực giác, điều này có nghĩa là mỗi tính năng nên có càng ít ảnh hưởng đến kết quả càng tốt (có nghĩa là có độ dốc nhỏ), trong khi vẫn dự đoán tốt.
Hạn chế này là một ví dụ về sự chuẩn hóa. Sự chuẩn hóa có nghĩa là hạn chế rõ ràng một mô hình để tránh overfitting. Loại đặc biệt được sử dụng bởi hồi quy Ridge được gọi là quy tắc l2. [Lời nhắn cuối cùng: Về mặt toán học, Ridge bắt lỗi các hệ số l2, hoặc độ dài Euclidean của w.]
Ridge hồi quy được thực thi trong linear_model.Ridge. Chúng ta hãy cùng xem nó làm tốt như thế nào trong bộ dữ liệu mở rộng của Boston:


  1. from sklearn.linear_model import Ridge
  2. ridge = Ridge().fit(X_train, y_train)
  3. print("training set score: %f" % ridge.score(X_train, y_train))
  4. print("test set score: %f" % ridge.score(X_test, y_test))
training set score: 0.886058
test set score: 0.752714

Như bạn thấy, điểm tập huấn của Ridge thấp hơn LinearRegression,trong khi điểm kiểm tra là cao hơn. Điều này phù hợp với mong đợi của chúng ta. Với LinearRegression, chúng ta đã overfitting vào dữ liệu của chúng ra. Ridge là một mô hình hạn chế hơn, vì vậy chúng ta ít có khả năng overfit hơn. Một mô hình ít phức tạp có nghĩa là hiệu suất kém hơn trên tập huấn luyện, nhưng tổng quát hóa tốt hơn.
Vì chúng ta chỉ quan tâm đến hiệu suất tổng quát nên chúng ta nên chọn mô hình Ridge hơn là mô hình LinearRegression.
Mô hình Ridge tạo một trade- off giữa sự đơn giản của mô hình (hệ số gần bằng 0) và hiệu suất của nó trên tập huấn luyện. Tầm quan trọng của mô hình đặt trên đơn giản so với hiệu suất thiết lập đào tạo có thể được xác định bởi người sử dụng, bằng cách sử dụng tham số alpha. Ở trên, chúng ta đã sử dụng tham số mặc định alpha = 1.0.
Không có lý do tại sao điều này sẽ mang lại cho chúng ta trade-off tốt nhất. Tăng các hệ số lực alpha để di chuyển gần tới 0, làm giảm hiệu suất tập huấn, nhưng có thể giúp khái quát hóa.


  1. ridge10 = Ridge(alpha=10).fit(X_train, y_train)
  2. print("training set score: %f" % ridge10.score(X_train, y_train))
  3. print("test set score: %f" % ridge10.score(X_test, y_test))
training set score: 0.788346
test set score: 0.635897

Giảm alpha cho phép hệ số ít bị hạn chế, có nghĩa là chúng ta di chuyển ngay trên hình XXX.
Đối với các giá trị rất nhỏ của alpha, các hệ số hầu như không bị hạn chế, và chúng ta kết thúc với một mô hình tương tự như LinearRegression


  1. ridge01 = Ridge(alpha=0.1).fit(X_train, y_train)
  2. print("training set score: %f" % ridge01.score(X_train, y_train))
  3. print("test set score: %f" % ridge01.score(X_test, y_test))
training set score: 0.928578
test set score: 0.771793

Ở đây, alpha = 0,1 dường như hoạt động tốt. Chúng ta có thể thử giảm alpha thêm nữa để cải thiện khái quát hoá. Bây giờ, chú ý đến tham số alpha tương ứng với sự phức tạp của mô hình như thể hiện trong sự phức tạp của mô hình Figure. Chúng ta sẽ thảo luận các phương pháp để lựa chọn đúng các tham số trong chương 6 (Lựa chọn mô hình).
Chúng ta cũng có thể có được một cái nhìn sâu sắc hơn về cách tham số alpha thay đổi mô hình bằng cách kiểm tra coef_attributes của các mô hình với các giá trị khác nhau của alpha. Một alpha cao hơn có nghĩa là một mô hình hạn chế hơn, vì vậy chúng ta có thể đoán rằng các mục của coef _have nhỏ hơn có cho một giá trị alpha cao hơn giá trị alpha thấp.
Điều này đã được khẳng định trong bảng dưới đây:
  1. plt.title("ridge_coefficients")
  2. plt.plot(ridge.coef_, 'o', label="Ridge alpha=1")
  3. plt.plot(ridge10.coef_, 'o', label="Ridge alpha=10")
  4. plt.plot(ridge01.coef_, 'o', label="Ridge alpha=0.1")
  5. plt.plot(lr.coef_, 'o', label="LinearRegression")
  6. plt.ylim(-25, 25)
  7. plt.legend()

Ở đây, trục x liệt kê các mục của coef_: x = 0 cho biết hệ số liên quan đến tính năng đầu tiên, x = 1 hệ số liên quan đến tính năng thứ hai, và x = 100. Trục y hiển thị giá trị số của giá trị tương ứng của hệ số. Sự mất đi chính ở đây là alpha = 10 (như được hiển thị bởi các chấm màu xanh lá cây), các hệ số chủ yếu là từ khoảng -3 đến 3. Các hệ số cho mô hình ridge với alpha = 1 (như được chỉ ra bởi các chấm màu xanh) , là một cái gì đó lớn hơn. Các chấm đỏ có cường độ lớn hơn vẫn còn, và nhiều điểm chấm xanh, tương ứng với tuyến tính không có bất kỳ sự định chuẩn nào (có thể là alpha = 0) quá lớn thậm chí nằm ngoài biểu đồ.

Lasso:

Một thay thế cho Ridge regression là Lasso. Lasso cũng hạn chế các hệ số để được gần bằng không, tương tự như Ridge regression, nhưng theo một cách hơi khác nhau, được gọi là “l1” quy tắc [chú thích: Các Lasso phạt chuẩn mực l1 của vector hệ số, hay nói cách khác là tổng của các giá trị tuyệt đối của các hệ số].
Hậu quả của quy tắc l1 là khi sử dụng Lasso, một số hệ số chính xác là không.
Điều này có nghĩa một số đặc tính được hoàn toàn bị bỏ qua bởi các mô hình. Điều này có thể được xem như một hình thức lựa chọn đặc tính tự động. Có một số hệ số được chính xác bằng không thường làm cho một mô hình dễ dàng hơn để giải thích, và có thể tiết lộ những đặc tính quan trọng nhất của mô hình của bạn.
Hãy áp dụng lasso vào bộ dữ liệu được mở rộng Boston housing:
  1. from sklearn.linear_model import Lasso
  2. lasso = Lasso().fit(X_train, y_train)
  3. print("training set score: %f" % lasso.score(X_train, y_train))
  4. print("test set score: %f" % lasso.score(X_test, y_test))
  5. print("number of features used: %d" % np.sum(lasso.coef_ != 0))

training set score: 0.293238
test set score: 0.209375
number of features used: 4

Như bạn có thể thấy, Lasso khá tệ, cả về đào tạo và tập kiểm tra. Điều này cho thấy rằng chúng ta đang thiếu hợp lý (underfitting). Chúng tôi thấy rằng nó chỉ sử dụng 4 trong số 105 tính năng. Tương tự như Ridge, Lasso cũng có một tham số quy tắc alphathat điều khiển cách mạnh mẽ hệ số được đẩy về phía zero. Ở trên, chúng tôi sử dụng mặc định của alpha = 1,0. Để giảm bớt underfitting, chúng ta hãy thử giảm alpha:
  1. lasso001 = Lasso(alpha=0.01).fit(X_train, y_train)
  2. print("training set score: %f" % lasso001.score(X_train, y_train))
  3. print("test set score: %f" % lasso001.score(X_test, y_test))
  4. print("number of features used: %d" % np.sum(lasso001.coef_ != 0))

/home/andy/checkout/scikit-learn/sklearn/linear_model/coordinate_descent.py:474: ConvergenceWarnin ConvergenceWarning)
Một alpha thấp hơn cho phép chúng ta phù hợp với một mô hình phức tạp hơn, làm việc tốt hơn trong việc huấn luyện và dữ liệu thử nghiệm. Việc thực hiện được tốt hơn một chút so với sử dụng Ridge, và chúng tôi chỉ đang sử dụng 32 trong số 105 tính năng. Điều này làm cho mô hình này có khả năng dễ hiểu hơn.
Nếu chúng ta đặt thông số alpha quá thấp, chúng tôi một lần nữa loại bỏ ảnh hưởng của quy tắc và kết thúc với một kết quả tương tự như hồi quy tuyến tính (Linear regression).

  1. lasso00001 = Lasso(alpha=0.0001).fit(X_train, y_train)
  2. print("training set score: %f" % lasso00001.score(X_train, y_train))
  3. print("test set score: %f" % lasso00001.score(X_test, y_test))
  4. print("number of features used: %d" % np.sum(lasso00001.coef_ != 0))

/home/andy/checkout/scikit-learn/sklearn/linear_model/coordinate_descent.py:474: ConvergenceWarnin ConvergenceWarning)
Một lần nữa, chúng ta có thể vẽ biểu đồ các hệ số của các mô hình khác nhau, tương tự như Hình ridge_coefficients.
Đối với alpha = 1, với các hệ số cho thấy là các chấm xanh, chúng ta không chỉ thấy rằng hầu hết các hệ số là bằng 0 (mà chúng ta đã biết), nhưng các hệ số còn lại cũng nhỏ về độ lớn. Giảm alpha xuống 0,01 chúng ta nhận được giải pháp được hiển thị dưới dạng các chấm xanh, điều này làm cho hầu hết các tính năng chính xác là bằng 0. Sử dụng alpha = 0.00001, chúng ta có được một mô hình khá không quy tắc, với hầu hết các hệ số khác 0 và cường độ lớn.
Để so sánh, giải pháp tốt nhất Ridge được hiển thị trong teal. Các mô Ridge với alpha = 0,1 có hiệu suất dự đoán tương tự như mô hình Lasso với alpha = 0,01, nhưng sử dụng Ridge, tất cả các hệ số khác 0.
  1. plt.plot(lasso.coef_, 'o', label="Lasso alpha=1")
  2. plt.plot(lasso001.coef_, 'o', label="Lasso alpha=0.01")
  3. plt.plot(lasso00001.coef_, 'o', label="Lasso alpha=0.0001")
  4. plt.plot(ridge01.coef_, 'o', label="Ridge alpha=0.1")
  5. plt.ylim(-25, 25)
  6. plt.legend()

Trên thực tế, Ridge hồi quy thường là sự lựa chọn đầu tiên giữa hai mô hình.
Tuy nhiên, nếu bạn có một số lượng lớn các đặc tính và mong muốn chỉ là một vài trong số họ là quan trọng, Lasso có thể là một lựa chọn tốt hơn. Tương tự, nếu bạn muốn có một mô hình đó là dễ dàng để giải thích, Lasso sẽ cung cấp một mô hình đó là dễ hiểu, vì nó sẽ chỉ chọn một tập hợp con của các đặc tính đầu vào.


0 nhận xét: