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

Sklearn Pipeline中IsolationForest离群值移除器报错问题

问题解决:自定义离群值移除器在Sklearn Pipeline中报错的修复

错误原因

你的IsolationForestOutlierRemover类违反了Sklearn Transformer的接口规范:Transformer的transform方法只能返回特征矩阵X,不能同时返回X和y。

当你把这个类放进Pipeline后,Pipeline会将transform返回的元组(X_filtered, y_filtered)直接作为下一个步骤(随机森林)的输入X,导致随机森林收到的是一个包含两个数组的元组,而非正常的特征矩阵,从而触发形状不匹配的报错。

另外,即使你修改transform只返回X,Pipeline默认仍会将原始的y传递给下一个步骤,导致过滤后的X(95个样本)和原始y(100个样本)样本数不匹配,同样会报错。

修复方案

方案1:调整自定义Transformer,配合手动过滤y(适合简单场景)

先修改IsolationForestOutlierRemover的transform方法,只返回过滤后的X:

class IsolationForestOutlierRemover(BaseEstimator, TransformerMixin):
    def __init__(self, contamination=0.05):
        self.contamination = contamination
        self.isolation_forest = IsolationForest(contamination=self.contamination)

    def fit(self, X, y=None):
        self.isolation_forest.fit(X)
        mask = self.isolation_forest.predict(X) == 1
        self.mask = mask
        return self

    def transform(self, X, y=None):
        # 只返回过滤后的特征矩阵X
        return X[self.mask]

    def fit_transform(self, X, y=None):
        self.fit(X, y)
        if y is not None:
            return X[self.mask], y[self.mask]
        else:
            return X[self.mask]

然后在训练时,先手动过滤X和y,再传入Pipeline:

# 先过滤离群值
X_filtered, y_filtered = IsolationForestOutlierRemover().fit_transform(X1, y1)

# 用过滤后的数据集训练Pipeline
pipelinet = Pipeline(
    [
        ("random_forest", RandomForestClassifier()),
    ]
)
pipelinet.fit(X_filtered, y_filtered)

方案2:自定义MetaEstimator,实现端到端的离群值移除+模型训练(适合Pipeline集成)

如果你想把整个流程封装成一个可复用的组件,可以自定义一个MetaEstimator,内部先处理离群值过滤,再训练模型:

from sklearn.base import BaseEstimator
from sklearn.ensemble import IsolationForest, RandomForestClassifier
import numpy as np

class IsolationForestOutlierRemover(BaseEstimator, TransformerMixin):
    def __init__(self, contamination=0.05):
        self.contamination = contamination
        self.isolation_forest = IsolationForest(contamination=self.contamination)

    def fit(self, X, y=None):
        self.isolation_forest.fit(X)
        mask = self.isolation_forest.predict(X) == 1
        self.mask = mask
        return self

    def transform(self, X, y=None):
        if y is not None:
            return X[self.mask], y[self.mask]
        else:
            return X[self.mask]

    def fit_transform(self, X, y=None):
        self.fit(X, y)
        return self.transform(X, y)

# 自定义MetaEstimator,整合离群值移除和分类器
class OutlierResistantClassifier(BaseEstimator):
    def __init__(self, outlier_remover, classifier):
        self.outlier_remover = outlier_remover
        self.classifier = classifier
    
    def fit(self, X, y):
        # 先过滤离群值
        X_filtered, y_filtered = self.outlier_remover.fit_transform(X, y)
        # 训练分类器
        self.classifier.fit(X_filtered, y_filtered)
        return self
    
    def predict(self, X):
        # 预测时不需要过滤(离群值移除只在训练时做)
        return self.classifier.predict(X)
    
    def predict_proba(self, X):
        return self.classifier.predict_proba(X)

使用方式:

# 初始化整合后的模型
clf = OutlierResistantClassifier(
    outlier_remover=IsolationForestOutlierRemover(contamination=0.05),
    classifier=RandomForestClassifier()
)

# 直接用原始数据训练
clf.fit(X1, y1)
# 预测
predictions = clf.predict(X1)

完整可运行代码

from sklearn.datasets import make_classification
from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.ensemble import IsolationForest, RandomForestClassifier
import numpy as np

# 生成测试数据
X1, y1 = make_classification(n_samples=100, n_features=10, n_informative=5, n_classes=3)

# 自定义离群值移除器
class IsolationForestOutlierRemover(BaseEstimator, TransformerMixin):
    def __init__(self, contamination=0.05):
        self.contamination = contamination
        self.isolation_forest = IsolationForest(contamination=self.contamination)

    def fit(self, X, y=None):
        self.isolation_forest.fit(X)
        mask = self.isolation_forest.predict(X) == 1
        self.mask = mask
        return self

    def transform(self, X, y=None):
        if y is not None:
            return X[self.mask], y[self.mask]
        else:
            return X[self.mask]

    def fit_transform(self, X, y=None):
        self.fit(X, y)
        return self.transform(X, y)

# 自定义整合模型
class OutlierResistantClassifier(BaseEstimator):
    def __init__(self, outlier_remover, classifier):
        self.outlier_remover = outlier_remover
        self.classifier = classifier
    
    def fit(self, X, y):
        X_filtered, y_filtered = self.outlier_remover.fit_transform(X, y)
        self.classifier.fit(X_filtered, y_filtered)
        return self
    
    def predict(self, X):
        return self.classifier.predict(X)

# 训练并测试
clf = OutlierResistantClassifier(
    outlier_remover=IsolationForestOutlierRemover(contamination=0.05),
    classifier=RandomForestClassifier()
)
clf.fit(X1, y1)
print("预测结果:", clf.predict(X1[:5]))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 21:17:02