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

如何在Scikit-learn Pipeline中跨步骤传递拟合参数?

问题描述

我正在编写自定义Scikit-learn Pipeline:

Step 1 代码:

class Step1(BaseEstimator, TransformerMixin):
    def __init__(self, input1: str = "Input1") -> None:
        self.input1 = input1

    def fit(self, X: pd.DataFrame, y: pd.DataFrame = None):
        self.some_param = X["my_col"].mean()
        return self
    
    def transform(self, X):
        return X

Step 2 代码:

class Step2(BaseEstimator, TransformerMixin):
    def __init__(self, input2: str = "Input2") -> None:
        self.input2 = input2

    def fit(self, X: pd.DataFrame, y: pd.DataFrame = None):
        return self
    
    def transform(self, X):
        # 想要在此处使用Step1中拟合得到的变量: 'some_param'
        X["my_other_col"] = X["my_other_col"] - (some_param)
        return X

Pipeline定义:

pipeline = Pipeline([
('step1', Step1()),
('step2', Step2())
])

需求:在Step1中拟合得到的some_param,需要在Step2的transform方法中使用,尝试过set_param但效果不符合预期,求可行实现方法。


可行实现方法

方法一:拟合后手动传递参数

修改Step2,添加some_param作为初始化参数,在Pipeline拟合完成后,从Step1实例中取出参数赋值给Step2:

class Step2(BaseEstimator, TransformerMixin):
    def __init__(self, input2: str = "Input2", some_param: float = None) -> None:
        self.input2 = input2
        self.some_param = some_param  # 添加参数存储属性

    def fit(self, X: pd.DataFrame, y: pd.DataFrame = None):
        return self
    
    def transform(self, X):
        if self.some_param is None:
            raise ValueError("请先拟合Pipeline并设置some_param参数")
        X["my_other_col"] = X["my_other_col"] - self.some_param
        return X

使用方式:

pipeline = Pipeline([
    ('step1', Step1()),
    ('step2', Step2())
])

# 拟合Pipeline
pipeline.fit(X_train)

# 将Step1的some_param传递给Step2
pipeline.named_steps['step2'].some_param = pipeline.named_steps['step1'].some_param

# 执行转换
result = pipeline.transform(X_test)

方法二:通过DataFrame传递参数

让Step1在transform时将some_param作为临时列加入DataFrame,Step2读取后再移除该列,无需手动传递:

修改Step1:

class Step1(BaseEstimator, TransformerMixin):
    def __init__(self, input1: str = "Input1") -> None:
        self.input1 = input1

    def fit(self, X: pd.DataFrame, y: pd.DataFrame = None):
        self.some_param = X["my_col"].mean()
        return self
    
    def transform(self, X):
        X_copy = X.copy()  # 避免修改原始数据
        X_copy['_temp_some_param'] = self.some_param  # 添加临时列
        return X_copy

修改Step2:

class Step2(BaseEstimator, TransformerMixin):
    def __init__(self, input2: str = "Input2") -> None:
        self.input2 = input2

    def fit(self, X: pd.DataFrame, y: pd.DataFrame = None):
        return self
    
    def transform(self, X):
        X_copy = X.copy()
        # 从临时列读取参数(所有行值相同,取第一行即可)
        some_param = X_copy['_temp_some_param'].iloc[0]
        X_copy["my_other_col"] = X_copy["my_other_col"] - some_param
        X_copy.drop('_temp_some_param', axis=1, inplace=True)  # 删除临时列
        return X_copy

使用方式:

pipeline = Pipeline([
    ('step1', Step1()),
    ('step2', Step2())
])

pipeline.fit(X_train)
result = pipeline.transform(X_test)

方法三:自定义复合Transformer

将Step1和Step2封装到一个类中,内部直接传递参数,简化Pipeline结构:

class CombinedTransformer(BaseEstimator, TransformerMixin):
    def __init__(self, input1: str = "Input1", input2: str = "Input2") -> None:
        self.input1 = input1
        self.input2 = input2
        self.step1 = Step1(input1)
        self.step2 = Step2(input2)

    def fit(self, X: pd.DataFrame, y: pd.DataFrame = None):
        self.step1.fit(X, y)
        # 内部直接传递参数
        self.step2.some_param = self.step1.some_param
        self.step2.fit(X, y)
        return self
    
    def transform(self, X):
        X = self.step1.transform(X)
        X = self.step2.transform(X)
        return X

使用方式:

pipeline = Pipeline([
    ('combined', CombinedTransformer())
])

pipeline.fit(X_train)
result = pipeline.transform(X_test)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 00:06:22