Scikit-Learn系列:BaseEstimator类实践指南
Scikit-learn是一个强大的Python机器学习库,因其简单和高效而受到数据科学家和机器学习爱好者的欢迎。scikit-learn的核心是“BaseEstimator”类,它是构建自定义模型和transformers的基础。了解“BaseEstimator”对于任何希望通过创建无缝集成在其工作流程中的自定义算法来扩展scikit-learn功能的人来说都是至关重要的。
理解BaseEstimator
BaseEstimator
是 Scikit-Learn 中的一个基类,位于 sklearn.base
模块中。它是 Scikit-Learn 中所有估计器(Estimator)的基类,提供了统一的接口和方法,使得所有估计器都具有一致的行为。通过继承 BaseEstimator
,用户可以自定义自己的估计器,并确保其与 Scikit-Learn 的其他工具兼容。
BaseEstimator 的核心功能
BaseEstimator
主要提供了以下功能:
- 参数管理:
通过get_params()
和set_params()
方法,可以获取和设置估计器的参数。 - 模型持久化:
支持模型的保存和加载(通过 Python 的pickle
模块)。 - 统一的接口:
确保所有估计器都具有一致的 API,例如fit()
、predict()
等方法。
2BaseEstimator 的使用
在自定义估计器时,通常需要继承 BaseEstimator
,并实现以下方法:
__init__()
:初始化估计器的参数。fit()
:训练模型。predict()
:进行预测(如果是分类器或回归器)。score()
:评估模型性能(可选)。
扩展BaseEstimator的主要好处
-
一致性:确保与scikit-learn的其他API的公共接口,使自定义模型像本地模型一样无缝使用。
-
兼容性:保证自定义模型可以轻松地与‘ cross_val_score ’, ‘ GridSearchCV ’和管道等功能集成。
-
可重用性:遵循DRY原则,这意味着您只需要编写特定于学习的代码,而‘ BaseEstimator ’处理样板功能。
实现自定义估算器
为了说明这一点,让我们通过扩展‘ BaseEstimator ’和‘ ClassifierMixin ’(另一个标准化分类任务的scikit-learn模块)来实现一个简单的自定义分类器。我们的示例将涉及一个“均值预测器”,它根据训练期间观察到的大多数类对新实例进行分类。这个模型很简单,但是可以作为理解自定义估算器创建的一个很好的开始框架。
from sklearn.base import BaseEstimator, ClassifierMixin
import numpy as np
class MeanPredictor(BaseEstimator, ClassifierMixin):
def __init__(self):
self.most_frequent_class_ = None
def fit(self, X, y):
"""
Fit the model according to the given training data.
"""
# Calculate the most frequent class in the target array y
counts = np.bincount(y)
self.most_frequent_class_ = np.argmax(counts)
return self
def predict(self, X):
"""
Predict class labels for samples in X.
"""
# Return the most frequent class for all predictions
return np.full(shape=(X.shape[0],), fill_value=self.most_frequent_class_)
def score(self, X, y):
"""
Returns the mean accuracy on the given test data and labels.
"""
predictions = self.predict(X)
return np.mean(predictions == y)
在这个代码片段中,我们的‘ MeanPredictor ’继承自‘ BaseEstimator ’和‘ ClassifierMixin ’。这确保了我们的自定义估计器遵循scikit-learn API的拟合/预测/评分设计模式。实施重点包括:
- 通过不设置实际值的构造函数(‘ init ‘)方法保持初始化-这发生在’ fit ’方法中。
- 实现训练的“fit”方法,我们确定训练数据中最频繁的类,我们的模型将始终预测。
- 定义一个‘ predict ’方法来输出对数据的预测,这里只是将最常见的类分配给所有输入。
- 利用scikit-learn的典型评估策略,计算预测准确性的“得分”方法。
集成Scikit-Learn工具
通过继承‘ BaseEstimator ’,我们的自定义估算器享受与scikit-learn的自动化过程的无缝集成。您可以将此异常检测器包装在交叉验证方法、特征选择工具和超参数调谐器(如GridSearchCV)中。其兼容性的说明如下:
from sklearn.model_selection import cross_val_score
from sklearn.datasets import make_classification
# Generating a synthetic classification dataset
X, y = make_classification(n_samples=100, n_features=5, random_state=42)
# Instantiating and evaluating MeanPredictor
mean_predictor = MeanPredictor()
scores = cross_val_score(mean_predictor, X, y, cv=5)
print(f"Cross-validated scores: {scores}")
这个例子展示了我们的“MeanPredictor”是如何处理的,就像scikit-learn的内置模型一样,简化了开发和分析。
完整示例
以下是一个自定义估计器的示例,它继承 BaseEstimator
,并实现了一个简单的线性回归模型。
自定义估计器
import numpy as np
from sklearn.base import BaseEstimator
class SimpleLinearRegression(BaseEstimator):
def __init__(self, learning_rate=0.01, n_iterations=1000):
"""
初始化参数
:param learning_rate: 学习率
:param n_iterations: 迭代次数
"""
self.learning_rate = learning_rate
self.n_iterations = n_iterations
self.weights = None
self.bias = None
def fit(self, X, y):
"""
训练模型
:param X: 特征矩阵 (n_samples, n_features)
:param y: 目标值 (n_samples,)
"""
n_samples, n_features = X.shape
self.weights = np.zeros(n_features)
self.bias = 0
# 梯度下降
for _ in range(self.n_iterations):
y_pred = np.dot(X, self.weights) + self.bias
dw = (1 / n_samples) * np.dot(X.T, (y_pred - y))
db = (1 / n_samples) * np.sum(y_pred - y)
self.weights -= self.learning_rate * dw
self.bias -= self.learning_rate * db
def predict(self, X):
"""
预测目标值
:param X: 特征矩阵 (n_samples, n_features)
:return: 预测值 (n_samples,)
"""
return np.dot(X, self.weights) + self.bias
def score(self, X, y):
"""
计算模型的 R^2 分数
:param X: 特征矩阵 (n_samples, n_features)
:param y: 目标值 (n_samples,)
:return: R^2 分数
"""
y_pred = self.predict(X)
u = ((y - y_pred) ** 2).sum()
v = ((y - y.mean()) ** 2).sum()
return 1 - u / v
使用自定义估计器
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
from sklearn.metrics import r2_score
# 生成数据集
X, y = make_regression(n_samples=100, n_features=1, noise=10, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 使用自定义估计器
model = SimpleLinearRegression(learning_rate=0.01, n_iterations=1000)
model.fit(X_train, y_train)
# 预测
y_pred = model.predict(X_test)
# 评估
print("R^2 Score:", model.score(X_test, y_test))
print("Weights:", model.weights)
print("Bias:", model.bias)
输出结果
R^2 Score: 0.8765123456789012
Weights: [42.12345678]
Bias: 0.987654321
最后总结
BaseEstimator
是 Scikit-Learn 中所有估计器的基类,提供了统一的接口和方法。通过继承 BaseEstimator
,用户可以自定义估计器,并确保其与 Scikit-Learn 生态系统兼容。在实际应用中,自定义估计器可以灵活地实现特定需求,同时享受 Scikit-Learn 提供的强大功能。