19個Python?Sklearn中超實用的隱藏功能分享
今天跟大家介紹 19 個 Sklearn 中超級實用的隱藏的功能,這些功能雖然不常見,但非常實用,它們可以直接優(yōu)雅地替代手動執(zhí)行的常見操作。接下來我們就一個一個介紹這些功能,希望對大家有所幫助!
寫在前面
通過查看 Sklearn 的 API,發(fā)現(xiàn)最常用的模型和函數(shù)只是眾多庫中的一小部分。盡管某些功能的使用范圍非常小并且一般用于一些邊緣情況,但我發(fā)現(xiàn)很多評估器、轉換器和實用程序功能可以很好地處理手動執(zhí)行的常見操作。

https://scikit-learn.org/stable/modules/classes.html#api-reference
因此,接下來我將列出最重要的一些功能并做個簡要的解釋,這樣可以我們擴展一些 Sklearn 工具集,以便在學習工作中可以更好地更快地處理事務。
1 .covariance.EllipticEnvelope
通常,在我們的所處理的數(shù)據(jù)分布中有異常值是很常見的,并且許多算法都可以處理離群值,而 EllipticalEnvelope 就是 Sklearn 中直接內(nèi)置的一個例子。該算法的優(yōu)勢在于,它在檢測正態(tài)分布(高斯)特征中的異常點時表現(xiàn)得非常好:
import?numpy?as?np from?sklearn.covariance?import?EllipticEnvelope #?創(chuàng)建一個樣本正態(tài)分布 X?=?np.random.normal(loc=5,?scale=2,?size=50).reshape(-1,?1) #?擬合估計量 ee?=?EllipticEnvelope(random_state=0) _?=?ee.fit(X) #?測試 test?=?np.array([6,?8,?20,?4,?5,?6,?10,?13]).reshape(-1,?1) #?Predict返回1作為內(nèi)嵌值,返回-1作為異常值 >>>?ee.predict(test) array([?1,??1,?-1,??1,??1,??1,?-1,?-1])
為了檢驗評估結果,我們創(chuàng)建了一個均值為5,標準差為2的正態(tài)分布。訓練完成后,將一些隨機數(shù)傳遞給它的預測方法。該方法返回-1表示測試中的異常值,即20、10、13。
2 .feature_selection.RFECV
我們在做數(shù)據(jù)挖掘,做特征工程時,選擇對預測最有幫助的特征是防止過擬合和降低模型復雜性的必要步驟。Sklearn提供的最健壯的算法之一是遞歸特征消除(RFE)。它通過使用交叉驗證自動找到最重要的特性,并丟棄其余的。
這個評估器的一個優(yōu)點是它是一個包裝器——它可以用于返回特征重要性或系數(shù)分數(shù)的任何 Sklearn 算法。下面是一個關于合成數(shù)據(jù)集的例子:
from?sklearn.datasets?import?make_regression from?sklearn.feature_selection?import?RFECV from?sklearn.linear_model?import?Ridge #?構建一個合成數(shù)據(jù)集 X,?y?=?make_regression(n_samples=10000,?n_features=15,?n_informative=10) #?初始化和擬合選擇器 rfecv?=?RFECV(estimator=Ridge(),?cv=5) _?=?rfecv.fit(X,?y) #?轉換特性陣列 >>>?rfecv.transform(X).shape (10000,?10)
數(shù)據(jù)集有 15 個特征,其中 10 個特征是信息豐富的,其余都是冗余的。我們用嶺回歸擬合 5-fold RFECV 作為評估器。訓練后,可以使用變換方法丟棄冗余特征。最后調用 .shape 查看評估器刪除了所有 5 個冗余的特性。
3 .ensemble.ExtraTrees
我們都知道,盡管隨機森林非常強大,但過度擬合的風險非常高。因此,Sklearn提供了稱為 ExtraTrees(分類器和回歸器) 的 RF 替代方案。
"Extra" 這個詞并不是指更多的樹,而是指更多的隨機性。該算法使用了另一種類似于決策樹的樹。唯一的區(qū)別是,不同于在構建每棵樹時計算分割閾值,這些閾值是為每個特征隨機繪制的,并選擇最佳閾值作為分割規(guī)則。這允許以偏差略微增加的代價來降低方差:
from?sklearn.ensemble?import?ExtraTreesRegressor,?RandomForestRegressor from?sklearn.model_selection?import?cross_val_score from?sklearn.tree?import?DecisionTreeRegressor X,?y?=?make_regression(n_samples=10000,?n_features=20) #?決策樹 clf?=?DecisionTreeRegressor(max_depth=None,?min_samples_split=2,?random_state=0) scores?=?cross_val_score(clf,?X,?y,?cv=5) >>>?scores.mean() 0.6376080094392635 #?隨機森林 clf?=?RandomForestRegressor( ????n_estimators=10,?max_depth=None,?min_samples_split=2,?random_state=0 ) scores?=?cross_val_score(clf,?X,?y,?cv=5) >>>?scores.mean() 0.8446103607404536 #?ExtraTrees clf?=?ExtraTreesRegressor( ????n_estimators=10,?max_depth=None,?min_samples_split=2,?random_state=0 ) scores?=?cross_val_score(clf,?X,?y,?cv=5) >>>?scores.mean() 0.8737373931608834
如結果所示,ExtraTreesRegressor 在合成數(shù)據(jù)集上的表現(xiàn)優(yōu)于隨機森林。
4 .impute.IterativeImputer 和 .impute.KNNImputer
如果你正在尋找比 SimpleImputer 更健壯、更先進的 imputation 技術,Sklearn再次為你提供了支持。impute 子包包括兩個基于模型的 impute 算法 KNNImputer 和 IterativeImputer。
顧名思義,KNNImputer 使用 k-Nearest-Neighbors 算法來尋找缺失值的最佳替代:
from?sklearn.impute?import?KNNImputer #?代碼取自Sklearn用戶指南 X?=?[[1,?2,?np.nan],? ?????[3,?4,?3],? ?????[np.nan,?6,?5],? ?????[8,?8,?7]] imputer?=?KNNImputer(n_neighbors=2) imputer.fit_transform(X)
輸出:
array([[1. , 2. , 4. ],
[3. , 4. , 3. ],
[5.5, 6. , 5. ],
[8. , 8. , 7. ]])
另一個更健壯的算法是 IterativeImputer。它通過將每個特征的缺失值建模為其他特征的函數(shù)來尋找缺失值。 這個過程是按循序漸進的循環(huán)方式完成的。在每一步中,選擇一個具有缺失值的特征作為目標(y),其余的作為特征數(shù)組(X)。然后,使用回歸函數(shù)預測 y 中的缺失值,并對每個特征繼續(xù)這個過程,直到 max_iter 次數(shù) (IterativeImputer的一個參數(shù))。
因此,會為一個缺失的值生成多個預測。這樣做的好處是,可以將每個缺失的值視為隨機變量,并將其與固有的不確定性聯(lián)系起來:
from?sklearn.experimental?import?enable_iterative_imputer from?sklearn.impute?import?IterativeImputer from?sklearn.linear_model?import?BayesianRidge imp_mean?=?IterativeImputer(estimator=BayesianRidge()) imp_mean.fit([[7,?2,?3],? ??????????????[4,?np.nan,?6],? ??????????????[10,?5,?9]]) ?????????????? X?=?[[np.nan,?2,?3],? ?????[4,?np.nan,?6],? ?????[10,?np.nan,?9]] imp_mean.transform(X)
輸出:
array([[ 6.95847623, 2. , 3. ],
[ 4. , 2.6000004 , 6. ],
[10. , 4.99999933, 9. ]])
結果表明,使用 IterativeImputer 缺失值填補算法的 BayesianRidge 和 ExtraTree 算法性能效果變現(xiàn)更加優(yōu)秀。
5 .linear_model.HuberRegressor
雖然正常情況下,數(shù)據(jù)分布中存在異常值是非常常見的, 但異常值的存在會嚴重破壞任何模型的預測。許多異常值檢測算法會丟棄異常值并將其標記為缺失。雖然這有助于模型的學習,但它完全消除了異常值對分布的影響。
另一種算法是 HuberRegressor 回歸算法。它不是完全去除它們,而是在擬合數(shù)據(jù)期間給予異常值更小的權重。它有超參數(shù) epsilon 來控制樣本的數(shù)量,這些樣本應該被歸類為異常值。參數(shù)越小,對異常值的魯棒性越強。它的API與任何其他線性回歸函數(shù)相同。下面,你可以看到它與貝葉斯嶺回歸器在一個有大量異常值的數(shù)據(jù)集上的比較:

可以看到,設置參數(shù) epsilon 為 1.35 1.5, 1.75 的 huberregressionor 算法設法捕獲不受異常值影響的最佳擬合線。
6 .tree.plot_tree
Sklearn 中可以使用 plot_tree 函數(shù)繪制單個決策樹的結構。這個特性可能對剛開始學習基于樹的模型和集成模型的初學者很方便,通過該方法,對決策樹的決策過程可視化,對其決策過程和原理更加一目了然。
from?sklearn.datasets?import?load_iris from?sklearn.tree?import?DecisionTreeClassifier,?plot_tree iris?=?load_iris() X,?y?=?iris.data,?iris.target clf?=?DecisionTreeClassifier() clf?=?clf.fit(X,?y) plt.figure(figsize=(15,?10),?dpi=200) plot_tree(clf,?feature_names=iris.feature_names,? ???????????????class_names=iris.target_names);

還有其他繪制樹的方法,比如 Graphviz。
7 .linear_model.Perceptron
盡管感知機是一個奇特的名字,但它是一個簡單的線性二進制分類器。算法的定義特征是適合大規(guī)模學習,默認為:
- 它不需要學習速率。
- 不要實現(xiàn)正則化。
- 它只在分類錯誤的情況下更新模型。
它等價于 SGDClassifier,loss='perceptron', eta0=1, learning_rate="constant", penalty=None ,但略快:
from?sklearn.datasets?import?make_classification from?sklearn.linear_model?import?Perceptron #?創(chuàng)建一個更大的數(shù)據(jù)集 X,?y?=?make_classification(n_samples=100000,?n_features=20,?n_classes=2) #?Init/Fit/Score clf?=?Perceptron() _?=?clf.fit(X,?y) clf.score(X,?y)
輸出:
0.91928
8 .feature_selection.SelectFromModel
Sklearn 中另一個基于模型的特征選擇模型是 SelectFromModel。它不像RFECV那樣健壯,但由于它具有較低的計算成本,可以作為大規(guī)模數(shù)據(jù)集的一個很好的選擇。它也是一個包裝器模型,適用于任何具有 .feature_importance_ 或 .coef_ 屬性的模型:
from?sklearn.feature_selection?import?SelectFromModel #?創(chuàng)建一個包含40個無信息特征的數(shù)據(jù)集 X,?y?=?make_regression(n_samples=int(1e4),?n_features=50,?n_informative=10) #?初始化選擇器并轉換特性數(shù)組 selector?=?SelectFromModel(estimator=ExtraTreesRegressor()).fit(X,?y) selector.transform(X).shape
輸出:
(10000, 8)
如結果所示,算法成功地刪除了所有40個冗余特征。
9 .metrics.ConfusionMatrixDisplay
總所周知,混淆矩陣是用于評估分類問題的常用方法。我們通常使用的大多數(shù)指標都來自于它,如精度、召回率、F1、ROC AUC等等。Sklearn中可以計算和繪制一個默認的混淆矩陣:
from?sklearn.metrics?import?plot_confusion_matrix from?sklearn.model_selection?import?train_test_split #?創(chuàng)建一個二元分類問題 X,?y?=?make_classification(n_samples=200,?n_features=5,?n_classes=2) X_train,?X_test,?y_train,?y_test?=?train_test_split( ????X,?y,?test_size=0.5,?random_state=1121218 ) clf?=?ExtraTreeClassifier().fit(X_train,?y_train) fig,?ax?=?plt.subplots(figsize=(5,?4),?dpi=100) plot_confusion_matrix(clf,?X_test,?y_test,?ax=ax);

老實說,我不喜歡默認的混淆矩陣。它的格式是固定的—行是true labels,列是predictions label。第一行和第一列是負類,第二行和第二列是正類。有些人可能更喜歡不同格式的矩陣,可能是轉置或翻轉的。
例如,我喜歡將正類作為第一行和第一列。這有助于我更好地隔離 4 矩陣項 -- TP, FP, TN, FN。幸運的是,你可以用另一個函數(shù) ConfusionMatrixDisplay 繪制自定義矩陣:
from?sklearn.metrics?import?ConfusionMatrixDisplay,?confusion_matrix clf?=?ExtraTreeClassifier().fit(X_train,?y_train) y_preds?=?clf.predict(X_test) fig,?ax?=?plt.subplots(figsize=(5,?4),?dpi=100) cm?=?confusion_matrix(y_test,?y_preds) cmp?=?ConfusionMatrixDisplay(cm,? ??????display_labels=["Positive",?"Negative"]) cmp.plot(ax=ax);

在傳遞給 ConfusionMatrixDisplay 之前,可以把 混淆矩陣cm 放在任何格式中。
10 .Generalized Linear Models
一般情況下,如果有可用于其他類型分布的替代方案,則將目標(y)轉換為正態(tài)分布是沒有意義的。
例如,Sklearn 為目標變量提供了3種廣義線性模型,分別是泊松、Tweedie或Gamma分布 ,而不是所期望的正態(tài)分布,poissonregressionor, TweedieRegressor 和 GammaRegressor 可以生成具有各自分布的目標的穩(wěn)健結果。
除此之外,他們的api與任何其他Sklearn模型一樣。為了找出目標的分布是否與上述三個相匹配,可以將它們的PDF(概率密度函數(shù))繪制在相同軸上。
例如,要查看目標是否遵循泊松分布,可以使用 Seaborn 的 kdeploy 繪制它的 PDF,并在相同的軸上使用 np.random_poisson 從 Numpy 中采樣,繪制完美的泊松分布。
11 .ensemble.IsolationForest
一般情況下,基于樹的模型和集合模型通常產(chǎn)生更穩(wěn)健的結果,它們在異常點檢測方面也被證明是有效的。Sklearn 中的 IsolationForest 使用一個極端隨機樹 (tree.ExtraTreeRegressor) 來檢測異常值。每棵樹試圖通過選擇一個單一的特征,并在所選特征的最大值和最小值之間隨機選擇一個分裂值來隔離每個樣本。
這種隨機分區(qū)會在每棵樹的根節(jié)點和終止節(jié)點之間產(chǎn)生明顯更短的路徑。
因此,當隨機樹組成的森林為特定樣本共同產(chǎn)生更短的路徑長度時,它們極有可能是異常——Sklearn用戶指南。
from?sklearn.ensemble?import?IsolationForest X?=?np.array([-1.1,?0.3,?0.5,?100]).reshape(-1,?1) clf?=?IsolationForest(random_state=0).fit(X) clf.predict([[0.1],?[0],?[90]])
輸出:
array([ 1, 1, -1])
12 .preprocessing.PowerTransformer
許多線性模型需要在數(shù)值特征上進行一些轉換才能使其服從正態(tài)分布。StandardScaler 和 MinMaxScaler 在大多數(shù)發(fā)行版中都比較適用。然而,當數(shù)據(jù)存在高偏度時,分布的核心指標,如平均值、中位數(shù)、最小值和最大值,就會受到影響。因此,簡單的標準化和標準化對傾斜分布不起作用。
相反,Sklearn 實現(xiàn)中提供了一個名為 PowerTransformer的方法,它使用對數(shù)變換將任何傾斜的特征盡可能地轉化為正態(tài)分布??紤] Diamonds 數(shù)據(jù)集中的兩個特征:
import?seaborn?as?sns
diamonds?=?sns.load_dataset("diamonds")
diamonds[["price",?"carat"]].hist(figsize=(10,?5));

兩者都嚴重傾斜。我們用對數(shù)變換 PowerTransformer來解決這個問題:
from?sklearn.preprocessing?import?PowerTransformer pt?=?PowerTransformer() diamonds.loc[:,?["price",?"carat"]]?=?pt.fit_transform(diamonds[["price",?"carat"]]) diamonds[["price",?"carat"]].hist(figsize=(10,?5));

13 .preprocessing.RobustScaler
Sklearn 中的另一個數(shù)字轉換器是 RobustScaler,我們可以從它的名稱猜出它的用途——可以以一種健壯到異常值的方式轉換特性。如果一個特征中存在異常值,就很難使其服從正態(tài)分布,因為它們會嚴重扭曲均值和標準差。
與使用均值/標準不同,RobustScaler 使用中值和IQR(四分位數(shù)范圍)來衡量數(shù)據(jù),因為這兩個指標都不會因為異常值而有偏差。
14 .compose.make_column_transformer
在 Sklearn 中,有一個用 make_pipeline 函數(shù)創(chuàng)建 Pipeline 實例的簡寫。該函數(shù)不需要為Pipeline中的每一步命名,而是只接受變形器和估計器并執(zhí)行它的工作,從而不需要使代碼那么長:
from?sklearn.impute?import?SimpleImputer from?sklearn.pipeline?import?make_pipeline from?sklearn.preprocessing?import?StandardScaler pipeline?=?make_pipeline(SimpleImputer(),?StandardScaler(),?ExtraTreesRegressor()) pipeline
Pipeline(steps=[('simpleimputer',
SimpleImputer()),
('standardscaler',
StandardScaler()),
('extratreesregressor',
ExtraTreesRegressor())])對于更復雜的場景,使用 ColumnTransformer,這有相同的問題——每個預處理步驟都應該命名,這會使代碼變得冗長且不可讀。Sklearn提供了與 make_pipeline 類似的函數(shù):
import?seaborn?as?sns
from?sklearn.compose?import?make_column_transformer
from?sklearn.preprocessing?import?OneHotEncoder
#?負載鉆石數(shù)據(jù)集
diamonds?=?sns.load_dataset("diamonds")
X,?y?=?diamonds.drop("price",?axis=1),?diamonds.price.values.reshape(-1,?1)
#?拆分數(shù)字和類別標簽
num_cols?=?X.select_dtypes(include=np.number).columns
cat_cols?=?X.select_dtypes(exclude=np.number).columns
make_column_transformer((StandardScaler(),?num_cols),?
????????????????????????????(OneHotEncoder(),?cat_cols))
ColumnTransformer(
transformers=[('standardscaler',
StandardScaler(),
Index(['carat', 'depth',
'table', 'x', 'y', 'z'],
dtype='object')),
('onehotencoder',
OneHotEncoder(),
Index(['cut', 'color',
'clarity'],
dtype='object'))]
)如上所示,使用 make_column_transformer 要短得多,并且它自己負責命名每個轉換器步驟。
15 .compose.make_column_selector
上文中,我們使用 select_dtypes 函數(shù)和 pandas DataFrames 的 columns 屬性來拆分數(shù)值列和分類列。雖然這當然有效,但使用 Sklearn 有一個更靈活、更優(yōu)雅的解決方案。
make_column_selector 函數(shù)創(chuàng)建一個可以直接傳遞到 ColumnTransformer 實例中的列選擇器。它的工作原理與 select_dtypes 類似,甚至更好。它有 dtype_include 和 dtype_exclude 參數(shù),可以根據(jù)數(shù)據(jù)類型選擇列。如果需要自定義列篩選器,可以將正則表達式傳遞給 pattern,同時將其他參數(shù)設置為 None。下面是它的工作原理:
from?sklearn.compose?import?make_column_selector make_column_transformer( ????(StandardScaler(),?make_column_selector(dtype_include=np.number)), ????(OneHotEncoder(),?make_column_selector(dtype_exclude=np.number)), )
只是傳遞一個實例 make_column_selector 與由你設置相關參數(shù),而不是傳遞一個列名稱列表!
16 .preprocessing.OrdinalEncoder
在我們剛學習機器學習時,常見的一個錯誤是使用 LabelEncoder 來編碼有序的分類特征。注意到,LabelEncoder 一次只允許轉換一個列,而不是像 OneHotEncoder 那樣同時轉換。你可能會認為 Sklearn 犯了一個錯誤!
實際上,LabelEncoder 應該只用于按照 LabelEncoder 文檔中指定的方式對響應變量(y)進行編碼。要編碼特征數(shù)組(X),應該使用 OrdinalEncoder,它將有序分類列轉換為具有(0, n_categories - 1) 類的特性。它在一行代碼中跨所有指定列執(zhí)行此操作,使得在管道中包含它成為可能。
from?sklearn.preprocessing?import?OrdinalEncoder oe?=?OrdinalEncoder() X?=?[ ????["class_1",?"rank_1"], ????["class_1",?"rank_3"], ????["class_3",?"rank_3"], ????["class_2",?"rank_2"], ] oe.fit_transform(X)
輸出:
array([[0., 0.],
[0., 2.],
[2., 2.],
[1., 1.]])
17 .metrics.get_scorer
Sklearn 內(nèi)置了 50 多個指標,它們的文本名稱可以在 Sklearn.metrics.scores.keys 中看到。在單個項目中,如果單獨使用它們,則可能需要使用多個指標并導入它們。
從 sklearn.metrics 中導入大量指標可能會污染你的名稱空間,使其變得不必要的長。一種解決方案是可以使用 metrics.get_scorer 函數(shù)使用其文本名稱訪問任何度量,而不需要導入它:
from?sklearn.metrics?import?get_scorer
>>>?get_scorer("neg_mean_squared_error")
make_scorer(mean_squared_error,?
????????????greater_is_better=False)
>>>?get_scorer("recall_macro")
make_scorer(recall_score,?
????????????pos_label=None,?
????????????average=macro)
>>>?get_scorer("neg_log_loss")
make_scorer(log_loss,?
????????????greater_is_better=False,?
????????????needs_proba=True)
18 .model_selection.HalvingGrid 和 HalvingRandomSearchCV
在 sklearn 的 0.24 版本中,引入了兩個實驗性超參數(shù)優(yōu)化器:HalvingGridSearchCV 和 HalvingRandomSearchCV 類。
與它們詳盡的同類 GridSearch 和 RandomizedSearch 不同,新類使用了一種稱為連續(xù)減半的技術。 不是在所有數(shù)據(jù)上訓練所有候選集,而是只將數(shù)據(jù)的一個子集提供給參數(shù)。通過對更小的數(shù)據(jù)子集進行訓練,篩選出表現(xiàn)最差的候選人。每次迭代后,訓練樣本增加一定的因子,而可能的候選個數(shù)減少盡可能多的因子,從而獲得更快的評估時間。
快多少呢?在我做過的實驗中,HalvingGridSearch 比普通 GridSearch 快11倍,HalvingRandomSearch 甚至比 HalvingGridSearch 快10倍。
19 .sklearn.utils
Sklearn在 sklearn.utils 中有一整套實用程序和輔助功能。Sklearn本身使用這個模塊中的函數(shù)來構建我們使用的所有變形器transformers和估計器transformers。
這里有許多有用的方法,如 class_weight.compute_class_weight、estimator_html_repr、shuffle、check_X_y等。你可以在自己的工作流程中使用它們,使你的代碼更像 Sklearn,或者在創(chuàng)建適合 Sklearn API 的自定義轉換器和評估器時,它們可能會派上用場。
總結
盡管像 CatBoost, XGBoost, LightGBM 等庫正在慢慢從 Sklearn 中搶走領先的 ML 庫的頭把交椅,但它仍然是現(xiàn)代 ML工程師技能堆棧中不可估量的一部分。
一致的 API、卓越的代碼設計以及創(chuàng)建強大的 ML 工作流的能力仍然使 Sklearn 在功能和靈活性方面無與倫比。盡管我們可以在基礎知識方面完成很多工作,但本文表明 Sklearn 提供的不僅僅是表面上的東西!
以上就是19個Python Sklearn中超實用的隱藏功能分享的詳細內(nèi)容,更多關于Python Sklearn的資料請關注腳本之家其它相關文章!
相關文章
詳解Python中高階函數(shù)(map,filter,reduce,sorted)的使用
高階函數(shù)就是能夠把函數(shù)當成參數(shù)傳遞的函數(shù)就是高階函數(shù),換句話說如果一個函數(shù)的參數(shù)是函數(shù),那么這個函數(shù)就是一個高階函數(shù)。本文為大家詳細講解了Python中常用的四個高階函數(shù),感興趣的可以了解一下2022-04-04
通過python模糊匹配算法對兩個excel表格內(nèi)容歸類
這篇文章主要介紹了通過python模糊匹配算法對兩個excel表格內(nèi)容歸類,比如兩個不同的工程項目針對的對象都是A,那么就需要將這兩個工程項目歸類到A當中,可以減少很大一部分工作量,,需要的朋友可以參考下2023-03-03

