Sklearn 實現高效機器學習的 19 個最優雅的技巧
了解 19 個 Sklearn 功能,它們可以直接而優雅地替代你手動執行的常見操作。
通過查閱Sklearn 的API 參考[1],我發現最常用的模型和函數只是該庫功能的冰山一角。盡管有些功能非常局限,只用于極少數的邊緣情況,但我發現許多估算器、變換器和實用函數,可以更優雅地修復人們手動執行的常見操作。
因此,我決定列出最優雅、最重要的功能,并進行簡要說明,以便你可以在一篇文章中顯著擴展你的 Sklearn 工具集。
1.covariance.EllipticEnvelope[2]
分布中存在異常值是很常見的。許多算法都會處理異值,Sklearn 內置的一個例子EllipticalEnvelope就是一個例子。該算法的優勢在于它在檢測正態分布(高斯)特征中的異常值方面表現非常出色:
import numpy as np
from sklearn.covariance import EllipticEnvelope
# Create a sample normal distribution
X = np.random.normal(loc=5, scale=2, size=50).reshape(-1, 1)
# Fit the estimator
ee = EllipticEnvelope(random_state=0)
_ = ee.fit(X)
# Test
test = np.array([6, 8, 20, 4, 5, 6, 10, 13]).reshape(-1, 1)
# predict returns 1 for an inlier and -1 for an outlier
>>> ee.predict(test)
array([ 1, 1, -1, 1, 1, 1, -1, -1])展示如何使用橢圓包絡估計器從正態分布的特征中檢測異常值。
為了測試估計器,我們創建一個均值為 5、標準差為 2 的正態分布。訓練完成后,我們將一些隨機數傳遞給它的predict方法。該方法對test中的異常值(分別為 20、10、13)返回 -1。
2.feature_selection.RFECV[3]
選擇最有助于預測的特征是防止過擬合和降低模型復雜度的必要步驟。Sklearn 提供的最強大的算法之一是遞歸特征消除 (RFE)。它使用交叉驗證自動找到最重要的特征,并丟棄其余特征。
該估計器的一個優點是它是一個包裝器——它可以用于任何返回特征重要性或系數分數的 Sklearn 算法。。這是一個合成數據集上的示例:
from sklearn.datasets import make_regression
from sklearn.feature_selection import RFECV
from sklearn.linear_model import Ridge
# Build a synthetic dataset
X, y = make_regression(n_samples=10000, n_features=15, n_informative=10)
# Init/fit the selector
rfecv = RFECV(estimator=Ridge(), cv=5)
_ = rfecv.fit(X, y)
# Transform the feature array
>>> rfecv.transform(X).shape
(10000, 10)展示基于模型的特征選擇技術——RFECV 如何使用 Ridge 回歸器作為模型來工作。
偽數據集包含 15 個特征,其中 10 個為信息性特征,其余均為冗余特征。我們利用Ridge回歸模型擬合了 5 倍 RFECV 估計器。訓練完成后,你可以使用該transform方法丟棄冗余特征。調用結果.shape顯示,該估計器成功丟棄了所有 5 個不必要的特征。
我已經寫了一篇關于該算法的完整文章,涵蓋了它如何與真實世界的數據集一起工作的細節:
3.ensemble.ExtraTrees[4]
盡管隨機森林功能強大,但過擬合的風險很高。因此,Sklearn 提供了一種名為 ExtraTrees(既是分類器又是回歸器)的 RF 替代方案。
extra一詞并不意味著更多的樹,而是更多的隨機性。該算法使用了另一種與決策樹非常相似的樹。
唯一的區別在于,我們不是構建每棵樹時就計算分割閾值,而是為每個特征隨機抽取閾值,并選擇最佳閾值作為分割規則。這降低了方差,但會略微增加偏差:
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)
# Decision trees
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
# Random Forest
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)在合成數據集上比較 RandomForest 和 ExtaTreesRegressor 的性能。ExtraTrees 勝出!
如你所見,ExtraTreesRegressor 在合成數據集上的表現優于隨機森林。
從官方用戶指南[5]中了解有關極隨機樹的更多信息。
4.impute.IterativeImputer[6]和KNNImputer[7]
如果你正在尋找比更強大、更先進的插補技術SimpleImputer,Sklearn 可以再次滿足你的需求。
sklearn.impute子包包括兩個基于模型的插補算法——KNNImputer和IterativeImputer。
顧名思義,KNNImputer使用 k-Nearest-Neighbors 算法來找到缺失值的最佳替代:
from sklearn.impute import KNNImputer
# Code taken from Sklearn user guide
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. ]])使用 KNNImputer 作為基于模型的插補技術來適當填充缺失值。
一種更穩健的算法是IterativeImputer。它通過將每個缺失值特征建模為其余特征的函數來查找缺失值。此過程以循序漸進的方式進行。在每個步驟中,選擇一個具有缺失值的特征作為目標(y),其余特征則選擇為特征數組(X)。然后,使用回歸器預測 中的缺失值y,并對每個特征重復此過程,直到 max_iter 次數(IterativeImputer 的一個參數)。
因此,單個缺失值會生成多個預測。這樣做的好處是將每個缺失值視為一個隨機變量,并關聯其固有的不確定性:
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 與 IterativeImputer 配合使用效果更佳。
5.linear_model.HuberRegressor[8]
異常值的存在會嚴重影響任何模型的預測。許多異常值檢測算法會丟棄異常值并將其標記為缺失值。雖然這有助于模型的學習功能,但它完全消除了異常值對分布的影響。
另一種算法是HuberRegressor。它不是完全移除異常值,而是在擬合過程中賦予異常值較小的權重。它有epsilon一個超參數,用于控制應被歸類為異常值的樣本數量。參數越小,模型對異常值的魯棒性就越強。它的 API 與任何其他線性回歸器相同。
下面,你可以看到它與具有大量異常值的數據集上的貝葉斯嶺回歸器的比較[9]:
img
如你所見,epsilon 為 1.35、1.5、1.75 的 HuberRegressor 成功捕捉到了不受異常值影響的最佳擬合線。
你可以從用戶指南[10]中了解有關該算法的更多信息。
6.tree.plot_tree[11]
Sklearn 可以使用以下函數繪制單個決策樹的結構plot_tree。對于剛開始學習基于樹的模型和集成模型的初學者來說,此功能可能很方便:
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);使用 Sklearn 的 plot_tree 函數可視化決策樹。
圖片
還有其他繪制樹的方法,例如使用 Graphviz 格式。請參閱用戶指南[12]了解更多信息。
7.linear_model.Perceptron[13]
這份列表中最酷的名字是排名第七的——感知器。雖然名字很花哨,但它其實是一個簡單的線性二分類器。該算法最顯著的特點是它適用于大規模學習,并且默認情況下:
- 它不需要學習率。
- 不實施正則化。
- 它僅在出現錯誤時更新其模型。
它相當于 SGDClassifier,loss='perceptron', eta=1, learning_rate="constant", penalty=None但速度稍快一些:
from sklearn.datasets import make_classification
from sklearn.linear_model import Perceptron
# Create a large dataset
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[14]
Sklearn 中另一個基于模型的特征選擇估計器是SelectFromModel。它不如 RFECV 那樣穩健,但由于計算成本較低,對于海量數據集來說是一個不錯的選擇。它也是一個包裝器估計器,適用于任何具有以下.feature_importances_屬性的模型.coef_:
from sklearn.feature_selection import SelectFromModel
# Make a dataset with 40 uninformative features
X, y = make_regression(n_samples=int(1e4), n_features=50, n_informative=10)
# Init the selector and transform feature array
selector = SelectFromModel(estimator=ExtraTreesRegressor()).fit(X, y)
>>> selector.transform(X).shape
(10000, 8)在具有 40 個冗余特征的合成數據集上嘗試使用 ExtraTreesRegressor 的 SelectFromModel 估計器。
如你所見,該算法成功刪除了所有 40 個冗余特征。
9.metrics.ConfusionMatrixDisplay[15]
混淆矩陣是分類問題的圣杯。大多數指標都源于它,例如精確度、召回率、F1、ROC AUC 等。Sklearn 可以計算并繪制默認混淆矩陣:
from sklearn.metrics import plot_confusion_matrix
from sklearn.model_selection import train_test_split
# Make a binary classification problem
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);
圖片
說實話,我不太喜歡默認的混淆矩陣。它的格式是固定的——行是真實標簽,列是預測值。此外,第一行第一列是負類,第二行第二列是正類。有些人可能更喜歡其他格式的矩陣,比如轉置矩陣或翻轉矩陣。
例如,我喜歡將正類設為第一行第一列,以符合維基百科的格式。這有助于我更好地區分 TP、FP、TN、FN 這四個矩陣項。幸運的是,你可以使用另一個函數 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);
圖片
在將混淆矩陣cm傳遞給之前,你可以將ConfusionMatrixDisplay設置為你想要的任何格式。
10.Generalized Linear Models[16]
如果存在適用于其他類型分布的替代方案,那么將目標 ( y ) 轉換為正態分布是沒有意義的。
例如,Sklearn 為目標變量提供了三種廣義線性模型,分別為泊松分布、Tweedie 分布或 Gamma 分布。與預期的正態分布不同,PoissonRegressor、TweedieRegressor和GammaRegressor可以為具有相應分布的目標生成穩健的結果。
除此之外,它們的 API 與任何其他 Sklearn 模型相同。要確定目標的分布是否與上述三個分布相匹配,你可以將它們的 PDF(概率密度函數)繪制在具有完美分布的相同軸上。
例如,要查看目標是否遵循泊松分布,請使用 Seaborn 中的 kdeplot繪制其 PDF ,并通過在相同軸上從 Numpy 中np.random.poisson采樣來繪制完美的泊松分布。
11.ensemble.IsolationForest[17]
由于基于樹的模型和集成模型通常能產生更穩健的結果,它們在異常值檢測方面也被證明是有效的。例如,Sklearn 中的IsolationForest ,其使用由極其隨機的樹組成的森林(tree.ExtraTreeRegressor)來檢測異常值。每棵樹都嘗試通過選擇一個特征,并在所選特征的最大值和最小值之間隨機選擇一個分割值來隔離每個樣本。
這種類型的隨機分區會在每棵樹的根節點和終止節點之間產生明顯較短的路徑。
因此,當隨機樹林共同為特定樣本產生較短的路徑長度時,它們很可能是異常——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])該算法正確捕獲了異常值(90)并將其標記為-1。
在用戶指南[18]中閱讀有關該算法的更多信息。
12.preprocessing.PowerTransformer[19]
許多線性模型需要對數值特征進行一些轉換,以使其服從正態分布,StandardScaler和MinMaxScaler對大多數分布都運行良好。
然而,當數據偏度較高時,分布的核心指標(例如平均值、中位數、最小值和最大值)都會受到影響。因此,簡單的歸一化和標準化對偏斜分布不起作用。
相反,Sklearn 中的 PowerTransformer 使用對數變換將任何傾斜的特征實現了盡可能地轉換為正態分布。考慮 Diamonds 數據集中的這兩個特征:
import seaborn as sns
diamonds = sns.load_dataset("diamonds")
diamonds[["price", "carat"]].hist(figsize=(10, 5));
圖片
兩者都嚴重傾斜。讓我們使用對數變換來解決這個問題:
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[20]
Sklearn 中的另一個數字轉換器是RobustScaler。你大概能從它的名字猜到它的作用——它可以以一種對異常值魯棒的方式轉換特征。如果某個特征中存在異常值,則很難使它們服從正態分布,因為它們會嚴重扭曲平均值和標準差。
不使用平均值/標準差,而是RobustScaler使用中位數和四分位距 (IQR) 來縮放數據,因為這兩個指標不會因異常值而產生偏差。你也可以在用戶指南[21]中閱讀相關內容。
14.compose.make_column_transformer[22]
在 Sklearn 中,有一個使用make_pipeline函數創建 Pipeline 實例的簡寫方法。該函數無需為每個步驟命名,也無需讓代碼變得冗長,只需接受轉換器和估算器即可完成其工作:
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())])使用“make_pipeline”函數縮短創建 Sklearn 管道的代碼。
對于更復雜的場景,ColumnTransformer使用 ,但它也存在同樣的問題——每個預處理步驟都應該命名,這會使代碼冗長且難以閱讀。值得慶幸的是,Sklearn 提供了類似的函數make_pipeline— make_column_transformer:
import seaborn as sns
from sklearn.compose import make_column_transformer
from sklearn.preprocessing import OneHotEncoder
# Load diamonds dataset
diamonds = sns.load_dataset("diamonds")
X, y = diamonds.drop("price", axis=1), diamonds.price.values.reshape(-1, 1)
# Isolate numeric and categorical cols
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函數縮短創建ColumnTransformer對象的代碼。
如你所見,使用起來make_column_transformer要短得多,并且它負責自行命名每個轉換器步驟。
15.compose.make_column_selector[23]
如果你仔細觀察,就會發現我們使用了select_dtypes函數以及columnsPandas DataFrames 的屬性來隔離數字列和分類列。雖然這種方法有效,但使用 Sklearn 可以實現更靈活、更優雅的解決方案。
make_column_selector 函數創建一個可直接傳遞給ColumnTransformer實例的列選擇器。它的功能與select_dtypes類似, 甚至更好。它包含dtype_include和dtype_exclude參數,用于根據數據類型選擇列。
如果需要自定義列過濾器,甚至可以將正則表達式傳遞給 ,pattern同時將其他參數設置為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帶有相關參數的實例即可!
16.preprocessing.OrdinalEncoder[24]
初學者常犯的一個錯誤是使用LabelEncoder來編碼有序分類特征。如果你注意到了,LabelEncoder一次只能轉換一列,而不是像OneHotEncoder那樣同時轉換。你可能會認為 Sklearn 犯了一個錯誤!
實際上,LabelEncoder應該僅用于編碼響應變量(y),如其文檔[25]中所述。要編碼特征數組(X),你應該使用OrdinalEncoder可以正常工作的函數。它將有序分類列轉換為具有 (0, n_categories - 1) 個類別的特征。并且它只需一行代碼即可對所有指定的列執行此操作,從而可以將其包含在管道中。
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.]])使用 OrdinalEncoder 編碼序數分類特征
17.metrics.get_scorer[26]
Sklearn 內置了 50 多個指標,它們的文本名稱可以在 中查看sklearn.metrics.SCORERS.keys()。在單個項目中,你可能需要使用多個指標,如果要單獨使用它們,則需要導入它們。
直接導入大量指標sklearn.metrics可能會污染你的命名空間,并導致不必要的冗長代碼。解決方案是,你可以使用metrics.get_scorer函數通過文本名稱訪問任何指標,而無需導入它:
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)使用 get_scorer 函數而不導入指標。
18.model_selection.HalvingGrid[27]和HalvingRandomSearchCV[28]
在 Sklearn 0.24 版本中,我們引入了兩個實驗性的超參數優化器:HalvingGridSearchCV和HalvingRandomSearchCV類。
與窮舉型網格搜索 (GridSearch) 和隨機化搜索 (RandomizedSearch) 不同,新類別使用了一種名為“連續減半”的技術。它不是在所有數據上訓練所有候選集(參數組合集),而是只將一部分數據提供給參數。通過在較小的數據子集上進行訓練,可以過濾掉表現最差的候選集。每次迭代后,訓練樣本都會增加一定倍數,而可能的候選集數量則會相應減少,從而大大縮短評估時間。
快多少?在我進行的實驗中,HalvingGridSearch 比常規 GridSearch 快 11 倍,HalvingRandomSearch 甚至比 HalvingGridSearch 快 10 倍。你可以在這里閱讀我對連續減半的詳細概述和我的實驗:
19.sklearn.utils[29]
最后但同樣重要的是,Sklearn 的 subpackage 模塊中提供了大量的實用函數和輔助函數sklearn.utils。Sklearn 本身使用此模塊中的函數來構建我們常用的所有轉換器和估算器。
有很多有用的,例如class_weight.compute_class_weight,estimator_html_repr,shuffle,check_X_y等等。你可以在自己的工作流程中使用它們,使你的代碼更像 Sklearn,或者在創建適合 Sklearn API 的自定義轉換器和估算器時它們可能會派上用場。
參考資料
[1] Sklearn 的API 參考: https://scikit-learn.org/stable/modules/classes.html#api-reference
[2] covariance.EllipticEnvelope: https://scikit-learn.org/stable/modules/generated/sklearn.covariance.EllipticEnvelope.html#sklearn.covariance.EllipticEnvelope
[3] feature_selection.RFECV: https://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.RFECV.html
[4] ensemble.ExtraTrees: https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.ExtraTreesRegressor.html
[5] 用戶指南: https://scikit-learn.org/stable/modules/ensemble.html#extremely-randomized-trees
[6] impute.IterativeImputer: https://scikit-learn.org/stable/modules/generated/sklearn.impute.IterativeImputer.html
[7] KNNImputer: https://scikit-learn.org/stable/modules/generated/sklearn.impute.KNNImputer.html
[8] linear_model.HuberRegressor: https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.HuberRegressor.html
[9] 貝葉斯嶺回歸器的比較: https://scikit-learn.org/stable/auto_examples/linear_model/plot_huber_vs_ridge.html#sphx-glr-auto-examples-linear-model-plot-huber-vs-ridge-py
[10] 用戶指南: https://scikit-learn.org/stable/modules/linear_model.html#huber-regression
[11] tree.plot_tree: https://scikit-learn.org/stable/modules/generated/sklearn.tree.plot_tree.html
[12] 用戶指南: https://scikit-learn.org/stable/modules/tree.html#decision-trees
[13] linear_model.Perceptron: https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.Perceptron.html
[14] feature_selection.SelectFromModel: https://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.SelectFromModel.html
[15] metrics.ConfusionMatrixDisplay: https://scikit-learn.org/stable/modules/generated/sklearn.metrics.ConfusionMatrixDisplay.html
[16] Generalized Linear Models: https://scikit-learn.org/stable/modules/linear_model.html#generalized-linear-regression
[17] ensemble.IsolationForest: https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.IsolationForest.html
[18] 在用戶指南: https://scikit-learn.org/stable/modules/outlier_detection.html#isolation-forest
[19] preprocessing.PowerTransformer: https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.PowerTransformer.html
[20] preprocessing.RobustScaler: https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.RobustScaler.html
[21] 用戶指南: https://scikit-learn.org/stable/modules/preprocessing.html#preprocessing-data
[22] compose.make_column_transformer: https://scikit-learn.org/stable/modules/generated/sklearn.compose.make_column_transformer.html
[23] compose.make_column_selector: https://scikit-learn.org/stable/modules/generated/sklearn.compose.make_column_selector.html
[24] preprocessing.OrdinalEncoder: https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OrdinalEncoder.html
[25] 文檔: https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.LabelEncoder.html
[26] metrics.get_scorer: https://scikit-learn.org/stable/modules/generated/sklearn.metrics.get_scorer.html
[27] model_selection.HalvingGrid: https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.HalvingGridSearchCV.html
[28] HalvingRandomSearchCV: https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.HalvingGridSearchCV.html
[29] sklearn.utils: https://scikit-learn.org/stable/modules/classes.html#module-sklearn.utils





























