【问题标题】:mask 0 values during normalization在规范化期间屏蔽 0 值
【发布时间】:2021-02-10 12:01:14
【问题描述】:

我正在对数据集进行规范化,但由于填充,数据包含很多 0。

我可以在模型训练期间屏蔽它们,但显然,当我应用归一化时,这些零会受到影响。

from sklearn.preprocessing import StandardScaler,MinMaxScaler

我目前正在使用 Sklearn 库进行规范化

例如,给定一个维度为 (4,3,5) 为 (batch, step, features) 的 3D 数组

零填充的数量因批次而异,因为这些是我从音频文件中提取的特征,具有不同的长度,使用固定的窗口大小。

[[[0 0 0 0 0],
  [0 0 0 0 0],
  [0 0 0 0 0]]

 [[1 2 3 4 5],
  [4 5 6 7 8],
  [9 10 11 12 13]],

 [[14 15 16 17 18],
  [0 0 0 0 0],
  [24 25 26 27 28]],

 [[0 0 0 0 0],
  [423 2 230 60 70],
  [0 0 0 0 0]]
]

我希望按列进行归一化,所以

scaler = MinMaxScaler()
X_train = scaler.fit_transform(X_train.reshape(-1,X_train.shape[-1])).reshape(X_train.shape)
X_test = scaler.transform(X_test.reshape(-1,X_test.shape[-1])).reshape(X_test.shape)

但是,在这种情况下,零被视为有效值。例如,第一列的最小值应该是 1 而不是 0。

此外,在应用缩放器后,0 的值也会发生变化,但我希望将它们保持为 0,以便在训练期间屏蔽它们。 model.add(tf.keras.layers.Masking(mask_value=0.0, input_shape=(X_train.shape[1], X_train.shape[2])))

在标准化过程中是否有任何方法可以屏蔽它们,以便在此示例中仅使用第 2 步和第 3 步进行标准化?

此外,我的项目的数组的实际维度更大为 (2000,50,68) 在这 68 个特征中,这 68 个特征的值差异可能非常大。我试图通过将每个元素除以其行中最大的元素来对它们进行归一化,以避免来自 0 的影响,但这并不奏效。


【问题讨论】:

  • 你试过什么方法吗?你应该在这里写你的试用代码。
  • 我在网上找不到任何方法
  • 向我们展示这些零值转换为您不想要的东西的确切代码序列。
  • minimal reproducible example 提供输入数据和预期输出
  • 您应该先尝试一下,然后再在这里提问。当然,如果你不能实现,你可以在这里问。你应该为流程编写数据样本,这就是 StackOverflow 的方式

标签: python machine-learning scikit-learn


【解决方案1】:

刚才MinMaxScaler()屏蔽的任务可以通过下一段代码来解决。

其他操作需要单独的处理方式,如果您提到所有需要屏蔽的操作,那么我们可以一一解决,我会扩展我的答案。例如。正如你提到的,keras 层可以被tf.keras.layers.Masking() 层掩盖。

下一个代码最小/最大缩放仅非零特征,其余保持零。

import numpy as np
from sklearn.preprocessing import MinMaxScaler

X = np.array([
     [[0, 0, 0, 0, 0],
      [0, 0, 0, 0, 0],
      [0, 0, 0, 0, 0]],

     [[1,  2,  3,  4,  5],
      [4,  5,  6,  7,  8],
      [9, 10, 11, 12, 13]],

     [[14, 15, 16, 17, 18],
      [0, 0, 0, 0, 0],
      [24, 25, 26, 27, 28]],

     [[0, 0, 0, 0, 0],
      [423, 2, 230, 60, 70],
      [0, 0, 0, 0, 0]]
], dtype = np.float64)

nz = np.any(X, -1)
X[nz] = MinMaxScaler().fit_transform(X[nz])

print(X)

输出:

[[[0.         0.         0.         0.         0.        ]
  [0.         0.         0.         0.         0.        ]
  [0.         0.         0.         0.         0.        ]]

 [[0.         0.         0.         0.         0.        ]
  [0.007109   0.13043478 0.01321586 0.05357143 0.04615385]
  [0.01895735 0.34782609 0.03524229 0.14285714 0.12307692]]

 [[0.03080569 0.56521739 0.05726872 0.23214286 0.2       ]
  [0.         0.         0.         0.         0.        ]
  [0.05450237 1.         0.10132159 0.41071429 0.35384615]]

 [[0.         0.         0.         0.         0.        ]
  [1.         0.         1.         1.         1.        ]
  [0.         0.         0.         0.         0.        ]]]

如果您需要在一个数据集上训练 MinMaxScaler() 并稍后将其应用于其他数据集,那么您可以进行下一步:

scaler = MinMaxScaler().fit(X[np.any(X, -1)])
X[np.any(X, -1)] = scaler.transform(X[np.any(X, -1)])
Y[np.any(Y, -1)] = scaler.transform(Y[np.any(Y, -1)])

【讨论】:

  • 是的,我用 fit 和 transform 分别尝试了你的第二部分,但结果不知何故不正确。你介意看看吗?
  • 我已经用代码和输出更新了我的问题。
  • @Leo 您的代码无法正常工作的原因是因为您在函数内部对同一数组X 应用了两次归一化,为了解决这个问题,请在masked_normalization() 函数体下一行的开头添加@ 987654330@。此外,您可以将np.any(...) 的结果存储到变量中并重新使用它,而不是为同一个数组计算多次np.any(...)
  • @Leo 也让我们在this chat 内部继续讨论,因为 cmets 通常不用于讨论。
  • @Leo 感谢我的回答 +50 分(赏金)! :)
猜你喜欢
  • 2020-02-10
  • 2019-10-03
  • 2017-09-22
  • 2018-02-05
  • 1970-01-01
  • 1970-01-01
  • 2020-03-15
  • 2017-01-30
  • 2010-12-01
相关资源
最近更新 更多