画像の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アレイに関しては、完全に失われています。具体的には、次の質問があります。
私はあなたの助けに感謝します!
編集:形状(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)
形状(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)
これに答えるためには、おそらくデータに関する詳細情報が必要ですが、一般に、たとえば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)
さて、これは少し大きな質問です。配列ごとの最小値や最大値などの関数が必要な場合は、Numpyバージョンを使用します。たとえば、インデックス付けは、上記の例からわかるように、軸全体の区切り記号によって実現されます。また、詳細については、Numpyのndarray @ https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.html のドキュメントを参照してください。彼らは本当にn次元配列のための素晴らしいツールセットを持っています。
ここにはさまざまなアプローチがあります。画像のバッチ全体で正規化するか、単一の画像ごとに正規化するかを決定できます。これを行うには、単一の画像の平均を使用するか、画像のバッチ全体の平均を使用するか、別のデータセットの固定平均を使用します。 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)