You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Sklearn多类别场景下的单类别独立模型构建方案咨询

解决方案

Sklearn 中没有现成工具直接匹配你的需求:OneVsOneClassifier、OneVsRestClassifier 这类多分类包装器都会使用全量数据集训练每个子二分类器(每个子模型会用到所有类别的正/负样本),MultioutputClassifier 则针对多输出任务,和你的场景不匹配。你需要自行封装实现一套符合要求的流程,以下是具体方案:

核心思路

针对每个类别单独构建模型:

  • 若你是想做一类分类(仅用该类的正样本训练,判断样本是否属于该类),可选用 OneClassSVM、IsolationForest 这类支持单类别训练的模型;
  • 若你实际是想让每个二分类器以该类为正例、其他类为负例,但仅针对该类特性单独调参,也可基于常规二分类器封装,单独处理每个类别的数据和调参逻辑。

以下以一类分类+单独调参+TopN概率输出的场景为例,给出实现代码:

代码实现

1. 自定义多类别模型类

from sklearn.base import BaseEstimator, ClassifierMixin
from sklearn.model_selection import GridSearchCV
from sklearn.svm import OneClassSVM
import numpy as np

class PerCategoryClassifier(BaseEstimator, ClassifierMixin):
    def __init__(self, base_model=OneClassSVM(), param_grids=None):
        self.base_model = base_model
        self.param_grids = param_grids if param_grids else {}
        self.models = {}  # 存储每个类别的训练好的模型
        self.classes_ = None  # 存储所有类别

    def fit(self, X, y):
        self.classes_ = np.unique(y)
        for cls in self.classes_:
            # 仅提取当前类别的数据作为训练集
            X_cls = X[y == cls]
            # 为当前类别单独做超参数调优
            grid = GridSearchCV(self.base_model, self.param_grids.get(cls, {}), cv=3, scoring='roc_auc')
            grid.fit(X_cls)
            # 保存调优后的最佳模型
            self.models[cls] = grid.best_estimator_
        return self

    def predict_proba(self, X):
        # 对每个样本,计算属于每个类别的概率(将一类模型的决策函数转换为概率)
        probas = []
        for cls in self.classes_:
            model = self.models[cls]
            # 把决策函数值归一化到[0,1]区间作为近似概率
            dec_func = model.decision_function(X)
            prob = (dec_func - dec_func.min()) / (dec_func.max() - dec_func.min())
            probas.append(prob)
        # 转换为形状(n_samples, n_classes)的数组,列对应self.classes_的顺序
        return np.array(probas).T

    def predict_top_n(self, X, n=3):
        probas = self.predict_proba(X)
        # 获取每个样本概率TopN的类别索引
        top_n_indices = np.argsort(-probas, axis=1)[:, :n]
        # 转换为类别标签
        top_n_classes = self.classes_[top_n_indices]
        return top_n_classes

2. 使用示例

from sklearn.datasets import load_iris
import numpy as np

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

# 为每个类别定义不同的超参数网格
param_grids = {
    0: {'gamma': [0.001, 0.01, 0.1], 'nu': [0.1, 0.5]},
    1: {'gamma': [0.01, 0.1, 1], 'nu': [0.3, 0.7]},
    2: {'gamma': [0.1, 1, 10], 'nu': [0.2, 0.6]}
}

# 初始化并训练模型
clf = PerCategoryClassifier(param_grids=param_grids)
clf.fit(X, y)

# 预测Top2类别
test_sample = X[0:5]
top_2 = clf.predict_top_n(test_sample, n=2)
print("Top2类别预测结果:\n", top_2)

# 获取概率
probas = clf.predict_proba(test_sample)
print("概率矩阵:\n", probas)

关键说明

  • 模型初始化:自定义类初始化时无需传入类别信息,fit 阶段会自动从训练数据中提取所有类别并创建对应模型;
  • 单独调参:通过 param_grids 参数可为每个类别指定不同的超参数搜索空间,实现针对性调优;
  • 概率转换:一类模型本身不直接输出概率,这里通过对决策函数做归一化处理得到近似概率,你也可以根据需求更换其他转换方式(比如Sigmoid函数);
  • TopN输出:predict_top_n 方法直接返回每个样本概率最高的N个类别,满足需求。

如果你实际需求是常规二分类(每个子模型用该类正样本+其他类负样本训练,但单独调参),只需修改 fit 方法中数据提取的逻辑,将非当前类别的数据标记为负例,使用常规二分类器(如LogisticRegression、RandomForestClassifier)即可,超参数调优逻辑保持不变。

内容的提问来源于stack exchange,提问作者max

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 20:01:13