web-dev-qa-db-ja.com

4D numpy配列を正規化する方法は?

画像の3次元のnumpy配列があります( CIFAR-10データセット )。画像配列の形状は次のとおりです。

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

ディープラーニングを行う前に、より良い結果を得るためにデータを正規化します。 1D配列を使用すると、次のように最小最大正規化を実行できることがわかります。

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配列でどのように実装しますか?

私はあなたの助けに感謝します!


編集:形状(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)
14
George Liu

形状(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)
15
Eric
  1. どの軸に沿って最小と最大を取りますか?

これに答えるためには、おそらくデータに関する詳細情報が必要ですが、一般に、たとえば3チャンネルの画像を議論する場合、チャンネルごとの最小値と最大値を使用して正規化します。つまり、チャネルごとに1回、正規化を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

編集:1つのチャネルデータ(たとえば32x32イメージ)を取得したら、次のように簡単に使用できることがわかりました。

from sklearn.preprocessing import normalize
img_a_norm = normalize(img_a)
  1. 3Dアレイをどのように使用しますか?

さて、これは少し大きな質問です。配列ごとの最小値や最大値などの関数が必要な場合は、Numpyバージョンを使用します。たとえば、インデックス付けは、上記の例からわかるように、軸全体の区切り記号によって実現されます。また、詳細については、Numpyのndarray @ https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.html のドキュメントを参照してください。彼らは本当にn次元配列のための素晴らしいツールセットを持っています。

3
antonmik

ここにはさまざまなアプローチがあります。画像のバッチ全体で正規化するか、単一の画像ごとに正規化するかを決定できます。これを行うには、単一の画像の平均を使用するか、画像のバッチ全体の平均を使用するか、別のデータセットの固定平均を使用します。 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)
0
tsveti_iko