如何将NumPy数组归一化到特定范围内?
在对音频或图像数据进行处理后,我们需要把这些数据调整到一个特定的范围内,才能把它们保存到文件里。可以这样做:
# 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)
这里的关键词参数 axis
、with_mean
和 with_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 中能达到的最有效的解决方案。
就地操作不会改变容器数组的数据类型。因为我们想要的归一化值是浮点数,所以在进行就地操作之前,audio
和 image
数组需要是浮点数类型。如果它们还不是浮点数类型,你需要使用 astype
来进行转换。例如,
image = image.astype('float64')