Skip to content

Scikit Learn - 约定

Scikit-Learn 的对象遵循统一且一致的 API 惯例,通常包含三个互补的接口:

  • 估算器(Estimator)接口:用于根据数据构建和拟合模型。
  • 预测器(Predictor)接口:用于根据拟合好的模型进行预测或推断属性。
  • 转换器(Transformer)接口:用于转换或预处理数据。

这些 API 遵循简单的惯例,其设计选择旨在避免不必要的框架代码,从而提高易用性和互操作性。

这些惯例确保 API 遵循以下广泛原则:

一致性:所有对象,无论是基础的(如 LinearRegression)还是复合的(如 Pipeline),都共享一套有限的方法组成的一致接口(例如 fit()、predict()、transform())。

可检查性:构造函数参数(超参数)和算法学习到的参数值(以单下划线结尾的属性,例如 coef_)都被存储并作为公共属性暴露,方便用户进行检查。

避免类泛滥:数据集通常表示为 NumPy 数组或 SciPy 稀疏矩阵。超参数通常是标准的 Python 类型,如字符串、数字或布尔值。这最大限度地减少了对自定义数据结构的需要。

组合性:可以表示为转换序列或组合的算法,或基于其他算法参数化的元算法,都可以通过现有构建块(例如 Pipeline、FeatureUnion、元估算器如 GridSearchCV)来实现和组合。

合理的默认值:每当某个操作需要用户定义参数时,Scikit-Learn 都会提供一个合适的默认值。这个默认值应该能使操作以合理的方式执行,通常提供一个不错的基线解决方案。

让我们通过一些示例来探索这些惯例:

Scikit-Learn 估算器通常期望输入数据 X 为数值类型,并会尝试将其转换为 float64(对于某些稀疏矩阵操作,可能是 float32)。目标值 y 可以是数值型或分类型,具体取决于任务。

示例:输入数据类型转换。

import numpy as np
from 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: float32
Transformed X_new dtype: float64

在这个示例中,X_float32(dtype 为 float32)在 fit_transform() 内部被转换为 float64。

估算器的超参数可以在实例化后使用 set_params() 方法进行更新。这在模型选择中特别有用(例如结合 GridSearchCV)。在调用 set_params() 后再次调用 fit() 会使用新的参数重新拟合估算器。

示例:更改 SVC 的核函数并重新拟合。

import numpy as np
from sklearn.datasets import load_iris
from 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 refit
clf.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 refit
clf.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: linear
Predictions with RBF kernel (C=0.5): [0 0 0 0 0]
Current kernel: rbf, C: 0.5

这演示了如何使用 set_params() 实现对估算器的动态修改和重新拟合。

Scikit-Learn 根据提供给 fit() 方法的目标数据 y 的格式来处理多类别和多标签分类任务。

对于多类别分类,y 通常是一个包含类别标签的 1D 数组。

示例:使用 1D 目标数组进行 OneVsRestClassifier 多类别分类。

from sklearn.svm import SVC
from sklearn.multiclass import OneVsRestClassifier
from 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 reproducibility
classifier = 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 multilabel
classifier_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 和贡献指南,请查阅开发者文档。