Оценка тензорного потока дает большую ошибку, чем в последнюю эпоху обучения

#python #tensorflow #keras #tensorflow2.0

Вопрос:

У меня есть регрессионная модель тензорного потока. Я не думаю, что детали слоев модели связаны с вопросом, поэтому я пропускаю это. Я могу добавить это, если вы считаете, что это было бы полезно.

Я компилирую со следующим кодом. Потеря и показатель — это среднеквадратичная ошибка.

 model.compile(
    loss=tf.keras.losses.MeanSquaredError(), optimizer=tf.keras.optimizers.Adam(lr=0.001),
    metrics=['mse']
)
 

Теперь я запускаю следующий код для обучения сети и ее оценки. Я тренирую его в течение 2 эпох, затем оцениваю модель по тем же данным с evaluate помощью метода и оцениваю ее вручную, используя predict метод и формулу MSE.

 print('fit')
model.fit(X, y, epochs=2, batch_size=32)

print('evaluate')
print(model.evaluate(X, y))

print('manual evaluate')
print(((y - model.predict(X).ravel()) ** 2).mean())
 

Вот результат:

 3152/3152 [==============================] - 12s 3ms/step - loss: 7.7276 - mse: 7.7275
Epoch 2/2
3152/3152 [==============================] - 11s 4ms/step - loss: 0.9898 - mse: 0.9894
evaluate
3152/3152 [==============================] - 2s 686us/step - loss: 1.3753 - mse: 1.3748
[1.3753225803375244, 1.3747814893722534]
manual evaluate
1.3747820755885116
 

У меня есть небольшая регуляризация, поэтому потери немного больше, чем ожидалось, как и ожидалось.

Но, как вы можете видеть, MSE составляет 0,98 в конце последней эпохи. Тем не менее, я получаю 1,37 MSE, когда оцениваю его evaluate методом или когда я фактически вычисляю его вручную. Насколько я знаю, модель использует веса после последней эпохи, поэтому эти два числа должны быть равны, верно? Чего мне здесь не хватает? Я пробовал использовать разные размеры пакетов и количество эпох. Оцененный MSE всегда выше, чем MSE в последнюю эпоху метода подгонки.

Примечание: y является одномерным массивом NumPy

 y.shape
> (100836,)
 

Изменить: Я запускаю fit метод с validation_data параметром, используя те (X, y) же данные проверки:

 model.fit(X, y, epochs=2, batch_size=32, validation_data=(X, y))
 

Выход:

 Epoch 1/2
3152/3152 [==============================] - 23s 7ms/step - loss: 7.9766 - mse: 7.9764 - val_loss: 2.0284 - val_mse: 2.0280
Epoch 2/2
3152/3152 [==============================] - 22s 7ms/step - loss: 0.9839 - mse: 0.9836 - val_loss: 1.3436 - val_mse: 1.3431
evaluate
[1.3436073064804077, 1.3430677652359009]
 

Теперь в этом есть какой-то смысл. Последняя val_mse эпоха, похоже, совпадает с evaluate результатом. Но я ожидал mse , что значения и val_mse значения будут одинаковыми в индикаторе выполнения, поскольку данные обучения и данные проверки совпадают. Я думаю, что мое понимание того, что показывает индикатор выполнения, неверно. Может ли кто-нибудь объяснить, как я должен интерпретировать индикатор выполнения и почему mse и val_mse значения на индикаторе выполнения отличаются?

Комментарии:

1. У вас есть слои BatchNorm?

2. @Frightera, нет, в модели нет никакого слоя пакетной нормализации.

Ответ №1:

Причина, по которой для одних и тех же данных показатели (в вашем случае потери) различаются на этапах обучения и проверки, проста. А именно, во время обучения ваша модель тренируется, изменяя свои параметры от партии к партии. На индикаторе выполнения вы видите среднее значение показателя для всех партий. Напротив, на этапе проверки параметры вашей сети замораживаются. Используемые параметры-это параметры, полученные после обработки последней партии, которую видела сеть. Это объясняет разницу.

Вопрос о том, почему потеря валидации оказалась большей потерей при обучении, является тонким. Одной из причин может быть то, что в вашей модели есть слои, которые ведут себя по-разному во время обучения и проверки (например, BatchNorm, как заметил Frightera). Другой причиной может быть неправильная скорость обучения. Если он слишком велик, параметры будут слишком сильно меняться, тем самым пропуская реальный минимум. Даже с оптимизацией адама это может быть так.

Чтобы понять, в чем проблема со скоростью обучения, попробуйте сделать ее намного меньше. Если разница в метрике сохраняется, то слои вашей сети ведут себя по-разному на этапах обучения и проверки.

Могут быть и другие причины разницы в показателях. Например, обучающие данные зашумлены, так что сеть не может хорошо тренироваться. Это приведет к тому, что потери будут колебаться вблизи среднего значения, что является нормальным. Чтобы понять, так ли это, вам следует изучить графики потерь для разных партий (например, с помощью тензорной доски).

Комментарии:

1. Большое спасибо. Позвольте мне задать следующий вопрос, допустим, мои данные проверки совпадают с данными обучения, у меня есть 3 пакета, и каждый пакет содержит одни и те же данные. И допустим, после первой партии mse рассчитывается как 1,4. После второй партии он равен 1,2, а после последней партии-0,4. Таким образом, индикатор выполнения покажет 1,0 в качестве обучающего mse (путем усреднения всех значений mse пакета), но mse проверки будет 0,4 (так как параметры заморожены после 3-й партии). Это правда? Если это так, можем ли мы сказать, что mse должен увеличиваться от партии к партии в эпоху, чтобы наблюдать val_mse > train_mse?

2. Кроме того, нормализацию пакетов замечает Страхтера, а не я.

3. По первому вопросу. Я предполагаю, что во время обучения TF сначала вычисляет убыток, а затем обновляет параметры (будет странно, если TF вычислит убыток дважды, до и после обновления параметров). Следовательно, потеря проверки может отличаться от потери для последней партии (поскольку параметры изменились). По второму вопросу. Не обязательно — он может колебаться, в то время как в среднем все еще снижается. Колебания могут быть большими из-за неправильной скорости обучения или зашумленных данных.

4. Кстати, если вы хотите получить потери или какие-либо другие показатели по конкретным (проверочным) данным после обработки каждой партии , вы можете написать пользовательский callback . Подробнее о том, как это сделать, см. в этом руководстве .