如何让sklearn缩放器基于自定义最值而非训练集缩放百分比特征?
自定义百分比列缩放:替代MinMaxScaler的方案
问题说明
当需要将百分比列固定缩放到0-1区间(而非基于训练集的最大最小值动态缩放)时,sklearn.preprocessing.MinMaxScaler无法满足需求。它会根据训练集的min/max计算缩放公式,导致超出训练集范围的输入值缩放结果偏离预期。
示例代码验证:
from sklearn.preprocessing import MinMaxScaler X_train = [[60], [70]] scaler = MinMaxScaler(feature_range=(0,1)) scaler.fit(X=X_train) # 预期输出[[1.0]],实际输出[[4.0]] print(scaler.transform([[100]]))
原因是MinMaxScaler的缩放公式为(x - min_train) / (max_train - min_train),这里训练集min=60、max=70,代入后得到(100-60)/(70-60)=4,完全不符合百分比缩放的预期。
解决方案:实现自定义PercentageScaler
通过继承sklearn的Transformer基类,构建一个不依赖训练集统计值的缩放器,再结合Pipeline和ColumnTransformer实现分列处理:
from sklearn.pipeline import Pipeline from sklearn.compose import ColumnTransformer from sklearn.impute import SimpleImputer from sklearn.base import _OneToOneFeatureMixin, TransformerMixin, BaseEstimator import numpy as np def isolate(): X_train = [[60, 50], [70, 90]] class PercentageScaler(_OneToOneFeatureMixin, TransformerMixin, BaseEstimator): def __init__(self) -> None: super().__init__() def fit(self, X, y=None): # 无需训练,直接返回自身 return self def transform(self, X): # 固定将百分比值除以100,缩放到0-1区间 return np.array(X) / 100 # 处理百分比列的流水线:先填充缺失值,再缩放 percent_transformer = Pipeline(steps=[ ('imputer', SimpleImputer(strategy='median')), ('scaler', PercentageScaler()) ]) # 处理普通数值列的流水线:先填充缺失值,再用MinMaxScaler缩放 num_transformer = Pipeline(steps=[ ('imputer', SimpleImputer(strategy='median')), ('scaler', MinMaxScaler()) ]) # 组合两个流水线,分别处理指定列 transformer = ColumnTransformer(transformers=[ ('percent', percent_transformer, [0]), # 第0列是百分比列 ('num', num_transformer, [1]) # 第1列是普通数值列 ]) transformer.fit(X=X_train) # 输出:[[1. 0.25]],符合预期:100%→1.0,60在50-90区间缩放为0.25 print(transformer.transform([[100, 60]])) isolate()
这个方案的核心优势是:
- 百分比列的缩放规则固定,不受训练集数据分布影响
- 可以和sklearn的流水线生态无缝结合,统一处理不同类型的特征列
内容的提问来源于stack exchange,提问作者Jason Rich Darmawan
相关产品推荐
相关产品推荐

