[深度学习] 关于 sklearn 归一化函数 MinMaxScaler 类的掉坑经历

335 阅读2分钟

深度学习里常用到 sci-kit learn机器学习包,比如数据归一化、引入评价指标等。

在数据预处理阶段,有时希望量纲不同的数据能统一压缩[0,1]范围内,方便塞进后面的深度学习模型。为此,我们常用 sklearn.preprocessing.MinMaxScaler 来处理这一流程。

要点:

  • MinMaxScalar 类进行归一化/反归一化操作时,特定的缩放比例保存在其属性scale_中。

常见用法

通常进行归一化与反归一化时,用例如下:

from sklearn.preprocessing import MinMaxScaler
import numpy as np

# 创建一个示例特征矩阵
X = np.array([[1.0], 
              [2.0], 
              [3.0]])

# 创建MinMaxScaler对象
scaler = MinMaxScaler(feature_range=(0, 1))

# 对特征矩阵进行最小-最大缩放
X_scaled = scaler.fit_transform(X)

# 打印缩放后的特征矩阵
"""
[[0. ]
 [0.5]
 [1. ]]
 """
print(X_scaled)

X_original = scaler.inverse_transform(X_scaled)

"""
[[1.]
 [2.]
 [3.]]
"""
print(X_original)

上面的代码并不会出现问题。

踩坑经历

现在的需求是,有一个二维表(DataFrame),包括若干行记录和多个量纲不同的列。希望分别对每一列数据进行单独的归一化。

此时如果还用单个 MinMaxScaler 类循环地对每一列数据归一化,比如

for col in dataframe.cloumns:
    sc.fit_transform(...)

将会导致反归一化某一列时,MinMaxScaler依据的是循环的最后一列的scale_。也就是说,将产生错误的反归一化。

解决方案

为指定要反归一化的数据列专设一个 MinMaxScaler 实例,由于直接用= 赋值只是给新变量传递了旧变量的引用,底层还是同一份数据。注意使用 copy 模块完成对象实例的拷贝。用例如下:

import copy

sc = MinMaxScaler(feature_range=(0, 1))

for i in range(num_columns):
   sc.fit_transform(df_column[i])
   # 对指定列完全复制出一个实例
   if i == 3:
       new_sc = copy.copy(sc)