MinMaxScaler与手动计算结果不符的原因排查
问题:MinMaxScaler手动计算与sklearn结果不一致的原因?
我在调试sklearn的MinMaxScaler时,尝试通过手动计算验证其工作逻辑,使用如下数组进行归一化处理:
array = [[0, -1.73, -1.73, -2.0, -2.0, -2.0, -1.73], [-1.73, 0, -1.41, -1.73, -1.73, -1.73, -1.41], [-1.73, -1.41, 0, -1.73, -1.73, -1.73, -0.0], [-2.0, -1.73, -1.73, 0, -1.41, -1.41, -1.73], [-2.0, -1.73, -1.73, -1.41, 0, -0.0, -1.73], [-2.0, -1.73, -1.73, -1.41, -0.0, 0, -1.73], [-1.73, -1.41, -0.0, -1.73, -1.73, -1.73, 0]]
我认为该数据的最小值为-2.0,最大值为0。按照sklearn官方文档给出的MinMaxScaler公式x' = (x-min)/ (max - min)手动计算时,-1.73的结果应为0.135:
x' = (-1.73-(-2)) / (0 - (-2)) x' = 0.135
但运行以下代码后:
from sklearn.preprocessing import MinMaxScaler import numpy as np X = np.array([ [0, -1.73, -1.73, -2.0, -2.0, -2.0, -1.73], [-1.73, 0, -1.41, -1.73, -1.73, -1.73, -1.41], [-1.73, -1.41, 0, -1.73, -1.73, -1.73, -0.0], [-2.0, -1.73, -1.73, 0, -1.41, -1.41, -1.73], [-2.0, -1.73, -1.73, -1.41, 0, -0.0, -1.73], [-2.0, -1.73, -1.73, -1.41, -0.0, 0, -1.73], [-1.73, -1.41, -0.0, -1.73, -1.73, -1.73, 0] ]) # 创建MinMaxScaler实例 scaler = MinMaxScaler() # 拟合并转换数据 X_scaled = scaler.fit_transform(X) # 打印缩放后的数据 print(X_scaled)
得到的结果数组中部分-1.73被缩放为0:
[[1. 0. 0. 0. 0. 0. 0. ] [0.135 1. 0.1849711 0.135 0.135 0.135 0.1849711] [0.135 0.1849711 1. 0.135 0.135 0.135 1. ] [0. 0. 0. 1. 0.295 0.295 0. ] [0. 0. 0. 0.295 1. 1. 0. ] [0. 0. 0. 0.295 1. 1. 0. ] [0.135 0.1849711 1. 0.135 0.135 0.135 1. ]]
请问我的手动计算与sklearn实现的差异点在哪里?为什么部分-1.73会被缩放为0?
核心原因:MinMaxScaler默认按列归一化,而非全局
你犯了一个关键错误:默认配置下,MinMaxScaler是对每一列独立计算min和max,再单独归一化该列的数据,并非用整个数据集的全局min和max处理所有元素。
我们针对你的数据验证这一点:
- 看第二列原始数据:
[-1.73, 0, -1.41, -1.73, -1.73, -1.73, -1.41],这一列的最小值是-1.73,最大值是0。对该列的-1.73套用公式计算:(-1.73 - (-1.73))/(0 - (-1.73)) = 0,这就是你看到部分-1.73被缩放为0的原因。 - 再看第一列原始数据:
[0, -1.73, -1.73, -2.0, -2.0, -2.0, -1.73],该列min是-2.0,max是0,所以其中的-1.73计算后为0.135,和你手动结果一致。 - 同理,第四列、第五列的min是
-2.0、max是0,所以这些列的-1.73计算后也是0.135。
如何实现全局归一化
如果需要用整个数据集的min和max做归一化,需要先将数据扁平化,归一化后再恢复原形状:
from sklearn.preprocessing import MinMaxScaler import numpy as np X = np.array([ [0, -1.73, -1.73, -2.0, -2.0, -2.0, -1.73], [-1.73, 0, -1.41, -1.73, -1.73, -1.73, -1.41], [-1.73, -1.41, 0, -1.73, -1.73, -1.73, -0.0], [-2.0, -1.73, -1.73, 0, -1.41, -1.41, -1.73], [-2.0, -1.73, -1.73, -1.41, 0, -0.0, -1.73], [-2.0, -1.73, -1.73, -1.41, -0.0, 0, -1.73], [-1.73, -1.41, -0.0, -1.73, -1.73, -1.73, 0] ]) # 全局归一化实现 scaler = MinMaxScaler() # 将数据扁平化为一维数组 X_flat = X.reshape(-1, 1) # 拟合并转换扁平化数据 X_flat_scaled = scaler.fit_transform(X_flat) # 恢复原数据形状 X_scaled_global = X_flat_scaled.reshape(X.shape) print(X_scaled_global)
此时所有-1.73都会被缩放为0.135,和你手动计算的结果完全一致。
内容的提问来源于stack exchange,提问作者Michael Halim
相关产品推荐
相关产品推荐

