Skip to content

Scikit Learn - Estimator API

本章介绍 Scikit-Learn 中的核心应用程序编程接口(API):估计器 API (Estimator API)。理解这个 API 对于有效使用 Scikit-Learn 至关重要。

在 Scikit-Learn 中,估计器(estimator)是一个从数据中学习的对象。它可以是用于分类(classification)、回归(regression)、聚类(clustering)、降维(dimensionality reduction)的任何算法,甚至是一个用于特征提取或预处理的变换器(transformer)。估计器 API 在如此广泛的机器学习应用中提供了统一的接口,使得在不同模型之间切换变得容易。

所有估计器对象都公开了一个 fit 方法用于从数据中学习。这个方法通常将训练数据(以及监督学习中的标签/目标)作为输入:

estimator.fit(data, targets) # For supervised learning
# 用于监督学习
estimator.fit(data) # For unsupervised learning
# 用于无监督学习

估计器的参数,通常称为超参数(hyperparameters),在创建估计器实例时设置。这些参数可以直接作为估计器对象的属性访问和修改:

from sklearn.linear_model import LogisticRegression
# Instantiate the estimator with desired hyperparameters
# 使用所需的超参数实例化估计器
estimator = LogisticRegression(C=1.0, solver='liblinear')
print(estimator.C) # Accessing a hyperparameter
# 访问超参数

在调用 fit 方法且估计器从数据中学习之后,学习到的参数(例如,模型系数)作为属性存储在估计器对象上。按照约定,这些学习到的属性总是以下划线 (_) 结尾:

# Assuming estimator has been fitted:
# 假设估计器已拟合:
# print(estimator.coef_) # Accessing a learned parameter (e.g., coefficients in LinearRegression)
# 访问学习到的参数 (例如 LinearRegression 中的系数)

估计器在机器学习工作流程中服务于各种目的:

估计器的主要作用是从数据中学习模型。这个学习到的模型的特性由以下因素决定:

  • 实例化时提供的超参数。
  • 全局随机状态(例如 numpy.random),如果估计器的 random_state 参数设置为 None 且算法包含随机性。
  • 传递给最近一次调用 fit, fit_transform, 或 fit_predict 的数据。
  • 对于支持增量学习的估计器,传递给一系列 partial_fit 调用的数据。

拟合完成后,监督式估计器通常有一个 predict() 方法,用于对新的、未见数据进行预测。无监督式估计器可能具有 predict()(用于聚类),transform()(用于降维或特征工程),或 fit_predict()/fit_transform() 方法。

变换器估计器(Transformer estimators)(例如 StandardScaler, PCA, PolynomialFeatures)修改或重塑数据。它们实现 fit() 方法从数据中学习必要的参数(如 StandardScaler 的均值和标准差),并实现 transform() 方法应用变换。方便的方法 fit_transform() 先拟合然后变换数据。

某些估计器设计用于识别离群点或新颖点。它们通常使用 fit() 方法学习正常数据分布,并使用 predict() 或 fit_predict() 方法将样本分类为正常点或离群点。

Scikit-Learn API 设计遵循几个核心原则,以确保可用性和一致性:

所有对象(估计器、变换器等)共享一个由有限方法集(例如 fit, predict, transform)组成的通用接口。文档和命名约定也保持一致。

有限对象层级和标准数据格式 (Limited Object Hierarchy & Standard Data Formats)

Section titled “有限对象层级和标准数据格式 (Limited Object Hierarchy & Standard Data Formats)”

Scikit-Learn 遵循以下约定:

  • 算法由 Python 类表示。
  • 数据集主要期望为 NumPy 数组、Pandas DataFrames 或 SciPy 稀疏矩阵。
  • 超参数作为参数传递给构造函数,它们的名称是标准的 Python 字符串。

许多复杂的机器学习工作流程可以通过组合更简单的构建块来构建。Scikit-Learn 的 Pipeline 对象就是一个典型的例子,它允许将多个估计器串联起来。

估计器为其超参数提供了合理的默认值,允许用户无需进行大量调优即可获得合理的基础结果。

实例化期间指定的所有超参数值以及所有学习到的参数(以下划线 _ 结尾)都作为公共属性公开,以便轻松检查估计器的状态。

使用 Scikit-Learn 估计器的典型工作流程包括以下步骤:

从 Scikit-Learn 导入适当的估计器类。例如,from sklearn.linear_model import LinearRegression。

步骤 2: 实例化估计器并选择超参数

Section titled “步骤 2: 实例化估计器并选择超参数”

创建所选类的一个实例,并设置任何所需的超参数。例如,model = LinearRegression(fit_intercept=True)。

将您的数据组织成特征矩阵(通常是 X),对于监督学习,还需要目标向量(y)。X 通常是二维数组(样本数,特征数),y 是一维数组(样本数)。

调用模型实例的 fit() 方法,传入您的训练数据。例如,model.fit(X_train, y_train)。

对于监督学习,使用 predict() 方法对新的、未见数据进行预测。例如,predictions = model.predict(X_test)。对于无监督学习,您可能根据任务使用 transform() 或 predict()。

监督学习示例:线性回归 (Linear Regression)

Section titled “监督学习示例:线性回归 (Linear Regression)”

让我们用一个简单的线性回归示例来说明这些步骤,将一条直线拟合到 (x, y) 数据上。

首先,我们将生成一些样本数据。我们也将展示如何加载像 Iris 这样的数据集作为背景,尽管我们的线性回归将使用合成数据。

数据准备(Iris 加载示例,仅作说明)

Section titled “数据准备(Iris 加载示例,仅作说明)”
import seaborn as sns
import pandas as pd
# Load Iris dataset using seaborn (returns a Pandas DataFrame)
# 使用 seaborn 加载 Iris 数据集 (返回 Pandas DataFrame)
# iris_df = sns.load_dataset('iris')
# X_iris = iris_df.drop('species', axis=1)
# y_iris = iris_df['species']
# print(f"Iris features shape: {X_iris.shape}")
# print(f"Iris target shape: {y_iris.shape}")

Iris 加载的输出(如果取消注释):

Iris features shape: (150, 4)
Iris target shape: (150,)

现在,让我们使用合成数据继续进行线性回归步骤:

# For plotting in Jupyter notebooks, you might use: %matplotlib inline
# 在 Jupyter Notebook 中绘图,您可能使用: %matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
# Generate synthetic data
# 生成合成数据
rng = np.random.RandomState(35)
x = 10 * rng.rand(40)
y = 2 * x - 1 + rng.randn(40) # y = 2x - 1 + noise
# y = 2x - 1 + 噪声
# Plot the raw data
# 绘制原始数据
# plt.scatter(x, y)
# plt.title('Synthetic Data for Linear Regression')
# plt.xlabel('x')
# plt.ylabel('y')
# plt.show()

该图将显示大致沿向上线性趋势分布的点。

我们将使用 LinearRegression:

from sklearn.linear_model import LinearRegression

我们将实例化 LinearRegression,并保持 fit_intercept=True(这是默认值)。normalize 参数已弃用;如果需要特征缩放,应使用像 StandardScaler 这样的预处理器完成。

model = LinearRegression(fit_intercept=True)
print(model)

输出:

LinearRegression()
# (Older versions might show: LinearRegression(copy_X=True, fit_intercept=True, n_jobs=None, normalize=False))
# (旧版本可能显示: LinearRegression(copy_X=True, fit_intercept=True, n_jobs=None, normalize=False))

我们的目标 y 已经是一个一维数组。我们的特征 x 也是一维的,但 Scikit-Learn 期望 X(特征矩阵)是二维的 [n_samples, n_features]。我们重塑 x:

X = x[:, np.newaxis] # Reshape x to be a 2D column vector
# 将 x 重塑为二维列向量
print(f"Shape of X: {X.shape}")

输出:

Shape of X: (40, 1)

将模型拟合到我们的数据 (X, y) 上:

model.fit(X, y)

拟合后,模型学习到了一些参数,这些参数以下划线结尾存储。对于 LinearRegression:

print(f"Learned coefficient (slope): {model.coef_}")
# 学习到的系数 (斜率)
print(f"Learned intercept: {model.intercept_}")
# 学习到的截距

输出(值将接近 2 和 -1):

Learned coefficient (slope): [1.99839352]
Learned intercept: -0.9895459457775022

5. 将模型应用于新数据(预测)

Section titled “5. 将模型应用于新数据(预测)”

我们现在可以预测新 x 值的 y 值:

xfit = np.linspace(-1, 11, 50) # Generate new x values for prediction
# 生成用于预测的新 x 值
Xfit = xfit[:, np.newaxis] # Reshape for Scikit-Learn
# 为 Scikit-Learn 重塑
yfit = model.predict(Xfit) # Predict y values
# 预测 y 值
# Plot the original data and the fitted line
# 绘制原始数据和拟合线
# plt.scatter(x, y, label='Original data')
# plt.plot(xfit, yfit, color='red', label='Fitted line')
# plt.title('Linear Regression Fit')
# plt.xlabel('x')
# plt.ylabel('y')
# plt.legend()
# plt.show()

该图将显示原始散点,以及代表线性模型拟合的一条红色直线,该直线穿过数据。

import matplotlib.pyplot as plt
import numpy as np
from sklearn.linear_model import LinearRegression
# Generate synthetic data
# 生成合成数据
rng = np.random.RandomState(35)
x = 10 * rng.rand(40)
y = 2 * x - 1 + rng.randn(40)
# 1. Choose model & 2. Instantiate with hyperparameters
# 1. 选择模型 & 2. 实例化并设置超参数
model = LinearRegression(fit_intercept=True)
# 3. Arrange data
# 3. 整理数据
X = x[:, np.newaxis]
# 4. Fit model
# 4. 拟合模型
model.fit(X, y)
print(f"Slope: {model.coef_}, Intercept: {model.intercept_}")
# 斜率: {model.coef_}, 截距: {model.intercept_}
# 5. Predict on new data
# 5. 在新数据上预测
xfit = np.linspace(-1, 11, 50)
Xfit = xfit[:, np.newaxis]
yfit = model.predict(Xfit)
# Visualization
# 可视化
# plt.scatter(x, y)
# plt.plot(xfit, yfit, color='red')
# plt.title('Linear Regression Example')
# plt.show()

无监督学习示例:主成分分析 (Principal Component Analysis, PCA)

Section titled “无监督学习示例:主成分分析 (Principal Component Analysis, PCA)”

让我们使用 PCA 来降低 Iris 数据集的维度,这是一个无监督学习任务。

import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from sklearn.datasets import load_iris # Using scikit-learn's direct loader
# 使用 scikit-learn 的直接加载器
# Load Iris dataset
# 加载 Iris 数据集
iris = load_iris()
X_iris = iris.data
y_iris_labels = iris.target # Numerical labels
# 数值标签
species_names = iris.target_names
# 类别名称
print(f"Original Iris data shape: {X_iris.shape}")
# 原始 Iris 数据形状

输出:

Original Iris data shape: (150, 4)
# Already imported: from sklearn.decomposition import PCA
# 已经导入: from sklearn.decomposition import PCA

我们将降维到 2 个主成分以便可视化:

model_pca = PCA(n_components=2, random_state=42) # random_state for SVD solver if applicable
# 如果适用,random_state 用于 SVD 求解器
print(model_pca)

输出(可能因版本略有差异):

PCA(n_components=2, random_state=42)

X_iris 已经是正确的 [n_samples, n_features] 格式。无监督 PCA 拟合不需要目标 y。

model_pca.fit(X_iris)

学习到的参数包括 components_ 和 explained_variance_ratio_。

print(f"Explained variance ratio by 2 components: {model_pca.explained_variance_ratio_}")
# 2 个主成分解释的方差比例

输出(示例):

Explained variance ratio by 2 components: [0.92461872 0.05306648]

使用 transform 方法:

X_2D = model_pca.transform(X_iris)
print(f"Transformed data shape: {X_2D.shape}")
# 变换后的数据形状

输出:

Transformed data shape: (150, 2)

现在,我们可以可视化二维数据,并按类别着色:

# Create a DataFrame for easier plotting with Seaborn
# 创建一个 DataFrame 以便使用 Seaborn 更轻松地绘图
iris_2D_df = pd.DataFrame(data=X_2D, columns=['PCA1', 'PCA2'])
iris_2D_df['species'] = [species_names[label] for label in y_iris_labels]
# Plot using Seaborn
# 使用 Seaborn 绘图
# sns.lmplot(x="PCA1", y="PCA2", hue='species', data=iris_2D_df, fit_reg=False, height=6)
# plt.title('Iris Dataset after PCA (2 Components)')
# plt.show()

该图将显示 Iris 样本投影到两个主成分上,并按不同类别着色,通常会显示类别之间有良好的分离。

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from sklearn.datasets import load_iris
# Load Iris dataset
# 加载 Iris 数据集
iris = load_iris()
X_iris = iris.data
y_iris_labels = iris.target
species_names = iris.target_names
# 1. & 2. Choose model and instantiate
# 1. & 2. 选择模型并实例化
model_pca = PCA(n_components=2, random_state=42)
# 3. Data is X_iris (no y for unsupervised fit)
# 3. 数据是 X_iris (无监督拟合不需要 y)
# 4. Fit model
# 4. 拟合模型
model_pca.fit(X_iris)
# 5. Transform data
# 5. 变换数据
X_2D = model_pca.transform(X_iris)
# Visualization
# 可视化
# iris_2D_df = pd.DataFrame(data=X_2D, columns=['PCA1', 'PCA2'])
# iris_2D_df['species'] = [species_names[label] for label in y_iris_labels]
# sns.lmplot(x="PCA1", y="PCA2", hue='species', data=iris_2D_df, fit_reg=False, height=6)
# plt.title('PCA of Iris Dataset')
# plt.show()

有关 Scikit-Learn API 设计和用法的更多详细信息,请参阅Scikit-Learn API 文档。