如何根据自己的类型对 3D 数组的特定维度中的特征进行归一化

Posted

技术标签:

【中文标题】如何根据自己的类型对 3D 数组的特定维度中的特征进行归一化【英文标题】:How to normalize features in a specific dimension of a 3D array with respect to their own type 【发布时间】:2021-01-30 13:09:14 【问题描述】:

我有一个 3D 数组 (1883,100,68) 作为 (batch,step,features)。

这68个特征是完全不同的特征,比如能量和mfcc。

我希望根据自己的类型对特征进行规范化。

scaler = StandardScaler()
X_train = scaler.fit_transform(X_train.reshape(X_train.shape[0], -1)).reshape(X_train.shape)
X_test = scaler.transform(X_test.reshape(X_test.shape[0], -1)).reshape(X_test.shape)
print(X_train.shape)
print(max(X_train[0][0]))
print(min(X_train[0][0]))

显然,将其转换为 2D 数组是行不通的,因为每个特征都针对所有 6800 个特征进行了归一化。这导致 所有 100 个步骤中的多个特征变为零。

例如,我正在寻找的特征[0] 是能量。对于一个批次,由于 100 个步骤,有 100 个能量值。我希望这 100 个能量值在自身内部标准化。

所以归一化应该在[1,1,0],[1,2,0],[1,3,0]...[1,100,0]之间进行。所有其他功能都一样。

我应该如何处理它?

更新:

以下代码是在 sai 的帮助下生成的。

def feature_normalization(x):
    batches_unrolled = np.expand_dims(np.reshape(x, (-1, x.shape[2])), axis=0)

    x_normalized = (x - np.mean(batches_unrolled, axis=1, keepdims=True)) / np.std(batches_unrolled, axis=1, keepdims=True)

    np.testing.assert_allclose(x_normalized[0, :, 0], (x[0, :, 0] - np.mean(x[:, :, 0])) / np.std(x[:, :, 0]))
    return x_normalized

def testset_normalization(X_train,X_test):
    batches_unrolled = np.expand_dims(np.reshape(X_train, (-1, x.shape[2])), axis=0)
    fitted_mean = np.mean(batches_unrolled, axis=1, keepdims=True)
    fitted_std = np.std(batches_unrolled, axis=1, keepdims=True)
    X_test_normalized = (X_test - fitted_mean) / fitted_std
    return X_test_normalized 

【问题讨论】:

应该是reshape(-1, X_train.shape[-1]) 两种方式都导致了同样的问题。 【参考方案1】:

在一个批次中独立地对所有样本的特征进行归一化-

    展开批量样本以获得 [10(time steps)*batch_size] x [40 features] 矩阵 获取每个特征的均值和标准差 对实际的批处理样本执行元素归一化
import numpy as np

x = np.random.random((20, 10, 40))

batches_unrolled = np.expand_dims(np.reshape(x, (-1, 40)), axis=0)

x_normalized = (x - np.mean(batches_unrolled, axis=1, keepdims=True)) / np.std(batches_unrolled, axis=1, keepdims=True)

np.testing.assert_allclose(x_normalized[0, :, 0], (x[0, :, 0] - np.mean(x[:, :, 0])) / np.std(x[:, :, 0]))

【讨论】:

是的,你是对的!实际上,我刚刚意识到,当我们进行标准化时,它不应该局限于每个批次,它应该包括所有批次及其 100 个步骤,但特征应该独立标准化。您介意修改您的代码以包含所有批次吗? @Leo,您意识到这一点是正确的。此外,除非您使用具有均匀分布的数据,否则标准化也不应仅限于某个批次。对于您正在使用的整个数据集,规范化通常应该相同 如果我希望将 x 的值限制为 [-1,1]。我应该执行 x_normalized = (x-np.min(batches_unrolled, axis=1, keepdims=True)) / (np.max(batches_unrolled, axis=1, keepdims=True)-np.min(batches_unrolled, axis=1, keepdims=True)) ?另外,我必须稍微调整一下代码以使其适合标准化 X_test,对吧? 我已经更新了问题,你介意看一下代码吗? 非常有可能展开一个批次,您的除法操作是在不同的轴上发生的,您必须自己检查。我的答案中提到的代码有效并经过测试。我建议您打印矩阵的形状并与您所期望的进行交叉检查。#

以上是关于如何根据自己的类型对 3D 数组的特定维度中的特征进行归一化的主要内容,如果未能解决你的问题,请参考以下文章

如何将 N-D 数组的最后两个维度作为 2D 数组?

Julia:如何根据具有特定值的类型字段访问类型数组中的元素

3d数组覆盖来自其他维度JS的值

sklearn的PCA

如何使用 JHDF5 读取/写入 3D+ 数组?

根据相互距离对 2D/3D 点数组进行排序的启发式方法