入门指南#
本指南旨在展示 scikit-learn
提供的一些主要功能。它假设读者具有机器学习实践的基本知识(如模型拟合、预测、交叉验证等)。请参考我们的 installation instructions 来安装 scikit-learn
。
Scikit-learn
是一个支持监督学习和无监督学习的开源机器学习库。它还提供了各种工具,用于模型拟合、数据预处理、模型选择、模型评估以及其他许多实用功能。
拟合和预测:估计器基础#
Scikit-learn
提供了数十种内置的机器学习算法和模型,称为 estimators 。每个估计器都可以使用其 fit 方法拟合到某些数据上。
以下是一个简单示例,我们将一个 RandomForestClassifier
拟合到一些非常基本的数据上:
>>> from sklearn.ensemble import RandomForestClassifier
>>> clf = RandomForestClassifier(random_state=0)
>>> X = [[ 1, 2, 3], # 2 个样本, 3 个特征
... [11, 12, 13]]
>>> y = [0, 1] # 每个样本的类别
>>> clf.fit(X, y)
RandomForestClassifier(random_state=0)
fit 方法通常接受 2 个输入:
样本矩阵(或设计矩阵) X 。
X
的大小通常是(n_samples, n_features)
,这意味着样本表示为行,特征表示为列。目标值 y ,对于回归任务是实数,对于分类任务是整数(或任何其他离散值集合)。对于无监督学习任务,
y
不需要指定。y
通常是一个一维数组,其中第i
个条目对应于X
的第i
个样本(行)的目标。
X
和y
通常期望是 numpy 数组或等效的 类数组 数据类型,尽管某些估计器支持其他格式,如稀疏矩阵。
一旦估计器被拟合,它就可以用于预测新数据的目标值。您不需要重新训练估计器:
>>> clf.predict(X) # 预测训练数据的类别
array([0, 1])
>>> clf.predict([[4, 5, 6], [14, 15, 16]]) # 预测新数据的类别
array([0, 1])
您可以查看 选择合适的估计器 来了解如何为您的用例选择合适的模型。
转换器和预处理器#
机器学习工作流程通常由不同的部分组成。一个典型的管道包括一个预处理步骤,该步骤转换或填充数据,以及一个最终的预测器,用于预测目标值。
在 scikit-learn
中,预处理器和转换器遵循与估计器对象相同的 API(实际上它们都继承自同一个 BaseEstimator
类)。转换器对象没有 predict 方法,而是有一个 transform 方法,该方法输出一个新的转换样本矩阵 X
>>> from sklearn.preprocessing import StandardScaler
>>> X = [[0, 15],
... [1, -10]]
>>> # 根据计算的缩放值缩放数据
>>> StandardScaler().fit(X).transform(X)
array([[-1., 1.],
[ 1., -1.]])
有时,您希望对不同的特征应用不同的转换:ColumnTransformer 正是为此类用例设计的。
管道:链接预处理器和估计器#
转换器和估计器(预测器)可以组合在一起成为一个单一的统一对象:Pipeline
。管道提供的 API 与常规估计器相同:可以使用 fit
和 predict
进行拟合和预测。正如我们稍后将看到的,使用管道还可以防止数据泄露,即在训练数据中披露一些测试数据。
在以下示例中,我们 load the Iris dataset ,将其拆分为训练集和测试集,并在测试数据上计算管道的准确性得分:
>>> from sklearn.preprocessing import StandardScaler
>>> from sklearn.linear_model import LogisticRegression
>>> from sklearn.pipeline import make_pipeline
>>> from sklearn.datasets import load_iris
>>> from sklearn.model_selection import train_test_split
>>> from sklearn.metrics import accuracy_score
...
>>> # 创建一个管道对象
>>> pipe = make_pipeline(
... StandardScaler(),
... LogisticRegression()
... )
...
>>> # 加载鸢尾花数据集并将其拆分为训练集和测试集
>>> X, y = load_iris(return_X_y=True)
>>> X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
...
>>> # 拟合整个管道
>>> pipe.fit(X_train, y_train)
Pipeline(steps=[('standardscaler', StandardScaler()),
('logisticregression', LogisticRegression())])
>>> # 我们现在可以像使用其他估计器一样使用它
>>> accuracy_score(pipe.predict(X_test), y_test)
0.97...
模型评估#
将模型拟合到某些数据并不意味着它将在未见数据上预测良好。这需要直接进行评估。我们刚刚看到了 :func:` ~sklearn.model_selection.train_test_split`助手,它将数据集拆分为训练集和测试集,但 scikit-learn
还提供了许多其他用于模型评估的工具,特别是用于 交叉验证 。
我们在这里简要展示如何使用 cross_validate
助手执行 5 折交叉验证过程。请注意,也可以手动遍历折叠,使用不同的数据拆分策略,并使用自定义评分函数。请参阅我们的 User Guide 了解更多详细信息:
>>> from sklearn.datasets import make_regression
>>> from sklearn.linear_model import LinearRegression
>>> from sklearn.model_selection import cross_validate
...
>>> X, y = make_regression(n_samples=1000, random_state=0)
>>> lr = LinearRegression()
...
>>> result = cross_validate(lr, X, y) # 默认为 5 折交叉验证
>>> result['test_score'] # r_squared 得分高是因为数据集简单
array([1., 1., 1., 1., 1.])
自动参数搜索#
所有估计器都有参数(在文献中通常称为超参数),这些参数可以进行调整。估计器的泛化能力通常在很大程度上取决于少数几个参数。例如,RandomForestRegressor
有一个 n_estimators
参数,用于确定森林中的树的数量,还有一个 max_depth
参数,用于确定每棵树的最大深度。通常,这些参数的确切值并不清楚,因为它们取决于手头的数据。
Scikit-learn
提供了工具来自动找到最佳的参数组合(通过交叉验证)。在以下示例中,我们随机搜索随机森林的参数空间,使用RandomizedSearchCV
对象。当搜索结束时,RandomizedSearchCV
的行为就像一个已经拟合了最佳参数集的RandomForestRegressor
。更多详细信息请参阅 User Guide>>> from sklearn.datasets import fetch_california_housing >>> from sklearn.ensemble import RandomForestRegressor >>> from sklearn.model_selection import RandomizedSearchCV >>> from sklearn.model_selection import train_test_split >>> from scipy.stats import randint ... >>> X, y = fetch_california_housing(return_X_y=True) >>> X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0) ... >>> # 定义将要搜索的参数空间 >>> param_distributions = {'n_estimators': randint(1, 5), ... 'max_depth': randint(5, 10)} ... >>> # 现在创建一个 searchCV 对象并将其拟合到数据上 >>> search = RandomizedSearchCV(estimator=RandomForestRegressor(random_state=0), ... n_iter=5, ... param_distributions=param_distributions, ... random_state=0) >>> search.fit(X_train, y_train) RandomizedSearchCV(estimator=RandomForestRegressor(random_state=0), n_iter=5, param_distributions={'max_depth': ..., 'n_estimators': ...}, random_state=0) >>> search.best_params_ {'max_depth': 9, 'n_estimators': 4} >>> # 现在 search 对象表现得像一个普通的随机森林估计器 >>> # 具有 max_depth=9 和 n_estimators=4 >>> search.score(X_test, y_test) 0.73...
在实践中,你几乎总是希望对一个管道(pipeline)进行搜索,而不是单个估计器。主要原因之一是,如果你对整个数据集应用预处理步骤而不使用管道,然后进行任何形式的交叉验证,你将破坏训练数据和测试数据之间独立性的基本假设。实际上,由于你使用整个数据集对数据进行了预处理,一些关于测试集的信息已经对训练集可用。这将导致过高估计估计器的泛化能力(你可以在 Kaggle post 中了解更多信息)。
使用管道进行交叉验证和搜索将大大避免这种常见陷阱。
下一步#
我们已经简要介绍了估计器拟合和预测、预处理步骤、管道、交叉验证工具和自动超参数搜索。本指南应该让您对库的一些主要功能有一个概览,但 scikit-learn
还有更多内容!
请参阅我们的 用户指南 以获取我们提供的所有工具的详细信息。您还可以在 API参考 中找到公共API的详尽列表。
您还可以查看我们众多的 示例,这些示例在许多不同的上下文中展示了``scikit-learn``的使用。