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?
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
).
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))
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,
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.