Потеря вывода Keras и прямое распространение не совпадают - PullRequest
1 голос
/ 12 октября 2019

введите описание изображения здесь

Я использую предварительно обученную модель Keras ResNet50 для обучения моего собственного набора дат, который содержит только одно изображение для целей тестирования. Сначала я оцениваю модель с моим изображением и получаю потерю 0,5 и точность 1. Затем я подгоняю модель и получаю потерю 6 и точность 0. Я не понимаю, почему потеря вывода ипрямое распространение не совпадает. Кажется, что поведение вывода и прямого распространения в Керасе различно. Я приложил свой фрагмент кода и скриншот.

model = ResNet50(weights='imagenet')

img_path = 'elephant.jpg'
img = image.load_img(img_path, target_size=(224, 224))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)

y = np.zeros((1, 1000))
y[0, 386] = 1

model.compile(loss='categorical_crossentropy', optimizer='sgd', metrics=['categorical_accuracy'])

model.evaluate(x, y)

1/1 [=============================] - 1 с 547 мс/ step [0.5232877135276794, 1.0]

model.fit(x, y, validation_data=(x, y))

Поезд на 1 пробе, проверка на 1 пробе Эпоха 1/1 1/1 [==============================] - 3s 3s / step - потеря: 6.1883 - категорическая точность: 0,0000e + 00 - val_loss: 9,8371e-04 - val_categorical_accuracy: 1,0000

model.evaluate(x, y)

1/1 [=============================] - 0 с 74 мс/ шаг [0,0009837078396230936, 1,0]

1 Ответ

0 голосов
/ 12 октября 2019

Извините за неправильное понимание вопроса. Проблема очень сложная. И проблема, вероятно, вызвана слоем BatchNorm, как @Natthaphon упоминал в комментариях, потому что я пробовал на VGG16, потери совпадают.

Затем я проверил в ResNet50, и потери в eval и в фитинге все еще не совпадают, хотя я "замораживаю" все слои. На самом деле, я вручную проверяю веса BN, они действительно не изменены.

from keras.applications import ResNet50, VGG16
from keras.applications.resnet50 import preprocess_input
from keras_preprocessing import image
import keras
from keras import backend as K
import numpy as np

img_path = '/home/zhihao/Downloads/elephant.jpeg'
img = image.load_img(img_path, target_size=(224, 224))

model = ResNet50(weights='imagenet')

for layer in model.layers:
    layer.trainable = False

x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)

y = np.zeros((1, 1000))
y[0, 386] = 1

model.compile(loss='categorical_crossentropy', optimizer='sgd', metrics=['categorical_accuracy'])

model.evaluate(x, y)
# 1/1 [==============================] - 2s 2s/step
# [0.2981376349925995, 1.0]

model.fit(x, y, validation_data=(x, y))
# Train on 1 samples, validate on 1 samples
# Epoch 1/1
# 1/1 [==============================] - 1s 549ms/step - loss: 5.3056 - categorical_accuracy: 0.0000e+00 - val_loss: 0.2981 - val_categorical_accuracy: 1.0000

Мы можем заметить, что потери в оценке равны 0,2981, а потери в форме - 5,3056. Я предполагаю, что слои Batch Norm имеют различное поведение между режимом eval и режимом train . Поправьте меня если я ошибаюсь.

Один из способов по-настоящему заморозить найденную мной модель - использовать K.set_learning_phase(0), как показано ниже,

model = ResNet50(weights='imagenet')

K.set_learning_phase(0)  # all new operations will be in test mode from now on

model.fit(x, y, validation_data=(x, y))

# Train on 1 samples, validate on 1 samples
# Epoch 1/1
# 1/1 [==============================] - 4s 4s/step - loss: 0.2981 - categorical_accuracy: 1.0000 - val_loss: 16.1181 - val_categorical_accuracy: 0.0000e+00

Теперь эти две потери совпадают.

...