如何将NumPy数组归一化到特定范围内?

223 投票
8 回答
485425 浏览
提问于 2025-04-15 16:00

在对音频或图像数据进行处理后,我们需要把这些数据调整到一个特定的范围内,才能把它们保存到文件里。可以这样做:

# Normalize audio channels to between -1.0 and +1.0
audio[:,0] = audio[:,0]/abs(audio[:,0]).max()
audio[:,1] = audio[:,1]/abs(audio[:,1]).max()

# Normalize image to between 0 and 255
image = image/(image.max()/255.0)

有没有更简单、更方便的方法来做到这一点呢?比如说,matplotlib.colors.Normalize() 似乎跟这个没什么关系。

8 个回答

46

你还可以使用 sklearn.preprocessing.scale 来重新调整数据的比例。这样做的好处是,你不仅可以让数据的平均值为零,还可以调整标准差。而且你可以选择在不同的方向上进行调整,比如按特征或者按记录。

from sklearn.preprocessing import scale
X = scale(X, axis=0, with_mean=True, with_std=True, copy=True)

这里的关键词参数 axiswith_meanwith_std 的意思都很简单,默认状态下的效果也都展示出来了。参数 copy 如果设置为 False,那么操作会直接在原数据上进行,而不是复制一份新的数据。

130

如果数组里同时有正数和负数,我会选择:

import numpy as np

a = np.random.rand(3,2)

# Normalised [0,1]
b = (a - np.min(a))/np.ptp(a)

# Normalised [0,255] as integer: don't forget the parenthesis before astype(int)
c = (255*(a - np.min(a))/np.ptp(a)).astype(int)        

# Normalised [-1,1]
d = 2.*(a - np.min(a))/np.ptp(a)-1

如果数组里有 nan(表示“不是一个数字”的意思),一种解决办法就是直接把它们去掉,像这样:

def nan_ptp(a):
    return np.ptp(a[np.isfinite(a)])

b = (a - np.nanmin(a))/nan_ptp(a)

不过,根据具体情况,你可能想要对 nan 采取不同的处理方式。比如,可以用其他值来填补它,比如用0,或者直接报错。

最后,虽然这不是提问者的问题,但值得一提的是 标准化

e = (a - np.mean(a)) / np.std(a)
212
# Normalize audio channels to between -1.0 and +1.0
audio /= np.max(np.abs(audio),axis=0)
# Normalize image to between 0 and 255
image *= (255.0/image.max())

使用 /=*= 可以省去一个临时数组,这样可以节省一些内存。因为乘法的计算成本比除法低,所以

image *= 255.0/image.max()    # Uses 1 division and image.size multiplications

在速度上会稍微快一点

image /= image.max()/255.0    # Uses 1+image.size divisions

由于我们在这里使用的是基本的 numpy 方法,我认为这是在 numpy 中能达到的最有效的解决方案。


就地操作不会改变容器数组的数据类型。因为我们想要的归一化值是浮点数,所以在进行就地操作之前,audioimage 数组需要是浮点数类型。如果它们还不是浮点数类型,你需要使用 astype 来进行转换。例如,

image = image.astype('float64')

撰写回答