🎬 HoRain云小助手个人主页

 🔥 个人专栏: 《Linux 系列教程》《c语言教程

⛺️生活的理想,就是为了理想的生活!


⛳️ 推荐

前些天发现了一个超棒的服务器购买网站,性价比超高,大内存超划算!忍不住分享一下给大家。点击跳转到网站。

专栏介绍

专栏名称

专栏介绍

《C语言》

本专栏主要撰写C干货内容和编程技巧,让大家从底层了解C,把更多的知识由抽象到简单通俗易懂。

《网络协议》

本专栏主要是注重从底层来给大家一步步剖析网络协议的奥秘,一起解密网络协议在运行中协议的基本运行机制!

《docker容器精解篇》

全面深入解析 docker 容器,从基础到进阶,涵盖原理、操作、实践案例,助您精通 docker。

《linux系列》

本专栏主要撰写Linux干货内容,从基础到进阶,知识由抽象到简单通俗易懂,帮你从新手小白到扫地僧。

《python 系列》

本专栏着重撰写Python相关的干货内容与编程技巧,助力大家从底层去认识Python,将更多复杂的知识由抽象转化为简单易懂的内容。

《试题库》

本专栏主要是发布一些考试和练习题库(涵盖软考、HCIE、HRCE、CCNA等)

目录

⛳️ 推荐

专栏介绍

🛠️ 1. 自定义评估指标 (Custom Metrics)

🔧 2. 自定义转换器 (Custom Transformers)

🤖 3. 自定义估计器 (Custom Estimators)

🧩 4. 在 Pipeline 中使用自定义组件

💡 5. 重写现有估算器

📌 总结


img

Sklearn 提供了灵活的机制来自定义模型和功能,使你能够扩展库以满足特定需求。以下是核心方法和示例:

🛠️ 1. 自定义评估指标 (Custom Metrics)

当内置指标不满足需求时,你可以创建自定义评估指标,并将其与 Sklearn 的模型评估工具(如 cross_val_scoreGridSearchCV)结合使用。

​示例:创建一个加权准确率评估器​

from sklearn.metrics import make_scorer, accuracy_score
import numpy as np

def weighted_accuracy(y_true, y_pred, positive_weight=2.0):
    correct = y_true == y_pred
    weights = np.where(y_true == 1, positive_weight, 1.0)
    return np.sum(correct * weights) / np.sum(weights)

# 使用 make_scorer 将函数转换为 scorer
custom_scorer = make_scorer(
    weighted_accuracy,
    greater_is_better=True, # 分数越高代表模型越好
    needs_threshold=False,  # 该指标不需要概率阈值
    positive_weight=2.0     # 传递额外参数
)

# 使用示例
from sklearn.datasets import make_classification
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score

X, y = make_classification(n_samples=1000, weights=[0.9, 0.1])
model = RandomForestClassifier()

# 在交叉验证中使用自定义评分器
scores = cross_val_score(model, X, y, cv=5, scoring=custom_scorer)
print("Weighted Accuracy Scores:", scores)

​关键点:​

  • make_scorer 是将自定义函数转化为 Scorer 的关键工具。
  • greater_is_better: 定义分数高低是否代表模型性能更好。
  • needs_threshold: 如果你的指标需要预测概率而非类别标签,需设置为 True
  • 自定义评分器可以像内置评分器一样用于 cross_val_score, GridSearchCV 等。

🔧 2. 自定义转换器 (Custom Transformers)

你可以创建自定义的数据预处理或特征工程步骤,并将其无缝集成到 Sklearn 的 Pipeline 中。

​示例:创建一个添加组合特征的转换器​

from sklearn.base import BaseEstimator, TransformerMixin
import numpy as np

# 通过继承 BaseEstimator 和 TransformerMixin 来创建转换器
class CombinedAttributesAdder(BaseEstimator, TransformerMixin):
    def __init__(self, add_bedrooms_per_room=True):
        self.add_bedrooms_per_room = add_bedrooms_per_room
        
    def fit(self, X, y=None):
        return self  # 本例无需在 fit 中学习任何参数
        
    def transform(self, X, y=None):
        # 假设 X 的列索引已知
        rooms_ix, bedrooms_ix, population_ix, household_ix = 3, 4, 5, 6
        
        rooms_per_household = X[:, rooms_ix] / X[:, household_ix]
        population_per_household = X[:, population_ix] / X[:, household_ix]
        
        if self.add_bedrooms_per_room:
            bedrooms_per_room = X[:, bedrooms_ix] / X[:, rooms_ix]
            return np.c_[X, rooms_per_household, population_per_household, bedrooms_per_room]
        else:
            return np.c_[X, rooms_per_household, population_per_household]

# 在 Pipeline 中使用
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler

pipeline = Pipeline([
    ('attribs_adder', CombinedAttributesAdder(add_bedrooms_per_room=True)),
    ('std_scaler', StandardScaler()),
])

X_transformed = pipeline.fit_transform(X_data)

​关键点:​

  • 继承 BaseEstimator 可以获得 get_paramsset_params 方法,使其与 GridSearchCV 兼容。
  • 继承 TransformerMixin 会自动获得 fit_transform 方法。
  • fit 方法用于从训练数据中学习参数(如均值、方差),并返回 self
  • transform 方法应用学到的参数对数据进行转换。

对于简单的转换,也可以使用 FunctionTransformer

from sklearn.preprocessing import FunctionTransformer
import pandas as pd

def reduce_memory(X, y=None):
    """将数值型列转换为 float32 以减少内存占用"""
    num_cols = X.select_dtypes(include=np.number).columns
    for col in num_cols:
        X[col] = X[col].astype("float32")
    return X

# 创建转换器
memory_reducer = FunctionTransformer(reduce_memory)
# 在 Pipeline 中使用
pipeline = Pipeline([
    ('memory_reduce', memory_reducer),
    # ... 其他步骤
])

🤖 3. 自定义估计器 (Custom Estimators)

你可以实现自己的机器学习算法,并使其遵循 Sklearn 的 API 规范。

​示例:创建一个简单的基于规则的分类型​

from sklearn.base import BaseEstimator, ClassifierMixin
import numpy as np

class SimpleClassifier(BaseEstimator, ClassifierMixin):
    def __init__(self, strategy='mean'):
        self.strategy = strategy
        
    def fit(self, X, y):
        # 这是一个极其简单的“模型”,仅用于演示
        if self.strategy == 'mean':
            self.threshold_ = np.mean(X, axis=0) # 计算每个特征的均值作为阈值
        # 可以添加其他策略...
        return self  # fit 必须返回 self
        
    def predict(self, X):
        # 预测:如果特征值大于阈值,则预测为 1,否则为 0
        return (X > self.threshold_).astype(int)
    
    # 可选:实现 score 方法,默认使用 accuracy_score
    # 由于继承了 ClassifierMixin,已经有了一个基本的 score 方法

# 使用自定义估计器
X_train = np.array([[1.5, 2.5], [2.0, 3.0], [3.5, 4.5], [4.0, 5.0]])
y_train = np.array([0, 0, 1, 1])

clf = SimpleClassifier()
clf.fit(X_train, y_train)
X_test = np.array([[2.5, 3.5], [1.0, 2.0]])
predictions = clf.predict(X_test)
print("Predictions:", predictions)

​关键点:​

  • 继承 BaseEstimator 是基础。
  • 继承 ClassifierMixin, RegressorMixinClusterMixin 等可以为你的估计器提供默认的 score 方法。
  • 必须实现 fitpredict 方法。
  • fit 方法应学习训练数据的属性并返回 self
  • 通过遵循此接口,你的自定义估计器可以与 Pipeline, GridSearchCV 等 Sklearn 工具协同工作。

🧩 4. 在 Pipeline 中使用自定义组件

自定义的转换器和估计器可以无缝地集成到 Sklearn Pipeline 中,构建完整的数据处理和机器学习工作流。

from sklearn.pipeline import Pipeline
from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris

# 加载数据
iris = load_iris()
X, y = iris.data, iris.target

# 创建一个包含自定义转换器和标准估计器的 Pipeline
# 假设 CombinedAttributesAdder 和 SimpleClassifier 已定义
pipeline = Pipeline([
    ('attrib_adder', CombinedAttributesAdder()),
    ('clf', RandomForestClassifier(random_state=42))
])

# 甚至可以定义自定义转换器的超参数进行网格搜索
param_grid = {
    'attrib_adder__add_bedrooms_per_room': [True, False], # 自定义转换器的参数
    'clf__n_estimators': [50, 100] # 标准估计器的参数
}

grid_search = GridSearchCV(pipeline, param_grid, cv=5, scoring='accuracy')
grid_search.fit(X, y)

print("Best parameters:", grid_search.best_params_)
print("Best cross-validation score:", grid_search.best_score_)

​关键点:​

  • Pipeline 的每一步都是一个 (名称, 估算器) 元组。
  • 可以通过 step_name__parameter_name 的语法来访问和调整 Pipeline 中任何步骤的超参数,包括自定义的步骤。
  • 这确保了从数据预处理到模型训练和评估的整个流程的可重复性和一致性。

💡 5. 重写现有估算器

有时你不需要从头创建,而是想微调现有 Sklearn 估算器的行为。你可以通过继承并重写其方法来实现。

​示例:重写 LogisticRegression​

from sklearn.linear_model import LogisticRegression

class CustomLogisticRegression(LogisticRegression):
    def __init__(self, custom_param=1.0, **kwargs):
        super().__init__(**kwargs)  # 调用父类初始化
        self.custom_param = custom_param
        
    def fit(self, X, y, sample_weight=None):
        # 可以在调用父类 fit 之前或之后添加自定义逻辑
        print(f"Using custom parameter: {self.custom_param}")
        # 例如,这里可以基于 custom_param 对数据做一些预处理
        return super().fit(X, y, sample_weight) # 调用父类的 fit 方法
        
    def predict(self, X):
        # 也可以自定义预测行为
        return super().predict(X)

# 使用自定义的 Logistic Regression
custom_lr = CustomLogisticRegression(custom_param=0.5, C=1.0, solver='liblinear')
custom_lr.fit(X_train, y_train)
predictions = custom_lr.predict(X_test)

​关键点:​

  • 通过继承现有的估算器,你可以保留其所有原有功能。
  • 使用 super() 来调用父类方法,避免重复编写代码。
  • 只需重写你需要修改的方法。

📌 总结

Sklearn 的自定义功能通过以下核心类实现:

  1. make_scorer​: 用于包装自定义评估指标函数,使其与 Sklearn 的评估框架兼容。
  2. BaseEstimator​: 所有估算器的基类,提供了 get_paramsset_params 方法,使对象能够进行超参数调整。
  3. TransformerMixin​: 转换器的混合类,提供了 fit_transform 方法。
  4. ClassifierMixin, RegressorMixin 等​​: 为特定类型的估算器提供默认的 score 方法。
  5. FunctionTransformer​: 将简单的函数快速转换为转换器,适用于简单的数据转换操作。
  6. Pipeline​: 将多个处理步骤(包括自定义步骤)组合成一个连贯的工作流。

通过利用这些功能,你可以极大地扩展 Sklearn 的适用性,将其灵活地应用于各种特定问题域,同时仍然享受 Sklearn 工具链(如网格搜索、交叉验证和管道)带来的所有便利。

❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍

🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐