Tập hợp các loại hồi quy khác nhau bằng scikit-learn (hoặc bất kỳ khung python nào khác)


27

Tôi đang cố gắng để giải quyết các nhiệm vụ hồi quy. Tôi phát hiện ra rằng 3 mô hình đang hoạt động tốt cho các tập hợp dữ liệu khác nhau: LassoLARS, SVR và Gradient Tree Boosting. Tôi nhận thấy rằng khi tôi đưa ra dự đoán bằng cách sử dụng cả 3 mô hình này và sau đó tạo một bảng 'đầu ra thực' và đầu ra của 3 mô hình của tôi, tôi thấy rằng mỗi lần ít nhất một trong số các mô hình thực sự gần với đầu ra thực, mặc dù có 2 mô hình khác có thể là tương đối xa.

Khi tôi tính toán sai số tối thiểu có thể (nếu tôi dự đoán từ dự đoán 'tốt nhất' cho mỗi ví dụ kiểm tra), tôi nhận được một lỗi nhỏ hơn nhiều so với lỗi của bất kỳ mô hình nào. Vì vậy, tôi nghĩ về việc cố gắng kết hợp các dự đoán từ 3 mô hình khác nhau này thành một loại hòa tấu nào đó. Câu hỏi là, làm thế nào để làm điều này đúng? Tất cả 3 mô hình của tôi đều được xây dựng và điều chỉnh bằng scikit-learn, nó có cung cấp một loại phương pháp nào đó có thể được sử dụng để đóng gói các mô hình thành tập hợp không? Vấn đề ở đây là tôi không muốn chỉ dự đoán trung bình từ cả ba mô hình, tôi muốn thực hiện điều này với trọng số, trong đó trọng số phải được xác định dựa trên các thuộc tính của ví dụ cụ thể.

Ngay cả khi scikit-learn không cung cấp chức năng như vậy, sẽ rất tuyệt nếu ai đó biết cách xử lý thuộc tính này - tìm ra trọng số của từng mô hình cho từng ví dụ trong dữ liệu. Tôi nghĩ rằng nó có thể được thực hiện bởi một bộ hồi quy riêng được xây dựng trên cả ba mô hình này, chúng sẽ thử trọng lượng tối ưu đầu ra cho mỗi 3 mô hình, nhưng tôi không chắc liệu đây có phải là cách tốt nhất để làm việc này không.

Câu trả lời:


32

Trên thực tế, scikit-learnkhông cung cấp một chức năng như vậy, mặc dù nó có thể hơi khó thực hiện. Dưới đây là một ví dụ hoạt động hoàn chỉnh của một bộ hồi quy trung bình như vậy được xây dựng dựa trên ba mô hình. Trước hết, hãy nhập tất cả các gói cần thiết:

from sklearn.base import TransformerMixin
from sklearn.datasets import make_regression
from sklearn.pipeline import Pipeline, FeatureUnion
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.neighbors import KNeighborsRegressor
from sklearn.preprocessing import StandardScaler, PolynomialFeatures
from sklearn.linear_model import LinearRegression, Ridge

Sau đó, chúng ta cần chuyển đổi ba mô hình hồi quy thành máy biến áp. Điều này sẽ cho phép chúng ta hợp nhất các dự đoán của chúng vào một vectơ tính năng duy nhất bằng cách sử dụng FeatureUnion:

class RidgeTransformer(Ridge, TransformerMixin):

    def transform(self, X, *_):
        return self.predict(X)


class RandomForestTransformer(RandomForestRegressor, TransformerMixin):

    def transform(self, X, *_):
        return self.predict(X)


class KNeighborsTransformer(KNeighborsRegressor, TransformerMixin):

    def transform(self, X, *_):
        return self.predict(X)

Bây giờ, hãy xác định hàm xây dựng cho mô hình frankenstein của chúng tôi:

def build_model():
    ridge_transformer = Pipeline(steps=[
        ('scaler', StandardScaler()),
        ('poly_feats', PolynomialFeatures()),
        ('ridge', RidgeTransformer())
    ])

    pred_union = FeatureUnion(
        transformer_list=[
            ('ridge', ridge_transformer),
            ('rand_forest', RandomForestTransformer()),
            ('knn', KNeighborsTransformer())
        ],
        n_jobs=2
    )

    model = Pipeline(steps=[
        ('pred_union', pred_union),
        ('lin_regr', LinearRegression())
    ])

    return model

Cuối cùng, hãy phù hợp với mô hình:

print('Build and fit a model...')

model = build_model()

X, y = make_regression(n_features=10, n_targets=2)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

model.fit(X_train, y_train)
score = model.score(X_test, y_test)

print('Done. Score:', score)

Đầu ra:

Build and fit a model...
Done. Score: 0.9600413867438636

Tại sao phải phức tạp hóa mọi thứ theo cách như vậy? Chà, cách tiếp cận này cho phép chúng tôi tối ưu hóa siêu âm mô hình bằng cách sử dụng các scikit-learnmô-đun tiêu chuẩn như GridSearchCVhoặc RandomizedSearchCV. Ngoài ra, bây giờ có thể dễ dàng lưu và tải từ đĩa một mô hình được đào tạo trước.


Khi sử dụng phương pháp này, có một cách đơn giản để trích xuất thuật toán nào đang được sử dụng khi / phần nào của mỗi thuật toán?
David Hagan

Có lẽ việc xem xét các hệ số của mô hình tuyến tính kết quả ( model.named_steps['lin_regr'].coef_) sẽ cung cấp cho bạn một số thông tin chi tiết về số lượng mỗi mô hình trong một tập hợp đóng góp cho giải pháp cuối cùng.
tạo ra

@constt Bạn có cần sử dụng cross_val_predict trong các mô hình cơ sở của mình không? Có vẻ như mô hình cấp cao nhất của bạn sẽ nhận được tín hiệu quá mức từ các mô hình cơ sở của bạn vì điều này hiện đang được triển khai.
Brian Biên

1
Đây chỉ là một ví dụ bằng chứng về khái niệm, tôi đã không đề cập đến lựa chọn mô hình ở đây. Tôi nghĩ rằng các mô hình như vậy nên được tối ưu hóa toàn bộ, tức là tối ưu hóa các tham số siêu của tất cả các mô hình tích hợp đồng thời sử dụng phương pháp xác thực chéo.
cấu thành

nếu chúng ta đặt n_target = 1 X, y = make_regression(n_features=10, n_targets=1)thì nó sẽ báo lỗi kích thước. bất cứ ai có thể giải thích những gì để làm?
Mohit Yadav

9

Ok, sau khi dành một chút thời gian cho việc googling tôi đã tìm ra cách tôi có thể làm trọng số trong con trăn ngay cả với scikit-learn. Hãy xem xét những điều dưới đây:

Tôi huấn luyện một tập các mô hình hồi quy của mình (như đã đề cập đến SVR, LassoLars và GradientBoostingRegressor). Sau đó, tôi chạy tất cả chúng trên dữ liệu huấn luyện (cùng một dữ liệu được sử dụng để đào tạo cho cả 3 biến hồi quy này). Tôi nhận được các dự đoán cho các ví dụ với từng thuật toán của mình và lưu 3 kết quả này vào khung dữ liệu gấu trúc với các cột 'dự đoánSVR', 'dự đoánLASSO' và 'dự đoánGBR'. Và tôi thêm cột cuối cùng vào datafrane này mà tôi gọi là 'dự đoán' là giá trị dự đoán thực sự.

Sau đó, tôi chỉ đào tạo một hồi quy tuyến tính trên khung dữ liệu mới này:

 #df - dataframe with results of 3 regressors and true output

 from sklearn linear_model
 stacker= linear_model.LinearRegression()
 stacker.fit(df[['predictedSVR', 'predictedLASSO', 'predictedGBR']], df['predicted'])

Vì vậy, khi tôi muốn đưa ra một dự đoán cho ví dụ mới, tôi chỉ chạy riêng 3 biến hồi quy của mình và sau đó tôi thực hiện:

 stacker.predict() 

trên đầu ra của 3 hồi quy của tôi. Và nhận được một kết quả.

Vấn đề ở đây là trung bình tôi đang tìm trọng số tối ưu cho các biến hồi quy, các trọng số sẽ giống nhau cho mỗi ví dụ mà tôi sẽ cố gắng đưa ra dự đoán.

Nếu bất cứ ai có bất kỳ ý tưởng nào về cách thực hiện xếp chồng (trọng số) bằng cách sử dụng các tính năng của ví dụ hiện tại, thật tuyệt khi nghe họ.


Wow, tôi rất thích cách tiếp cận này! Nhưng tại sao bạn lại sử dụng LinearRegression()thay cho LogisticRegression()mô hình?
harrison4

1
@ harrison4 vì tôi đang làm hồi quy, không phân loại nhiệm vụ? Vì vậy, tôi muốn đầu ra 'trọng lượng' từ mỗi mô hình. Dù sao, đây là một cách tiếp cận tồi, một cách tốt được mô tả ở đây: stackoverflow.com/a353170149/3633250
Maksim Khaitovich

Vâng, xin lỗi bạn đã đúng! Nhờ để chia sẻ liên kết!
harrison4

5

Nếu dữ liệu của bạn có các tập hợp con rõ ràng, bạn có thể chạy một thuật toán phân cụm như k-mean và sau đó liên kết từng phân loại với các cụm mà nó hoạt động tốt. Khi một điểm dữ liệu mới đến, sau đó xác định cụm nào trong đó và chạy trình phân loại liên quan.

Bạn cũng có thể sử dụng khoảng cách nghịch đảo từ tâm để lấy một tập các trọng số cho từng phân loại và dự đoán bằng cách sử dụng kết hợp tuyến tính của tất cả các phân loại.


Tôi tìm thấy một bài báo đã thử nghiệm chiến lược này (cùng với việc so sánh một số ý tưởng tương tự): giấy
anthonybell

Ý tưởng thú vị, mặc dù đòi hỏi rất nhiều công việc để ứng dụng nó. Cảm ơn vì giấy!
Maksim Khaitovich

1

Tôi hoàn thành một loại trọng số bằng cách thực hiện như sau, một khi tất cả các mô hình của bạn được đào tạo đầy đủ và hoạt động tốt:

  1. Chạy tất cả các mô hình của bạn trên một tập hợp lớn dữ liệu thử nghiệm chưa thấy
  2. Lưu trữ điểm số F1 trên bộ kiểm tra cho từng lớp, cho từng mẫu
  3. Khi bạn dự đoán với quần thể, mỗi mô hình sẽ cung cấp cho bạn loại có khả năng nhất, do đó, hãy cân nhắc độ tin cậy hoặc xác suất bằng điểm số F1 cho mô hình đó trên lớp đó. Nếu bạn đang xử lý khoảng cách (ví dụ như trong SVM), chỉ cần bình thường hóa khoảng cách để có được sự tự tin chung, sau đó tiến hành với trọng số cho mỗi lớp F1.

Bạn có thể điều chỉnh thêm bộ đồng phục của mình bằng cách đo phần trăm chính xác theo thời gian. Ví dụ, khi bạn có một tập dữ liệu mới lớn, đáng kể, bạn có thể vẽ ngưỡng theo các bước 0,1, ví dụ, so với phần trăm chính xác nếu sử dụng ngưỡng đó để ghi điểm, để có ý tưởng về ngưỡng nào sẽ cung cấp cho bạn, giả sử, đúng 95% cho lớp 1, v.v. Bạn có thể tiếp tục cập nhật bộ kiểm tra và điểm số F1 khi có dữ liệu mới và theo dõi độ trôi, xây dựng lại các mô hình khi ngưỡng hoặc độ chính xác giảm.


1
Điều đó thật thú vị, nhưng nó chỉ hoạt động cho các nhiệm vụ phân loại, theo như tôi thấy, trong khi tôi đang cố gắng giải quyết nhiệm vụ hồi quy. Do đó tôi không thể tính được điểm F1.
Maksim Khaitovich
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.