在最新的scikit-learn版本中,引入了许多错误修复和改进,以及一些关键的新特性。以下是一些主要的更新点。若要获取所有变更的详尽列表,请参考发布说明。
要安装最新版本,可以使用pip或conda进行安装:
pip install --upgradescikit-learn
conda install -c conda-forgescikit-learn
在本次更新中,特别增强了对DataFrame中分类数据类型的支持。例如,以下展示了如何使用包含分类和数值特征的数据集:
from sklearn.datasets import fetch_openml
X_adult, y_adult = fetch_openml("adult", version=2, return_X_y=True)
X_adult = X_adult.drop(["education-num", "fnlwgt"], axis="columns")
通过设置categorical_features="from_dtype"
,梯度提升分类器会将具有分类数据类型的列作为算法中的分类特征处理:
from sklearn.ensemble import HistGradientBoostingClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_auc_score
X_train, X_test, y_train, y_test = train_test_split(X_adult, y_adult, random_state=0)
hist = HistGradientBoostingClassifier(categorical_features="from_dtype")
hist.fit(X_train, y_train)
y_decision = hist.decision_function(X_test)
print(f"ROC AUC score is {roc_auc_score(y_test, y_decision)}")
输出的ROC AUC分数为0.9281711134685657,显示了模型的优良性能。此外,scikit-learn的转换器现在支持通过set_output
API输出Polars格式的数据。
import polars as pl
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
df = pl.DataFrame({"height": [120, 140, 150, 110, 100], "pet": ["dog", "cat", "dog", "cat", "cat"]})
preprocessor = ColumnTransformer([("numerical", StandardScaler(), ["height"]), ("categorical", OneHotEncoder(sparse_output=False), ["pet"])], verbose_feature_names_out=False)
preprocessor.set_output(transform="polars")
df_out = preprocessor.fit_transform(df)
输出的df_out
是一个Polars DataFrame,其形状为(5, 3),包含了数值和分类特征的处理结果。
在支持缺失值方面,扩展了随机森林分类器和回归器的功能。现在,在训练每棵树时,分割器会评估每个潜在的阈值,并将缺失值分配到左右节点。更多细节请参考用户指南。
import numpy as np
from sklearn.ensemble import RandomForestClassifier
X = np.array([0, 1, 6, np.nan]).reshape(-1, 1)
y = [0, 0, 1, 1]
forest = RandomForestClassifier(random_state=0).fit(X, y)
forest.predict(X)
输出的预测结果为[0, 0, 1, 1],展示了模型对缺失值的处理能力。此外,还为基于树的模型添加了单调约束的支持,包括树、随机森林、额外树和精确梯度提升。
import matplotlib.pyplot as plt
from sklearn.inspection import PartialDependenceDisplay
from sklearn.ensemble import RandomForestRegressor
n_samples = 500
rng = np.random.RandomState(0)
X = rng.randn(n_samples, 2)
noise = rng.normal(loc=0.0, scale=0.01, size=n_samples)
y = 5 * X[:, 0] + np.sin(10 * np.pi * X[:, 0]) - noise
rf_no_cst = RandomForestRegressor().fit(X, y)
rf_cst = RandomForestRegressor(monotonic_cst=[1, 0]).fit(X, y)
disp = PartialDependenceDisplay.from_estimator(rf_no_cst, X, features=[0], feature_names=["feature 0"], line_kw={"linewidth": 4, "label": "unconstrained", "color": "tab:blue"})
PartialDependenceDisplay.from_estimator(rf_cst, X, features=[0], line_kw={"linewidth": 4, "label": "constrained", "color": "tab:orange"}, ax=disp.axes_)
disp.axes_[0, 0].plot(X[:, 0], y, "o", alpha=0.5, zorder=-1, label="samples", color="tab:green")
disp.axes_[0, 0].set_ylim(-3, 3)
disp.axes_[0, 0].set_xlim(-1, 1)
disp.axes_[0, 0].legend()
plt.show()
以上代码展示了如何在回归问题中使用随机森林模型,并添加了单调约束。图表显示了有无约束条件下的部分依赖图。
还丰富了估计器的显示效果。例如,如果查看上面定义的forest
,在Jupyter环境中重新运行此单元格以显示HTML表示,或者信任笔记本。在GitHub上,HTML表示无法渲染,请尝试使用nbviewer.org加载此页面。
此外,还添加了元数据路由支持,允许在许多元估计器和交叉验证例程中使用。例如,以下是如何使用样本权重和GroupKFold
进行嵌套交叉验证的方法。
import sklearn
from sklearn.metrics import get_scorer
from sklearn.datasets import make_regression
from sklearn.linear_model import Lasso
from sklearn.model_selection import GridSearchCV, cross_validate, GroupKFold
sklearn.set_config(enable_metadata_routing=True)
n_samples = 100
X, y = make_regression(n_samples=n_samples, n_features=5, noise=0.5)
rng = np.random.RandomState(7)
groups = rng.randint(0, 10, size=n_samples)
sample_weights = rng.rand(n_samples)
estimator = Lasso().set_fit_request(sample_weight=True)
hyperparameter_grid = {"alpha": [0.1, 0.5, 1.0, 2.0]}
scoring_inner_cv = get_scorer("neg_mean_squared_error").set_score_request(sample_weight=True)
inner_cv = GroupKFold(n_splits=5)
grid_search = GridSearchCV(estimator=estimator, param_grid=hyperparameter_grid, cv=inner_cv, scoring=scoring_inner_cv)
outer_cv = GroupKFold(n_splits=5)
scorers = {"mse": get_scorer("neg_mean_squared_error").set_score_request(sample_weight=True)}
results = cross_validate(grid_search, X, y, cv=outer_cv, scoring=scorers, return_estimator=True, params={"sample_weight": sample_weights, "groups": groups})
print("cv error on test sets:", results["test_mse"])
输出的测试集上的交叉验证误差为[-0.23496471 -0.27218703 -0.24893252 -0.22341162 -0.42932459],显示了模型在不同测试集上的性能。
最后,改进了PCA处理稀疏数据时的内存和运行时间效率。现在,PCA能够原生地处理稀疏矩阵,通过利用scipy.sparse.linalg.LinearOperator避免在执行数据集协方差矩阵的特征值分解时显式化大型稀疏矩阵。
from sklearn.decomposition import PCA
import scipy.sparse as sp
from time import time
X_sparse = sp.random(m=1000, n=1000, random_state=0)
X_dense = X_sparse.toarray()
t0 = time()
PCA(n_components=10, svd_solver="arpack").fit(X_sparse)
time_sparse = time() - t0
t0 = time()
PCA(n_components=10, svd_solver="arpack").fit(X_dense)
time_dense = time() - t0
print(f"Speedup: {time_dense/time_sparse:.1f}x")
输出的加速比为3.7倍,显示了在处理稀疏数据时PCA的效率提升。脚本的总运行时间为(0分钟4.339秒)。