如何将 NumPy 数组标准化到一定范围内?

发布于 2024-08-11 07:53:38 字数 384 浏览 7 评论 0原文

对音频或图像数组进行一些处理后,需要在一定范围内对其进行标准化,然后才能写回文件。这可以像这样完成:

# 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() 似乎不相关。

After doing some processing on an audio or image array, it needs to be normalized within a range before it can be written back to a file. This can be done like so:

# 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)

Is there a less verbose, convenience function way to do this? matplotlib.colors.Normalize() doesn't seem to be related.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

私野 2024-08-18 07:53:38
# 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')
# 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())

Using /= and *= allows you to eliminate an intermediate temporary array, thus saving some memory. Multiplication is less expensive than division, so

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

is marginally faster than

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

Since we are using basic numpy methods here, I think this is about as efficient a solution in numpy as can be.


In-place operations do not change the dtype of the container array. Since the desired normalized values are floats, the audio and image arrays need to have floating-point point dtype before the in-place operations are performed.
If they are not already of floating-point dtype, you'll need to convert them using astype. For example,

image = image.astype('float64')
佼人 2024-08-18 07:53:38

如果数组同时包含正数和负数数据,我会选择:

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,或者引发错误。

最后,值得一提的是,即使这不是OP的问题,标准化

e = (a - np.mean(a)) / np.std(a)

If the array contains both positive and negative data, I'd go with:

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

If the array contains nan, one solution could be to just remove them as:

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

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

However, depending on the context you might want to treat nan differently. E.g. interpolate the value, replacing in with e.g. 0, or raise an error.

Finally, worth mentioning even if it's not OP's question, standardization:

e = (a - np.mean(a)) / np.std(a)
甚是思念 2024-08-18 07:53:38

您还可以使用 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,则就地执行操作。

You can also rescale using sklearn.preprocessing.scale. The advantages are that you can adjust normalize the standard deviation, in addition to mean-centering the data, and that you can do this on either axis, by features, or by records.

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

The keyword arguments axis, with_mean, with_std are self explanatory, and are shown in their default state. The argument copy performs the operation in-place if it is set to False.

携君以终年 2024-08-18 07:53:38

您正在尝试在 -1 和 +1 之间缩放 audio 的值,在 0 到 255 之间缩放 image 的值。

使用 sklearn.preprocessing.minmax_scale,应该很容易解决你的问题。

例如:

audio_scaled = minmax_scale(audio, feature_range=(-1,1))

shape = image.shape
image_scaled = minmax_scale(image.ravel(), feature_range=(0,255)).reshape(shape)

注意:不要与缩放的操作混淆将向量的范数(长度)调整为某个值(通常为 1),这通常也称为归一化。

You are trying to min-max scale the values of audio between -1 and +1 and image between 0 and 255.

Using sklearn.preprocessing.minmax_scale, should easily solve your problem.

e.g.:

audio_scaled = minmax_scale(audio, feature_range=(-1,1))

and

shape = image.shape
image_scaled = minmax_scale(image.ravel(), feature_range=(0,255)).reshape(shape)

note: Not to be confused with the operation that scales the norm (length) of a vector to a certain value (usually 1), which is also commonly referred to as normalization.

迷雾森÷林ヴ 2024-08-18 07:53:38

这个答案类似的问题为我解决了问题

np.interp(a, (a.min(), a.max()), (-1, +1))

This answer to a similar question solved the problem for me with

np.interp(a, (a.min(), a.max()), (-1, +1))
神经暖 2024-08-18 07:53:38

您可以使用“i”(如 idiv、imul..)版本,它看起来还不错:

image /= (image.max()/255.0)

对于另一种情况,您可以编写一个函数来按列标准化 n 维数组:

def normalize_columns(arr):
    rows, cols = arr.shape
    for col in xrange(cols):
        arr[:,col] /= abs(arr[:,col]).max()

You can use the "i" (as in idiv, imul..) version, and it doesn't look half bad:

image /= (image.max()/255.0)

For the other case you can write a function to normalize an n-dimensional array by colums:

def normalize_columns(arr):
    rows, cols = arr.shape
    for col in xrange(cols):
        arr[:,col] /= abs(arr[:,col]).max()
寄居人 2024-08-18 07:53:38

一个简单的解决方案是使用 sklearn.preprocessing 库提供的缩放器。

scaler = sk.MinMaxScaler(feature_range=(0, 250))
scaler = scaler.fit(X)
X_scaled = scaler.transform(X)
# Checking reconstruction
X_rec = scaler.inverse_transform(X_scaled)

错误 X_rec-X 将为零。您可以根据需要调整 feature_range,甚至使用标准缩放器 sk.StandardScaler()

A simple solution is using the scalers offered by the sklearn.preprocessing library.

scaler = sk.MinMaxScaler(feature_range=(0, 250))
scaler = scaler.fit(X)
X_scaled = scaler.transform(X)
# Checking reconstruction
X_rec = scaler.inverse_transform(X_scaled)

The error X_rec-X will be zero. You can adjust the feature_range for your needs, or even use a standart scaler sk.StandardScaler()

墨离汐 2024-08-18 07:53:38

我尝试按照 this 进行操作,并收到错误

TypeError: ufunc 'true_divide' output (typecode 'd') could not be coerced to provided output parameter (typecode 'l') according to the casting rule ''same_kind''

The numpy array I was试图标准化是一个整数数组。看来他们不赞成在版本 > 中进行类型转换1.10,你必须使用numpy.true_divide()来解决这个问题。

arr = np.array(img)
arr = np.true_divide(arr,[255.0],out=None)

img 是一个 PIL.Image 对象。

I tried following this, and got the error

TypeError: ufunc 'true_divide' output (typecode 'd') could not be coerced to provided output parameter (typecode 'l') according to the casting rule ''same_kind''

The numpy array I was trying to normalize was an integer array. It seems they deprecated type casting in versions > 1.10, and you have to use numpy.true_divide() to resolve that.

arr = np.array(img)
arr = np.true_divide(arr,[255.0],out=None)

img was an PIL.Image object.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文