Как нормализация данных работает в керах во время предсказания?
Я вижу, что imageDataGenerator позволяет мне указывать разные стили нормализации данных, например. featurewise_center, samplewise_center и т.д.
Из приведенных примеров видно, что если я укажу одну из этих опций, то мне нужно вызвать метод fit на генераторе, чтобы позволить генератору вычислить статистику как среднее изображение на генераторе.
(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)
Мой вопрос: как работает предсказание, если я задал нормализацию данных во время обучения? Я не вижу, как в рамках я бы даже передал знания о среднем значении /std для обучения, чтобы предсказать, чтобы я сам нормализовал свои тестовые данные, но я также не вижу в коде обучения, где эта информация сохранены.
Требуется ли статистика изображения для нормализации, хранящаяся в модели, чтобы они могли использоваться во время предсказания?
Ответы
Ответ 1
Да - это действительно огромный недостаток Keras.ImageDataGenerator
, который вы не могли бы предоставить статистике статистики самостоятельно. Но - есть простой способ решения этой проблемы.
Предполагая, что у вас есть функция normalize(x)
, которая нормализует изображение пакет (помните, что генератор не предоставляет простое изображение, но массив изображений - пакет с формой (nr_of_examples_in_batch, image_dims ..)
вы можете сделать свой собственный генератор с нормализацией, используя:
def gen_with_norm(gen, normalize):
for x, y in gen:
yield normalize(x), y
Тогда вы можете просто использовать gen_with_norm(datagen.flow, normalize)
вместо datagen.flow
.
Кроме того, вы можете восстановить mean
и std
, вычисленные методом fit
, получая его из соответствующих полей в datagen (например, datagen.mean
и datagen.std
).
Ответ 2
Используйте метод standardize
генератора для каждого элемента. Вот полный пример для 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))
Ответ 3
Я использую функцию datagen.fit
.
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)
В идеале с этим test_datagen
, установленный в наборе учебных материалов, будет изучать статистику учебных наборов данных. Затем он будет использовать эти статистические данные для нормализации данных тестирования.
Ответ 4
У меня также была такая же проблема, и я решил ее использовать ту же функциональность, что и 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), ...)
Обратите внимание, что это возможно только в том случае, если у вас есть разумный небольшой набор данных, например CIFAR-10. В противном случае решение предложенное Marcin, звучит более разумно.