Scikit Learn - 约定
Scikit-Learn - API 惯例
Section titled “Scikit-Learn - API 惯例”Scikit-Learn 的对象遵循统一且一致的 API 惯例,通常包含三个互补的接口:
- 估算器(Estimator)接口:用于根据数据构建和拟合模型。
- 预测器(Predictor)接口:用于根据拟合好的模型进行预测或推断属性。
- 转换器(Transformer)接口:用于转换或预处理数据。
这些 API 遵循简单的惯例,其设计选择旨在避免不必要的框架代码,从而提高易用性和互操作性。
这些惯例确保 API 遵循以下广泛原则:
一致性:所有对象,无论是基础的(如 LinearRegression)还是复合的(如 Pipeline),都共享一套有限的方法组成的一致接口(例如 fit()、predict()、transform())。
可检查性:构造函数参数(超参数)和算法学习到的参数值(以单下划线结尾的属性,例如 coef_)都被存储并作为公共属性暴露,方便用户进行检查。
避免类泛滥:数据集通常表示为 NumPy 数组或 SciPy 稀疏矩阵。超参数通常是标准的 Python 类型,如字符串、数字或布尔值。这最大限度地减少了对自定义数据结构的需要。
组合性:可以表示为转换序列或组合的算法,或基于其他算法参数化的元算法,都可以通过现有构建块(例如 Pipeline、FeatureUnion、元估算器如 GridSearchCV)来实现和组合。
合理的默认值:每当某个操作需要用户定义参数时,Scikit-Learn 都会提供一个合适的默认值。这个默认值应该能使操作以合理的方式执行,通常提供一个不错的基线解决方案。
实践中的关键惯例
Section titled “实践中的关键惯例”让我们通过一些示例来探索这些惯例:
类型转换和数据格式
Section titled “类型转换和数据格式”Scikit-Learn 估算器通常期望输入数据 X 为数值类型,并会尝试将其转换为 float64(对于某些稀疏矩阵操作,可能是 float32)。目标值 y 可以是数值型或分类型,具体取决于任务。
示例:输入数据类型转换。
import numpy as npfrom sklearn.random_projection import GaussianRandomProjection
rng = np.random.RandomState(0)X_float32 = rng.rand(10, 2000).astype(np.float32)print(f"Original X dtype: {X_float32.dtype}")
transformer = GaussianRandomProjection(random_state=42)X_new = transformer.fit_transform(X_float32)print(f"Transformed X_new dtype: {X_new.dtype}")输出:
Original X dtype: float32Transformed X_new dtype: float64在这个示例中,X_float32(dtype 为 float32)在 fit_transform() 内部被转换为 float64。
重新拟合和更新参数
Section titled “重新拟合和更新参数”估算器的超参数可以在实例化后使用 set_params() 方法进行更新。这在模型选择中特别有用(例如结合 GridSearchCV)。在调用 set_params() 后再次调用 fit() 会使用新的参数重新拟合估算器。
示例:更改 SVC 的核函数并重新拟合。
import numpy as npfrom sklearn.datasets import load_irisfrom sklearn.svm import SVC
X, y = load_iris(return_X_y=True)clf = SVC(gamma='scale', random_state=0) # Initial gamma='scale' uses rbf kernel by default
# Change kernel to 'linear' and refitclf.set_params(kernel='linear').fit(X, y)predictions_linear = clf.predict(X[:5])print(f"Predictions with linear kernel: {predictions_linear}")print(f"Current kernel: {clf.kernel}")
# Change kernel back to 'rbf' (or another) and refitclf.set_params(kernel='rbf', C=0.5).fit(X, y)predictions_rbf = clf.predict(X[:5])print(f"Predictions with RBF kernel (C=0.5): {predictions_rbf}")print(f"Current kernel: {clf.kernel}, C: {clf.C}")输出:
Predictions with linear kernel: [0 0 0 0 0]Current kernel: linearPredictions with RBF kernel (C=0.5): [0 0 0 0 0]Current kernel: rbf, C: 0.5这演示了如何使用 set_params() 实现对估算器的动态修改和重新拟合。
多类别和多标签拟合
Section titled “多类别和多标签拟合”Scikit-Learn 根据提供给 fit() 方法的目标数据 y 的格式来处理多类别和多标签分类任务。
对于多类别分类,y 通常是一个包含类别标签的 1D 数组。
示例:使用 1D 目标数组进行 OneVsRestClassifier 多类别分类。
from sklearn.svm import SVCfrom sklearn.multiclass import OneVsRestClassifierfrom sklearn.preprocessing import LabelBinarizer
X_multi = np.array([[1, 2], [3, 4], [4, 5], [5, 2], [1, 1], [2,5]])y_multi_1d = np.array([0, 0, 1, 1, 2, 1]) # 3 classes: 0, 1, 2
# Using OneVsRestClassifier with an SVC estimator# gamma='scale' and random_state for reproducibilityclassifier = OneVsRestClassifier(estimator=SVC(gamma='scale', random_state=0))classifier.fit(X_multi, y_multi_1d)predictions_1d_target = classifier.predict(X_multi)print(f"Predictions (1D target): {predictions_1d_target}")输出:
Predictions (1D target): [0 0 1 1 2 1]或者,对于某些分类器或元估算器,y 可以是一个 2D 的二元标签指示矩阵(每列代表一个类别)。LabelBinarizer 可以创建这种格式。
y_multi_2d = LabelBinarizer().fit_transform(y_multi_1d)print(f"Binarized y (first 3 rows):\n{y_multi_2d[:3]}")
classifier_2d_target = OneVsRestClassifier(estimator=SVC(gamma='scale', random_state=0))classifier_2d_target.fit(X_multi, y_multi_2d)predictions_2d_target = classifier_2d_target.predict(X_multi)print(f"Predictions (2D target, first 3 rows):\n{predictions_2d_target[:3]}")输出:
Binarized y (first 3 rows):[[1 0 0] [1 0 0] [0 1 0]]Predictions (2D target, first 3 rows):[[1 0 0] [1 0 0] [0 1 0]]对于多标签分类,其中每个实例可以被分配多个标签,y 必须是一个 2D 的二元指示矩阵。MultiLabelBinarizer 用于此目的。
示例:多标签分类。
from sklearn.preprocessing import MultiLabelBinarizer# Sample multilabel data (list of lists/tuples of labels)y_multilabel_list = [[0, 1], [0, 2], [1, 3], [0, 2, 3], [2, 4], [1,4]]X_multilabel = X_multi # Reusing X_multi for simplicity
y_multilabel_2d = MultiLabelBinarizer().fit_transform(y_multilabel_list)print(f"Binarized multilabel y (first 3 rows):\n{y_multilabel_2d[:3]}")
# Using the same OneVsRestClassifier setup for multilabelclassifier_multilabel = OneVsRestClassifier(estimator=SVC(gamma='scale', random_state=0))classifier_multilabel.fit(X_multilabel, y_multilabel_2d)predictions_multilabel = classifier_multilabel.predict(X_multilabel)print(f"Predictions (multilabel, first 3 rows):\n{predictions_multilabel[:3]}")输出:
Binarized multilabel y (first 3 rows):[[1 1 0 0 0] [1 0 1 0 0] [0 1 0 1 0]]Predictions (multilabel, first 3 rows):[[1 1 0 0 0] [1 0 1 0 0] [0 1 0 1 0]]这些惯例使得 Scikit-Learn 成为一个多功能且用户友好的库。要更深入地了解 Scikit-Learn 的 API 和贡献指南,请查阅开发者文档。