--- breaks: false # false 表示採用 "軟換行規則",即 "換行符號" 不會換到新行。 --- # Scikit-Learn sklearn.ensemble.StackingClassifier ###### tags: `scikit-learn` `sklearn` `python` `machine learning` `ensemble` >[name=Marty.chen ] >[time=Wed, Dec 25, 2019 11:32 AM] >以下範例資料皆來自官方文件 :::danger 官方文件: * [API](https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.StackingClassifier.html#sklearn.ensemble.StackingClassifier) * [User Guide](https://scikit-learn.org/stable/modules/ensemble.html#stacking) ::: ## 說明 Stacked generalization是0.22版新增的功能,可以結合多個分類器或迴歸器做整體學習。按官方文件說明,堆疊起來的估計器會以完整的訓練資料集訓練,而`final_estimator`會以各估計器的output做為input,並以交叉驗證做訓練。 參數`estimators`以list格式來堆疊不同的估計器: ```python >>> from sklearn.linear_model import RidgeCV, LassoCV >>> from sklearn.svm import SVR >>> estimators = [('ridge', RidgeCV()), ... ('lasso', LassoCV(random_state=42)), ... ('svr', SVR(C=1, gamma=1e-6))] ``` `final_estimator`則視實作上的分類或數值而import不同的module,`StackingClassifier`或`StackingRegressor`: ```python >>> from sklearn.ensemble import GradientBoostingRegressor >>> from sklearn.ensemble import StackingRegressor >>> reg = StackingRegressor( ... estimators=estimators, ... final_estimator=GradientBoostingRegressor(random_state=42)) ``` 最後一樣使用實作`StackingClassifier`或`StackingRegressor`的估計器來擬合模型: ```python >>> from sklearn.datasets import load_boston >>> X, y = load_boston(return_X_y=True) >>> from sklearn.model_selection import train_test_split >>> X_train, X_test, y_train, y_test = train_test_split(X, y, ... random_state=42) >>> reg.fit(X_train, y_train) ``` 訓練過程中,如上所述,`estimators`內的估計器是以整個訓練資料集來訓練,而為了泛化性以及避免過擬合,`final_estimator`是以樣本外的資料來訓練,並以[sklearn.model_selection.cross_val_predict](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.cross_val_predict.html#sklearn.model_selection.cross_val_predict)做交叉驗證。 對`StackingClassifier`而言,`estimators`內的output是由`StackingClassifier`的參數`stack_method`來控制。 ```python >>> y_pred = reg.predict(X_test) >>> from sklearn.metrics import r2_score >>> print('R2 score: {:.2f}'.format(r2_score(y_test, y_pred))) R2 score: 0.81 ``` 你也可以用`transform`來取得`estimators`內的output: ```python >>> reg.transform(X_test[:5]) array([[28.78..., 28.43... , 22.62...], [35.96..., 32.58..., 23.68...], [14.97..., 14.05..., 16.45...], [25.19..., 25.54..., 22.92...], [18.93..., 19.26..., 17.03... ]]) ``` 如果設置`stack_method_='predict_proba'`,而且是一個二分類問題的話,則第一個column在訓練過程中會被拿掉,這是為了避免共線性的問題。 你也可以巢狀堆疊你的估計器,也就說,`final_estimator`也可以是`StackingClassifier`或`StackingRegressor`: ```python >>> final_layer = StackingRegressor( ... estimators=[('rf', RandomForestRegressor(random_state=42)), ... ('gbrt', GradientBoostingRegressor(random_state=42))], ... final_estimator=RidgeCV() ... ) >>> multi_layer_regressor = StackingRegressor( ... estimators=[('ridge', RidgeCV()), ... ('lasso', LassoCV(random_state=42)), ... ('svr', SVR(C=1, gamma=1e-6, kernel='rbf'))], ... final_estimator=final_layer ... ) >>> multi_layer_regressor.fit(X_train, y_train) StackingRegressor(...) >>> print('R2 score: {:.2f}' ... .format(multi_layer_regressor.score(X_test, y_test))) R2 score: 0.82 ``` ## 應用 ```python from sklearn.ensemble import StackingClassifier ``` ### class ```python sklearn.ensemble.StackingClassifier(estimators, final_estimator=None, cv=None, stack_method='auto', n_jobs=None, passthrough=False, verbose=0) ``` #### parameters * estimatorslist: * type: list of (str, estimator) * note: 每一個list內的元素都要以tuple格式來定義 * final_estimator: * type: estimator * default: None * note: 預設使用的分類器為`LogisticRegression` * cv: * type: int, cross-validation generator, or an iterable * default: None * options: * 未設置情況下會預設交叉驗證的`cv`為5 * 設置數值則指定KFold * 可以設置交叉驗證生成器的物件 * 可以設置可迭代物件 * note: * 對於數值或None的輸入,如果估計器是分類器,而且`y`是兩類或是多類別,則使用`StratifiedKFold `,其它情況皆使用`KFold` * 參考[使用者指南](https://scikit-learn.org/stable/modules/cross_validation.html#cross-validation)可瞭解更多可用的交叉驗證策略 * 訓練資料集夠大的時候,大量的拆分是無濟於事,而且訓練時間也會增加,`cv`並非用於模型選擇,而是預測 * stack_method: * default: auto * options: * auto: 如果設置auto則以下列順序執行 * predict_proba * decision_function * predict * n_jobs: * type: int * default: None * note: * 擬合過程中平行計算的核心數 * None表示1 * -1則表示使用所有的處理器 * passthrough: * type: bool * default: False * options: * False: 代表`final_estimator`使用`estimator`內的分類器的預測做為input * True: 代表`final_estimator`則使用`estimator`內的分類器的預測以及原始訓練資料集做為input #### attributes * estimators_: list of estimators * note: 估計參數的元素,已擬合於訓練資料上。如果設置`drop`則不顯示於清單中 * named_estimators: _Bunch * note: 以名稱取得`estimators_`的分類器屬性 * final_estimator_: estimator * note: 預測給定`estimators_`的輸出的分類器 * stack_method_: list of str * note: 每一個估計器使用的方法 #### methods * decision_function * note: 使用`final_estimator_.decision_function`預測決策函數 * fit * note: 擬合 * fit_transform * note: 擬合並轉換 * get_params * note: 取得估計器的參數 * predict * note: 預測目標類別 * predict_proba * note: 使用`final_estimator_.predict_proba`預測類別機率 * score * note: 回傳給定資料的平均準確度 * set_params * note: 設置估計器的參數 * transform * note: 回傳每一個估計器的類別標籤或機率 ## 範例 範例取自官方文件: ```python from sklearn.datasets import load_iris from sklearn.ensemble import RandomForestClassifier from sklearn.svm import LinearSVC from sklearn.linear_model import LogisticRegression from sklearn.preprocessing import StandardScaler from sklearn.pipeline import make_pipeline from sklearn.ensemble import StackingClassifier X, y = load_iris(return_X_y=True) estimators = [ ('rf', RandomForestClassifier(n_estimators=10, random_state=42)), ('svr', make_pipeline(StandardScaler(), LinearSVC(random_state=42))) ] clf = StackingClassifier( estimators=estimators, final_estimator=LogisticRegression() ) from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split( X, y, stratify=y, random_state=42 ) clf.fit(X_train, y_train).score(X_test, y_test) ```