Sklearn 自定义模型与功能
在 Scikit-learn(sklearn)中,自定义模型与功能允许用户扩展现有功能,创建符合特定需求的模型或数据处理步骤。这对于实现非标准算法、自定义预处理或集成特定业务逻辑非常有用。以下是关于 Scikit-learn 自定义模型与功能 的详细指南,涵盖核心概念、实现方法、代码示例和最佳实践,力求简洁清晰。
一、自定义模型与功能的核心概念
- 自定义模型:通过继承 Scikit-learn 的基类(如
BaseEstimator和ClassifierMixin/RegressorMixin),实现自定义机器学习模型,兼容 sklearn 的接口(如fit、predict)。 - 自定义转换器:通过继承
BaseEstimator和TransformerMixin,实现自定义数据预处理或特征工程步骤,兼容fit和transform。 - Pipeline 集成:自定义模型和转换器可无缝嵌入 Pipeline,与其他 sklearn 工具(如 GridSearchCV)结合。
- 关键基类:
BaseEstimator:提供参数管理和get_params/set_params方法。TransformerMixin:自动实现fit_transform方法。ClassifierMixin/RegressorMixin:为分类/回归模型提供默认的score方法。ClusterMixin:为聚类模型提供标准接口。
二、实现自定义转换器
自定义转换器用于数据预处理或特征工程,需实现 fit 和 transform 方法。
2.1 基本自定义转换器
示例:创建一个将特征值乘以指定因子的转换器。
from sklearn.base import BaseEstimator, TransformerMixin
class FeatureMultiplier(BaseEstimator, TransformerMixin):
def __init__(self, factor=2):
self.factor = factor
def fit(self, X, y=None):
# 不需要训练,直接返回 self
return self
def transform(self, X):
# 将特征值乘以 factor
return X * self.factor
# 使用示例
import numpy as np
X = np.array([[1, 2], [3, 4]])
transformer = FeatureMultiplier(factor=3)
X_transformed = transformer.fit_transform(X)
print(X_transformed)
# 输出: [[3 6]
# [9 12]]
2.2 在 Pipeline 中使用
自定义转换器可直接嵌入 Pipeline:
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
# 数据准备
iris = load_iris()
X, y = iris.data, iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建 Pipeline
pipeline = Pipeline([
('multiplier', FeatureMultiplier(factor=2)), # 自定义转换器
('scaler', StandardScaler()), # 标准化
('classifier', LogisticRegression(random_state=42))
])
# 训练和预测
pipeline.fit(X_train, y_train)
y_pred = pipeline.predict(X_test)
print(f"Accuracy: {accuracy_score(y_test, y_pred):.3f}")
三、实现自定义模型
自定义模型用于实现非标准算法,需实现 fit 和 predict 方法(分类模型还需 predict_proba)。
3.1 自定义分类模型
示例:实现一个简单的最近质心分类器(基于最近均值分类)。
from sklearn.base import BaseEstimator, ClassifierMixin
from sklearn.metrics import pairwise_distances_argmin
class NearestCentroidClassifier(BaseEstimator, ClassifierMixin):
def __init__(self):
pass
def fit(self, X, y):
# 计算每个类别的均值(质心)
self.classes_ = np.unique(y)
self.centroids_ = np.array([X[y == c].mean(axis=0) for c in self.classes_])
return self
def predict(self, X):
# 预测样本所属的最近质心类别
return self.classes_[pairwise_distances_argmin(X, self.centroids_)]
def score(self, X, y):
# 默认使用准确率
return accuracy_score(y, self.predict(X))
# 使用示例
from sklearn.datasets import load_iris
iris = load_iris()
X, y = iris.data, iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
model = NearestCentroidClassifier()
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
print(f"Accuracy: {model.score(X_test, y_test):.3f}")
输出示例:
Accuracy: 0.967
3.2 自定义回归模型
示例:实现一个简单线性回归(仅单特征)。
from sklearn.base import RegressorMixin
class SimpleLinearRegression(BaseEstimator, RegressorMixin):
def __init__(self):
pass
def fit(self, X, y):
# 假设 X 是单特征,计算斜率和截距
x_mean = np.mean(X)
y_mean = np.mean(y)
self.slope_ = np.sum((X - x_mean) * (y - y_mean)) / np.sum((X - x_mean) ** 2)
self.intercept_ = y_mean - self.slope_ * x_mean
return self
def predict(self, X):
return self.slope_ * X + self.intercept_
# 使用示例
X = np.array([[1], [2], [3], [4]])
y = np.array([2, 4, 5, 4])
model = SimpleLinearRegression()
model.fit(X, y)
print(f"Predictions: {model.predict(X).ravel()}")
输出示例:
Predictions: [2.2 3.3 4.4 5.5]
四、与 Pipeline 和 GridSearchCV 结合
自定义模型和转换器可无缝集成到 Pipeline,并通过 GridSearchCV 调优参数。
示例:调优自定义转换器和模型
# 自定义转换器(带参数)
class FeatureMultiplier(BaseEstimator, TransformerMixin):
def __init__(self, factor=2):
self.factor = factor
def fit(self, X, y=None):
return self
def transform(self, X):
return X * self.factor
# 创建 Pipeline
pipeline = Pipeline([
('multiplier', FeatureMultiplier()),
('scaler', StandardScaler()),
('classifier', LogisticRegression(random_state=42))
])
# 定义参数网格
param_grid = {
'multiplier__factor': [1, 2, 3], # 调优自定义转换器的参数
'classifier__C': [0.1, 1, 10]
}
# 网格搜索
grid_search = GridSearchCV(pipeline, param_grid, cv=5, scoring='accuracy')
grid_search.fit(X_train, y_train)
print("Best Parameters:", grid_search.best_params_)
print(f"Test Accuracy: {accuracy_score(y_test, grid_search.predict(X_test)):.3f}")
输出示例:
Best Parameters: {'classifier__C': 1, 'multiplier__factor': 2}
Test Accuracy: 1.000
五、进阶功能:自定义评估指标
可以通过 make_scorer 创建自定义评估指标,用于 GridSearchCV 或 cross_val_score。
from sklearn.metrics import make_scorer
from sklearn.metrics import f1_score
# 自定义 F1 分数(加权平均)
custom_scorer = make_scorer(f1_score, average='weighted')
# 在 GridSearchCV 中使用
grid_search = GridSearchCV(pipeline, param_grid, cv=5, scoring=custom_scorer)
grid_search.fit(X_train, y_train)
print("Best F1 Score:", grid_search.best_score_)
六、注意事项
- 接口一致性:
- 转换器需实现
fit和transform。 - 分类模型需实现
fit和predict,可选predict_proba。 - 回归模型需实现
fit和predict。
- 参数管理:
- 使用
BaseEstimator自动支持get_params和set_params,便于 GridSearchCV。
- 数据泄漏:
- 在
fit中仅使用训练数据,避免测试数据影响模型。
- 性能优化:
- 自定义模型可能效率低于 sklearn 的优化算法,需权衡复杂度。
- 调试:
- 在 Pipeline 中使用
verbose=True查看每步执行情况。 - 检查中间结果:
pipeline.named_steps['step_name'].transform(X)。
七、完整示例(鸢尾花分类)
结合自定义转换器和模型:
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.metrics import accuracy_score
import numpy as np
# 自定义转换器
class FeatureMultiplier(BaseEstimator, TransformerMixin):
def __init__(self, factor=2):
self.factor = factor
def fit(self, X, y=None):
return self
def transform(self, X):
return X * self.factor
# 自定义分类器
class NearestCentroidClassifier(BaseEstimator, ClassifierMixin):
def fit(self, X, y):
self.classes_ = np.unique(y)
self.centroids_ = np.array([X[y == c].mean(axis=0) for c in self.classes_])
return self
def predict(self, X):
return self.classes_[pairwise_distances_argmin(X, self.centroids_)]
# 数据准备
iris = load_iris()
X, y = iris.data, iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建 Pipeline
pipeline = Pipeline([
('multiplier', FeatureMultiplier(factor=2)),
('classifier', NearestCentroidClassifier())
])
# 训练和预测
pipeline.fit(X_train, y_train)
y_pred = pipeline.predict(X_test)
print(f"Accuracy: {accuracy_score(y_test, y_pred):.3f}")
输出示例:
Accuracy: 0.967
八、资源
- 官方文档:https://scikit-learn.org/stable/developers/develop.html
- 示例:https://scikit-learn.org/stable/auto_examples/miscellaneous/plot_pipeline.html
- 社区:在 X 平台搜索
#scikit-learn获取最新讨论。
如果需要 更复杂的自定义模型(如基于特定算法)、可视化中间结果,或针对特定任务(如时间序列预测)的完整示例,请告诉我,我可以提供详细代码或进一步优化!