Comment fonctionne la normalisation des données dans keras pendant la prédiction?

je vois que l'imageDataGenerator me permet de spécifier différents styles de normalisation des données, par exemple featurewise_center, samplewise_center, etc.

je vois dans les exemples que si je spécifie une de ces options, alors je dois appeler la méthode fit sur le générateur afin de permettre au générateur de calculer des statistiques comme l'image moyenne sur le générateur.

(X_train, y_train), (X_test, y_test) = cifar10.load_data()
Y_train = np_utils.to_categorical(y_train, nb_classes)
Y_test = np_utils.to_categorical(y_test, nb_classes)

datagen = ImageDataGenerator(
    featurewise_center=True,
    featurewise_std_normalization=True,
    rotation_range=20,
    width_shift_range=0.2,
    height_shift_range=0.2,
    horizontal_flip=True)

# compute quantities required for featurewise normalization
# (std, mean, and principal components if ZCA whitening is applied)
datagen.fit(X_train)

# fits the model on batches with real-time data augmentation:
model.fit_generator(datagen.flow(X_train, Y_train, batch_size=32),
                samples_per_epoch=len(X_train), nb_epoch=nb_epoch)

ma question est, comment fonctionne la prédiction si j'ai spécifié la normalisation des données pendant de formation? Je ne vois pas comment, dans le cadre, je réussirais même la connaissance de la déviation moyenne/std De l'ensemble de formation à prédire pour me permettre de normaliser mes données d'essai moi-même, mais je ne vois pas non plus dans le code de formation où cette information est stockée.

est-ce que les statistiques d'image nécessaires à la normalisation sont stockées dans le modèle pour qu'elles puissent être utilisées lors de la prédiction?

11
demandé sur Marcin Możejko 2017-01-25 18:33:34

4 réponses

Oui - c'est vraiment un énorme inconvénient de Keras.ImageDataGenerator que vous ne pouviez pas fournir les statistiques de standarisation tout seul. Mais - il y a une méthode facile sur la façon de surmonter ce problème.

en Supposant que vous avez une fonction normalize(x) qui normalise une image lot (rappelez - vous que generator ne fournit pas une image simple mais un tableau d'images-a lot forme (nr_of_examples_in_batch, image_dims ..) vous pourriez faire votre propre générateur avec normalisation par en utilisant:

def gen_with_norm(gen, normalize):
    for x, y in gen:
        yield normalize(x), y

alors vous pouvez simplement utiliser gen_with_norm(datagen.flow, normalize) au lieu de datagen.flow.

de plus - vous pourriez récupérer le mean et std calculé par un fit méthode en l'obtenant à partir des champs appropriés dans datagen (par exemple datagen.mean et datagen.std).

15
répondu Marcin Możejko 2017-01-25 15:51:48

standardize méthode du générateur pour chaque élément. Voici un exemple complet pour CIFAR 10:

#!/usr/bin/env python

import keras
from keras.datasets import cifar10
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D

# input image dimensions
img_rows, img_cols, img_channels = 32, 32, 3
num_classes = 10

batch_size = 32
epochs = 1

# The data, shuffled and split between train and test sets:
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')

# Convert class vectors to binary class matrices.
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

model = Sequential()

model.add(Conv2D(32, (3, 3), padding='same', activation='relu',
                 input_shape=x_train.shape[1:]))
model.add(Conv2D(32, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Conv2D(64, (3, 3), padding='same', activation='relu'))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Flatten())
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))

model.compile(loss='categorical_crossentropy', optimizer='rmsprop',
              metrics=['accuracy'])

x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255

datagen = ImageDataGenerator(zca_whitening=True)

# Compute principal components required for ZCA
datagen.fit(x_train)

# Apply normalization (ZCA and others)
print(x_test.shape)
for i in range(len(x_test)):
    # this is what you are looking for
    x_test[i] = datagen.standardize(x_test[i])
print(x_test.shape)

# Fit the model on the batches generated by datagen.flow().
model.fit_generator(datagen.flow(x_train, y_train,
                                 batch_size=batch_size),
                    steps_per_epoch=x_train.shape[0] // batch_size,
                    epochs=epochs,
                    validation_data=(x_test, y_test))
17
répondu Martin Thoma 2017-03-28 12:20:32

j'utilise le datagen.fit fonction elle-même.

from keras.preprocessing.image import ImageDataGenerator

train_datagen = ImageDataGenerator(
    featurewise_center=True,
    featurewise_std_normalization=True)
train_datagen.fit(train_data)

test_datagen = ImageDataGenerator(  
    featurewise_center=True, 
    featurewise_std_normalization=True)
test_datagen.fit(train_data)

Idéalement avec cela,

2
répondu Hari 2017-05-12 06:14:28

j'ai aussi eu le même problème et je l'ai résolu en utilisant la même fonctionnalité que le ImageDataGenerator:

# Load Cifar-10 dataset
(trainX, trainY), (testX, testY) = cifar10.load_data()
generator = ImageDataGenerator(featurewise_center=True, 
                               featurewise_std_normalization=True)

# Calculate statistics on train dataset
generator.fit(trainX)
# Apply featurewise_center to test-data with statistics from train data
testX -= generator.mean
# Apply featurewise_std_normalization to test-data with statistics from train data
testX /= (generator.std + K.epsilon())

# Do your regular fitting
model.fit_generator(..., validation_data=(testX, testY), ...)

notez que cela n'est possible que si vous avez un ensemble de données raisonnable, comme CIFAR-10. Sinon, le solution proposée par Marcin semble bon plus raisonnable.

0
répondu Alexander Pacha 2017-05-23 12:02:39