it-swarm.com.de

Wie normalisiere ich ein 4D-numpy-Array?

Ich habe ein dreidimensionales numpy-Array von Bildern ( CIFAR-10-Datensatz ). Die Form des Bildarrays sieht wie folgt aus:

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

Bevor ich tiefes Lernen mache, möchte ich die Daten normalisieren, um bessere Ergebnisse zu erzielen. Mit einem 1D-Array weiß ich, dass wir eine minimale Normalisierung wie folgt durchführen können:

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

Bei einem 3D-Array bin ich jedoch völlig verloren. Im Einzelnen habe ich folgende Fragen:

  1. Auf welcher Achse nehmen wir min und max?
  2. Wie implementieren wir das mit dem 3D-Array?

Ich schätze Ihre Hilfe!


BEARBEITEN: Es stellt sich heraus, dass ich mit einem 4D Numpy-Array mit Shape (202, 32, 32, 3) arbeiten muss. Die erste Dimension wäre also der Index für das Bild und die letzten 3 Dimensionen sind das eigentliche Bild. Es wäre toll, wenn mir jemand den Code zur Normalisierung eines solchen 4D-Arrays zur Verfügung stellt. Vielen Dank!


EDIT 2: Dank @ Eric's Code unten habe ich es herausgefunden:

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)
13
George Liu

Angenommen, Sie arbeiten mit Bilddaten der Form (W, H, 3), sollten Sie wahrscheinlich jeden Kanal (axis=2) separat normalisieren, wie in der anderen Antwort erwähnt.

Sie können dies mit:

# 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)
14
Eric
  1. Auf welcher Achse nehmen wir min und max?

Um dies zu beantworten, benötigen wir wahrscheinlich mehr Informationen zu Ihren Daten. Wenn Sie beispielsweise über 3-Kanal-Bilder sprechen, würden wir im Allgemeinen die Min- und Max-Werte pro Kanal verwenden. Dies bedeutet, dass wir die Normalisierung dreimal durchführen würden - einmal pro Kanal . Hier ein Beispiel:

    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

Edit: Mir ist gerade eingefallen, dass, wenn Sie einmal die Daten eines Kanals haben (32x32-Bild zum Beispiel), Sie einfach Folgendes verwenden können:

from sklearn.preprocessing import normalize
img_a_norm = normalize(img_a)
  1. Wie arbeiten wir mit dem 3D-Array?

Nun, das ist eine große Frage. Wenn Sie Funktionen wie Array-weise Min und Max benötigen, würde ich die Numpy-Versionen verwenden. Die Indizierung wird beispielsweise durch achsweite Separatoren erreicht - wie Sie an meinem obigen Beispiel sehen können. Weitere Informationen finden Sie in der Dokumentation von Numpy zu ndarray @ https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.html Sie verfügen über wirklich erstaunliche Werkzeuge für n-dimensionale Arrays.

3
antonmik

Hier gibt es unterschiedliche Ansätze. Sie können entweder den gesamten Bildstapel normalisieren oder pro Bild normalisieren. Dazu können Sie entweder den Mittelwert eines einzelnen Bildes oder den Mittelwert des gesamten Bildstapels verwenden oder einen festen Mittelwert aus einem anderen Datensatz verwenden, z. Sie können den Mittelwert ImageNet verwenden. 

Wenn Sie dasselbe tun wollen wie Tensorflows tf.image.per_image_standardization , sollten Sie jedes einzelne Bild mit dem Mittelwert dieses Bildes normalisieren. Sie durchlaufen also alle Bilder und führen die Normalisierung für alle Achsen in einem einzigen Bild wie folgt aus:

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