2016-04-17 23 views
6

Tôi đang cố gắng để chuỗi Tìm kiếm lưới và loại bỏ tính năng đệ quy trong một đường ống bằng cách sử dụng scikit-tìm hiểu.Tìm kiếm lưới với tính năng đệ quy Loại bỏ trong đường ống scikit-tìm hiểu trả về một lỗi

GridSearchCV và RFE với phân loại "trần" hoạt động tốt:

from sklearn.datasets import make_friedman1 
from sklearn import feature_selection 
from sklearn.grid_search import GridSearchCV 
from sklearn.svm import SVR 

X, y = make_friedman1(n_samples=50, n_features=10, random_state=0) 

est = SVR(kernel="linear") 

selector = feature_selection.RFE(est) 
param_grid = dict(estimator__C=[0.1, 1, 10]) 
clf = GridSearchCV(selector, param_grid=param_grid, cv=10) 
clf.fit(X, y) 

Đưa phân loại trong một đường ống trả về một lỗi: RuntimeError: Bộ phân loại không phơi bày "coef_" hoặc "feature_importances_" thuộc tính

from sklearn.datasets import make_friedman1 
from sklearn import feature_selection 
from sklearn import preprocessing 
from sklearn import pipeline 
from sklearn.grid_search import GridSearchCV 
from sklearn.svm import SVR 

X, y = make_friedman1(n_samples=50, n_features=10, random_state=0) 

est = SVR(kernel="linear") 

std_scaler = preprocessing.StandardScaler() 
pipe_params = [('std_scaler', std_scaler), ('clf', est)] 
pipe = pipeline.Pipeline(pipe_params) 

selector = feature_selection.RFE(pipe) 
param_grid = dict(estimator__clf__C=[0.1, 1, 10]) 
clf = GridSearchCV(selector, param_grid=param_grid, cv=10) 
clf.fit(X, y) 

EDIT:

tôi đã nhận ra rằng tôi đã không rõ ràng mô tả vấn đề. Đây là đoạn trích rõ ràng hơn:

from sklearn.datasets import make_friedman1 
from sklearn import feature_selection 
from sklearn import pipeline 
from sklearn.grid_search import GridSearchCV 
from sklearn.svm import SVR 

X, y = make_friedman1(n_samples=50, n_features=10, random_state=0) 

# This will work 
est = SVR(kernel="linear") 
selector = feature_selection.RFE(est) 
clf = GridSearchCV(selector, param_grid={'estimator__C': [1, 10]}) 
clf.fit(X, y) 

# This will not work 
est = pipeline.make_pipeline(SVR(kernel="linear")) 
selector = feature_selection.RFE(est) 
clf = GridSearchCV(selector, param_grid={'estimator__svr__C': [1, 10]}) 
clf.fit(X, y) 

Như bạn thấy, sự khác biệt duy nhất là đặt trình ước lượng vào đường ống. Tuy nhiên, đường ống ẩn các thuộc tính "coef_" hoặc "feature_importances_". Các câu hỏi là:

  1. Có cách nào tốt để giải quyết vấn đề này trong học tập không?
  2. Nếu không, hành vi này có mong muốn vì bất kỳ lý do nào không?

EDIT2:

cập nhật, đoạn làm việc dựa trên các câu trả lời được cung cấp bởi @ Chris

from sklearn.datasets import make_friedman1 
from sklearn import feature_selection 
from sklearn import pipeline 
from sklearn.grid_search import GridSearchCV 
from sklearn.svm import SVR 


class MyPipe(pipeline.Pipeline): 

    def fit(self, X, y=None, **fit_params): 
     """Calls last elements .coef_ method. 
     Based on the sourcecode for decision_function(X). 
     Link: https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/pipeline.py 
     ---------- 
     """ 
     super(MyPipe, self).fit(X, y, **fit_params) 
     self.coef_ = self.steps[-1][-1].coef_ 
     return self 


X, y = make_friedman1(n_samples=50, n_features=10, random_state=0) 

# Without Pipeline 
est = SVR(kernel="linear") 
selector = feature_selection.RFE(est) 
clf = GridSearchCV(selector, param_grid={'estimator__C': [1, 10, 100]}) 
clf.fit(X, y) 
print(clf.grid_scores_) 

# With Pipeline 
est = MyPipe([('svr', SVR(kernel="linear"))]) 
selector = feature_selection.RFE(est) 
clf = GridSearchCV(selector, param_grid={'estimator__svr__C': [1, 10, 100]}) 
clf.fit(X, y) 
print(clf.grid_scores_) 
+0

Tôi sẽ xem xét mã nguồn để kiểm tra xem chuỗi sự kiện nào dẫn đến RuntimeError. Có thể bạn có thể ghi đè lên các thuộc tính của đối tượng trả về có liên quan và chỉ cần thêm lại vào các biến - ví dụ, nếu chúng giống nhau khi được trả về từ SVR(). Trong mọi trường hợp, make_pipeline() có thể không trả lại cùng một loại đối tượng như SVR(). – noumenal

Trả lời

2

Bạn gặp sự cố với việc sử dụng đường ống.

Một đường ống làm việc như sau:

đối tượng đầu tiên được áp dụng cho dữ liệu khi bạn gọi .fit (x, y) vv Nếu phương pháp đó cho thấy nhiều phương pháp .transform(), điều này được áp dụng và sản lượng này là được sử dụng làm đầu vào cho giai đoạn tiếp theo.

Đường ống có thể có bất kỳ mô hình hợp lệ nào làm đối tượng cuối cùng, nhưng tất cả các mô hình trước đó PHẢI phơi bày phương thức .transform().

Cũng giống như một đường ống - bạn nạp dữ liệu và mỗi đối tượng trong đường ống lấy đầu ra trước đó và thực hiện một phép biến đổi khác trên nó.

Như chúng ta có thể thấy,

http://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.RFE.html#sklearn.feature_selection.RFE.fit_transform

RFE cho thấy một phương pháp biến đổi, và vì vậy nên được bao gồm trong các đường ống chính nó. Ví dụ:

some_sklearn_model=RandomForestClassifier() 
selector = feature_selection.RFE(some_sklearn_model) 
pipe_params = [('std_scaler', std_scaler), ('RFE', rfe),('clf', est)] 

Nỗ lực của bạn có một vài vấn đề. Thứ nhất, bạn đang cố gắng mở rộng một phần dữ liệu của mình. Hãy tưởng tượng tôi có hai phân vùng [1,1], [10,10]. Nếu tôi bình thường hóa bằng giá trị trung bình của phân vùng, tôi sẽ mất thông tin rằng phân vùng thứ hai của tôi cao hơn đáng kể so với giá trị trung bình. Bạn nên mở rộng ở đầu, không phải ở giữa.

Thứ hai, SVR không triển khai phương pháp chuyển đổi, bạn không thể kết hợp nó làm phần tử không cuối cùng trong một đường ống.

RFE có một mô hình phù hợp với dữ liệu và sau đó đánh giá trọng lượng của mỗi đối tượng địa lý.

EDIT:

Bạn có thể bao gồm hành vi này nếu bạn muốn, bằng cách gói các đường ống dẫn sklearn trong lớp học của riêng bạn. Những gì chúng tôi muốn làm là khi chúng tôi phù hợp với dữ liệu, hãy lấy các phương pháp ước tính cuối cùng .coef_ và lưu trữ cục bộ trong lớp dẫn xuất của chúng tôi dưới tên chính xác. Tôi đề nghị bạn nhìn vào mã nguồn trên github vì đây chỉ là lần đầu tiên bắt đầu và kiểm tra lỗi nhiều hơn vv có lẽ sẽ được yêu cầu. Sklearn sử dụng một công cụ trang trí hàm gọi là @if_delegate_has_method, đây sẽ là một điều tiện dụng để thêm vào để đảm bảo phương pháp tổng quát. Tôi đã chạy mã này để chắc chắn rằng nó hoạt động chạy, nhưng không có gì nhiều hơn nữa.

from sklearn.datasets import make_friedman1 
from sklearn import feature_selection 
from sklearn import preprocessing 
from sklearn import pipeline 
from sklearn.grid_search import GridSearchCV 
from sklearn.svm import SVR 

class myPipe(pipeline.Pipeline): 

    def fit(self, X,y): 
     """Calls last elements .coef_ method. 
     Based on the sourcecode for decision_function(X). 
     Link: https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/pipeline.py 
     ---------- 
     """ 

     super(myPipe, self).fit(X,y) 

     self.coef_=self.steps[-1][-1].coef_ 
     return 

X, y = make_friedman1(n_samples=50, n_features=10, random_state=0) 

est = SVR(kernel="linear") 

selector = feature_selection.RFE(est) 
std_scaler = preprocessing.StandardScaler() 
pipe_params = [('std_scaler', std_scaler),('select', selector), ('clf', est)] 

pipe = myPipe(pipe_params) 



selector = feature_selection.RFE(pipe) 
clf = GridSearchCV(selector, param_grid={'estimator__clf__C': [2, 10]}) 
clf.fit(X, y) 

print clf.best_params_ 

nếu có gì không rõ ràng, vui lòng hỏi.

+0

Cảm ơn @ Chris vì câu trả lời của bạn. Tôi không rõ ràng mô tả vấn đề. Tôi đặc biệt tự hỏi làm thế nào để truy cập vào các thuộc tính "coef_" hoặc "feature_importances_" của một bộ ước lượng mà dường như bị ẩn bởi đường ống. – hubi86

+0

địa chỉ chỉnh sửa của tôi ngay bây giờ. Chúc may mắn. – Chris

0

Tôi nghĩ rằng bạn đã có một cách hơi khác nhau xây dựng các đường ống dẫn so với những gì đã được liệt kê trong số pipeline documentation.

Bạn đang tìm kiếm điều này?

X, y = make_friedman1(n_samples=50, n_features=10, random_state=0) 

est = SVR(kernel="linear") 

std_scaler = preprocessing.StandardScaler() 
selector = feature_selection.RFE(est) 
pipe_params = [('feat_selection',selector),('std_scaler', std_scaler), ('clf', est)] 
pipe = pipeline.Pipeline(pipe_params) 

param_grid = dict(clf__C=[0.1, 1, 10]) 
clf = GridSearchCV(pipe, param_grid=param_grid, cv=2) 
clf.fit(X, y) 
print clf.grid_scores_ 

Xem thêm điều này useful example để kết hợp mọi thứ trong đường ống. Đối với đối tượng RFE, tôi chỉ sử dụng official documentation để xây dựng nó với bộ ước lượng SVR của bạn - Tôi sau đó chỉ cần đặt đối tượng RFE vào đường ống theo cách tương tự như bạn đã thực hiện với đối tượng trình chia tỷ lệ và ước tính.

+0

Cảm ơn bạn đã trả lời nhưng giải pháp của bạn hoạt động khác nhau sau đó tôi dự định. Quy trình làm việc của bạn: 1. Trong khi tính năng GridSearchCV được chọn bằng cách sử dụng 'RFE (SVR())' với giá trị mặc định là 'C'. 2. Sau đó, các tính năng được chọn sẽ được chia tỷ lệ. 3. 'SVR()' được gắn với một tham số từ 'param_grid'. Luồng công việc mong muốn của tôi như sau: 1. Trong khi tính năng GridSearchCV được chia tỷ lệ. 2. 'SVR()' được gắn với một tham số từ 'param_grid'. 3. Sau đó, các tính năng có trọng số nhỏ nhất được cắt tỉa từ mô hình. 4. Các bước 1-3 được lặp lại cho đến khi đạt được số lượng tính năng mong muốn. – hubi86

Các vấn đề liên quan