sklearn MinMaxScaler/RobustScaler无法缩放极小值至1的问题咨询
MinMaxScaler/RobustScaler对极小值数据不缩放的原因及解决办法
原因分析
这是Scikit-learn缩放器内置的数值精度保护机制导致的。以MinMaxScaler为例,其核心缩放公式为:
(X - X_min) / (X_max - X_min)
当X_max - X_min的数值接近float64的机器精度(约2.2e-16)时,sklearn会判定该特征的数值范围过小,为避免除以极小值引发的数值不稳定或溢出,会直接跳过缩放操作,返回原始数据。
你的测试数据中,df_small的最大值与最小值之差为4e-16,已经非常接近float64的机器epsilon,触发了保护机制;而df_not_small的数值范围为4e-15,远大于机器精度,因此正常完成缩放。
解决方案
无需手动编写data = data / data.max(),可通过以下两种方式解决:
1. 使用MaxAbsScaler替代
MaxAbsScaler的逻辑是将数据除以特征的绝对值最大值,对于非负数据来说,刚好能把最大值缩放到1、最小值保持0,且不会因数值范围小触发保护机制:
from sklearn.preprocessing import MaxAbsScaler import pandas as pd import numpy as np df_small = pd.DataFrame((np.arange(5)*10.0**(-16))) scaler = MaxAbsScaler() small_transformed = scaler.fit_transform(df_small) print(small_transformed) # 输出: # [[0. ] # [0.25] # [0.5 ] # [0.75] # [1. ]]
2. 自定义MinMaxScaler移除精度判断
如果必须使用MinMaxScaler,可以继承并重写fit方法,强制保留数值范围计算逻辑:
from sklearn.preprocessing import MinMaxScaler import pandas as pd import numpy as np class CustomMinMaxScaler(MinMaxScaler): def fit(self, X, y=None): # 调用父类fit方法获取min和max super().fit(X, y) # 强制计算data_range_,忽略默认的精度判断 self.data_range_ = self.data_max_ - self.data_min_ return self df_small = pd.DataFrame((np.arange(5)*10.0**(-16))) scaler = CustomMinMaxScaler() small_transformed = scaler.fit_transform(df_small) print(small_transformed) # 输出: # [[0. ] # [0.25] # [0.5 ] # [0.75] # [1. ]]
注意:这种方法可能会引入微小的数值精度误差,但在你的场景下完全可接受。
内容的提问来源于stack exchange,提问作者Dima
相关产品推荐
相关产品推荐

