如何规范化4D numpy阵列?

时间:2017-02-25 18:52:14

标签: python arrays numpy deep-learning

我有一个三维numpy图像数组(CIFAR-10 dataset)。图像阵列形状如下所示:

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

在我深入学习之前,我想对数据进行规范化以获得更好的结果。使用一维数组,我知道我们可以像这样进行最大最小规范化:

v = np.random.rand(6)
(v - v.min())/(v.max() - v.min())

Out[68]:
array([ 0.89502294,  0.        ,  1.        ,  0.65069468,  0.63657915,
        0.08932196])

然而,当谈到3D阵列时,我完全迷失了。具体来说,我有以下问题:

  1. 我们沿着哪个轴取最小值和最大值?
  2. 我们如何使用3D阵列实现这一点?
  3. 感谢您的帮助!

    编辑: 事实证明我需要使用形状为(202, 32, 32, 3)的4D Numpy数组,因此第一个维度是图像的索引,最后3个维度是实际图像。如果有人可以为我提供规范化这样一个4D阵列的代码,那就太棒了。谢谢!

    编辑2: 感谢@ Eric的代码,我已经弄明白了:

    x_min = x.min(axis=(1, 2), keepdims=True)
    x_max = x.max(axis=(1, 2), keepdims=True)
    
    x = (x - x_min)/(x_max-x_min)
    

3 个答案:

答案 0 :(得分:15)

假设您正在使用形状(W, H, 3)的图像数据,您应该分别对每个频道(axis=2)进行标准化,如另一个答案中所述。

你可以这样做:

# keepdims makes the result shape (1, 1, 3) instead of (3,). This doesn't matter here, but
# would matter if you wanted to normalize over a different axis.
v_min = v.min(axis=(0, 1), keepdims=True)
v_max = v.max(axis=(0, 1), keepdims=True)
(v - v_min)/(v_max - v_min)

答案 1 :(得分:3)

  1. 我们沿着哪个轴取最小值和最大值?
  2. 要回答这个问题,我们可能需要有关您数据的更多信息,但一般来说,在讨论3个频道图像时,我们会使用每个频道的最小值和最大值进行标准化。这意味着我们将执行3次标准化 - 每个通道一次。 这是一个例子:

        img = numpy.random.randint(0, 100, size=(10, 10, 3))  # Generating some random numbers
        img = img.astype(numpy.float32)  # converting array of ints to floats
        img_a = img[:, :, 0]
        img_b = img[:, :, 1]
        img_c = img[:, :, 2]  # Extracting single channels from 3 channel image
        # The above code could also be replaced with cv2.split(img) << which will return 3 numpy arrays (using opencv)
    
        # normalizing per channel data:
        img_a = (img_a - numpy.min(img_a)) / (numpy.max(img_a) - numpy.min(img_a))
        img_b = (img_b - numpy.min(img_b)) / (numpy.max(img_b) - numpy.min(img_b))
        img_c = (img_c - numpy.min(img_c)) / (numpy.max(img_c) - numpy.min(img_c))
    
        # putting the 3 channels back together:
        img_norm = numpy.empty((10, 10, 3), dtype=numpy.float32)
        img_norm[:, :, 0] = img_a
        img_norm[:, :, 1] = img_b
        img_norm[:, :, 2] = img_c
    

    编辑:我刚想到,只要你拥有一个通道数据(例如32x32图像),你就可以使用:

    from sklearn.preprocessing import normalize
    img_a_norm = normalize(img_a)
    
    1. 我们如何使用3D阵列?
    2. 嗯,这是一个很大的问题。如果你需要像array-wise min和max这样的函数,我会使用Numpy版本。例如,索引是通过轴宽分离器实现的 - 正如您从上面的示例中可以看到的那样。 另外,请参阅Numpy的文档ndarray @ https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.html 了解更多。他们真的有一套令人惊奇的n维数组工具。

答案 2 :(得分:0)

这里有不同的方法。您可以决定对整批图像进行标准化,也可以对每张图像进行标准化。为此,您既可以使用单个图像的均值,也可以使用整批图像的均值,或者使用另一个数据集的固定均值-例如您可以使用ImageNet平均值。

如果要执行与Tensorflow的tf.image.per_image_standardization相同的操作,则应使用该图像的均值对每个图像进行归一化。因此,您可以遍历所有图像,并对单个图像中的所有轴进行归一化,如下所示:

import math
import numpy as np
from PIL import Image

# open images
image_1 = Image.open("your_image_1.jpg")
image_2 = Image.open("your_image_2.jpg")
images = [image_1, image_2]
images = np.array(images)
standardized_images = []

# standardize images
for image in images:
    mean = image.mean()
    stddev = image.std()
    adjusted_stddev = max(stddev, 1.0/math.sqrt(image.size))
    standardized_image = (image - mean) / adjusted_stddev
    standardized_images.append(standardized_image)

standardized_images = np.array(standardized_images)