#python #tensorflow #machine-learning #keras #conv-neural-network
#python #тензорный поток #машинное обучение #keras #conv-нейронная сеть
Вопрос:
Я пытаюсь создать CNN, который мог бы определять числа на изображении. Для этого я начал работать с набором данных Street View House Numbers (SVHN). Этот набор данных поставляется с предварительно обработанными изображениями, масштабированными до 32×32 цифр.Существует 10 классов для 10 чисел.
Я обучил сеть, и это дает приличную точность тестирования, близкую к ~ 0,93. Точность теста также рассчитывается на тестовом наборе, который представляет собой набор из 32×32 цифр.
Это все хорошо. Но проблема в том, что вероятность прогнозирования всегда равна единице. Вот как выглядит вывод одного из классов:
array([[0.0000000e 00, 0.0000000e 00, 0.0000000e 00, 0.0000000e 00,
1.0000000e 00, 8.5623318e-24, 0.0000000e 00, 0.0000000e 00,
0.0000000e 00, 2.4716297e-28]], dtype=float32)
Как видно из вывода одного из примеров, вероятность класса для одного из классов равна 1
. Это нормально для изображения, которое содержит изображение нужного класса, но вероятность 1 возникает, даже если на изображении нет знака числа. Например, следующее изображение предсказывает класс 4
с вероятностью 1
. На самом деле приведенное выше распределение предназначено для следующего изображения.
Изображение:
Я не смог определить причину этого. Я делюсь кодом, который я использовал для создания CNN.
val_split_length = 10623
num_train_samples = 73257
num_test_samples = 26032
total_classes = 10
model_prefix = "10c"
model = keras.Sequential()
# First Conv. Layer
model.add(keras.layers.Conv2D(filters = 96, kernel_size = (11,11), strides = (4,4), padding = "same", input_shape=(227,227,3)))
model.add(keras.layers.Activation("relu"))
model.add(keras.layers.BatchNormalization())
model.add(keras.layers.MaxPooling2D(pool_size = (3,3), strides = (2,2), padding="same"))
# ##More Conv. Layers ###
# First Fully Connected Layer
model.add(keras.layers.Flatten())
model.add(keras.layers.Dense(4096))
model.add(keras.layers.Activation("relu"))
model.add(keras.layers.Dropout(0.5))
## More Fully Connected Layers ###
# Third Fully Connected Layer
model.add(keras.layers.Dense(total_classes))
model.add(keras.layers.Activation("softmax"))
train_optimizer_adam = tf.train.AdamOptimizer(learning_rate=1e-3)
train_optimizer_rmsProp = keras.optimizers.RMSprop(lr=0.0001)
#https://keras.io/optimizers/
model.compile(loss="categorical_crossentropy", optimizer=train_optimizer_rmsProp, metrics=['accuracy'])
batch_size = 128 * 3
data_generator = keras.preprocessing.image.ImageDataGenerator(rescale = 1./255)
# https://keras.io/preprocessing/image/#flow_from_directory
train_generator = data_generator.flow_from_directory(
'train',
target_size=(227, 227),
batch_size=batch_size,
color_mode='rgb',
class_mode='categorical',
#save_to_dir="logs"
)
validation_generator = data_generator.flow_from_directory(
'validation',
target_size=(227, 227),
batch_size=batch_size,
color_mode='rgb',
class_mode='categorical')
# https://keras.io/models/model/#fit_generator
history = model.fit_generator(
train_generator,
validation_data = validation_generator,
validation_steps = math.ceil(val_split_length / batch_size),
epochs = 5,
steps_per_epoch = math.ceil(num_train_samples / batch_size),
use_multiprocessing = True,
workers = 8,
callbacks = model_callbacks,
verbose = 2
)
Для прогнозирования из модели выше:
img = cv2.imread("image.png")
img = cv2.resize(img, (227,227))
loaded_model = keras.models.load_model("saved-model-12-0.96.hdf5")
prob = loaded_model.predict_proba(np.expand_dims(img, axis = 0))
print(prob)
Что может быть причиной того, что я получаю высокую вероятность для класса, который нигде не существует на изображении? Я понимаю, что модель что-то предсказывает, но почему вероятность так высока?
Комментарии:
1. На самом деле это не вопрос программирования. Причина в том, что вероятности не откалиброваны, поэтому они не имеют никакого реального значения как вероятности. Модель всегда обучалась с вероятностями 1.0, поэтому ожидается, что она будет работать именно так.
2. @MatiasValdenegro Я хотел бы с вами не согласиться. Очень маловероятно, что вы получите такое уверенное предсказание (т. Е. Максимальную вероятность 1) в CNN, даже в очень хорошей модели. Проблема, скорее всего, связана с неправильной предварительной обработкой тестового изображения (т. Е. Не Используется тот же конвейер предварительной обработки, что и на этапе обучения). Вот почему модель выдает такой резкий пик выходных значений.
Ответ №1:
Проблема в том, что вы не применяете конвейер предварительной обработки, который вы использовали во время обучения модели. В частности, вы должны масштабировать значения пикселей изображения на 1/255.
:
img = img.astype('float32') / 255.
Действительно важно следовать тому же конвейеру предварительной обработки на этапе тестирования, который используется на этапе обучения; в противном случае ваша модель может запутаться и выдавать неправильные прогнозы.
Комментарии:
1. Это делается в генераторе 😉
data_generator = keras.preprocessing.image.ImageDataGenerator(rescale = 1./255)
2. @TheLoneDeranger Пожалуйста, внимательно прочитайте тестовый код! Генератор здесь неуместен.
3. Я не уверен, что вы имеете в виду, но я вижу, что прогноз не масштабируется, да.
4. @TheLoneDeranger Я имею в виду, что генератор не используется, когда OP использует свою модель для прогнозирования одного изображения (т. Е. Последнего блока кода в вопросе OP). Кроме того, это не имеет ничего общего с масштабированием прогнозирования ; скорее входные данные должны быть масштабированы. Вот почему это называется предварительной обработкой (а не последующей обработкой).
5. «Входные данные должны быть предсказаны», ваше величество.