Различные результаты при оценке производительности модели на тестовых данных с использованием model.evaluate и model.predict

У меня есть вопрос относительно функций model.evaluate() и model.predict() в Keras. Я построил простую модель LSTM в Keras и хочу проверить производительность модели на тестовом наборе данных. Я рассмотрел следующие два способа вычисления метрики в тестовом наборе данных:

  • Используйте метод model.evaluate()
  • Используйте метод model.predict() для получения подогнанных значений и вычисления метрики вручную.

Однако в итоге я получил другие результаты. Кроме того, результаты для метода model.evaluate() также зависят от значения аргумента batch_size. Исходя из моего понимания и этого поста, они должны иметь одинаковые результаты. Вот код, который может воспроизвести результаты:

import tensorflow as tf
from keras.models import Model
from keras.layers import Dense, LSTM, Activation, Input
import numpy as np
from tqdm.notebook import tqdm
import keras.backend as K
from keras.callbacks import ModelCheckpoint, EarlyStopping

class VLSTM:
    def __init__(self, input_shape=(6, 1), nb_output_units=1, nb_hidden_units=128, dropout=0.0, 
                 recurrent_dropout=0.0, nb_layers=1):
        self.input_shape = input_shape
        self.nb_output_units = nb_output_units
        self.nb_hidden_units = nb_hidden_units
        self.nb_layers = nb_layers
        self.dropout = dropout
        self.recurrent_dropout = recurrent_dropout

    def build(self):
        inputs = Input(shape=self.input_shape)
        outputs = LSTM(self.nb_hidden_units)(inputs)
        outputs = Dense(1, activation=None)(outputs)
        return Model(inputs=[inputs], outputs=[outputs])
    
def RMSE(output, target):
    return K.sqrt(K.mean((output - target) ** 2))

n_train = 500
n_val = 100
n_test = 250 

X_train = np.random.rand(n_train, 6, 1)
Y_train = np.random.rand(n_train, 1)
X_val = np.random.rand(n_val, 6, 1)
Y_val = np.random.rand(n_val, 1)
X_test = np.random.rand(n_test, 6, 1)
Y_test = np.random.rand(n_test, 1)

input_shape = (X_train.shape[1], X_train.shape[2])
model = VLSTM(input_shape=input_shape)
m = model.build()
m.compile(loss=RMSE,
              optimizer='adam',
              metrics=[RMSE])

callbacks = []
callbacks.append(EarlyStopping(patience=30))


# train model
hist = m.fit(X_train, Y_train, \
             batch_size=32, epochs=10, shuffle=True, \
             validation_data=(X_val, Y_val), callbacks=callbacks)

# Use evaluate method with default batch size
test_mse = m.evaluate(X_test, Y_test)[1]
print("Mse is {} using evaluate method with default batch size".format(test_mse))

# Use evaluate method with batch size 1
test_mse = m.evaluate(X_test, Y_test, batch_size=1)[1]
print("Mse is {} using evaluate method with batch size = 1".format(test_mse))

# Use evaluate method with batch size = n_test
test_mse = m.evaluate(X_test, Y_test, batch_size=n_test)[1]
print("Mse is {} using evaluate method with batch size = n_test".format(test_mse))

# Use pred method and compute RMSE mannually
Y_test_pred = m.predict(X_test)
test_mse = np.sqrt( ((Y_test_pred - Y_test) ** 2).mean())
print("Mse is {} using evaluate method with batch size = 1".format(test_mse))

После запуска кодов вот результаты:

Mse составляет 0,3068242073059082 с использованием метода оценки с размером пакета по умолчанию.

Mse составляет 0,26647186279296875 с использованием метода оценки с размером партии = 1.

Mse составляет 0,30763307213783264 с использованием метода оценки с размером партии = n_test.

Mse составляет 0,3076330596820157 с использованием метода прогнозирования.

И похоже, что использование mode.predict() и model.evaluate() с размером пакета = n_test дает те же результаты. Кто-нибудь может это объяснить? Заранее спасибо!

Оптимизация производительности модели: Руководство по настройке гиперпараметров в Python с Keras
Оптимизация производительности модели: Руководство по настройке гиперпараметров в Python с Keras
Настройка гиперпараметров - это процесс выбора наилучшего набора гиперпараметров для модели машинного обучения с целью оптимизации ее...
Определение пород собак с помощью конволюционных нейронных сетей (CNN)
Определение пород собак с помощью конволюционных нейронных сетей (CNN)
В рамках финального проекта Udacity Data Scietist Nanodegree я разработал алгоритм с использованием конволюционных нейронных сетей (CNN) для...
0
0
57
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Да, ваша догадка верна, mse, рассчитанная с помощью прогноза, действительно равна оценке с помощью batch_size=len(набор данных).
Это очень легко понять, потому что, когда вы вычисляете mse с помощью прогнозирования, вы не делите свой набор данных на партии для его вычисления, вы просто вычисляете все сразу.

Очевидно, вы можете рассчитать свою mse с помощью прогноза, также разделив его на такие партии:

Y_test_pred_batches = np.split(Y_test_pred, 5 ,axis=0) #batch_size = 250/5=50 
Y_test_batches = np.split(Y_test, 5 ,axis=0)
batch_rmss = []
for y_pred, y_true in zip(Y_test_pred_batches, Y_test_batches):
    batch_rmss.append(rms(y_pred, y_true))
np.mean(batch_rmss)

Результат: 0,28436336682976376. Теперь с оценкой:

test_mse = m.evaluate(X_test, Y_test, batch_size=50)[1]
test_mse

Результат: 0,28436335921287537. Так что в принципе они одинаковые.

Если вы попробуете использовать np.split(Y_test_pred, 250, axis=0), что сделает размер пакета равным 1, в моем случае результат будет 0,24441334738835332. А при оценке batch_size=1 результат равен 0,244413360953331. Таким образом, вы можете видеть, что это то же самое.

Большое спасибо! Дополнительный вопрос: если мы хотим оценить производительность тестового набора данных с точки зрения RMSE, нам нужно установить batch_size = n_test, если мы используем метод model.evaluate, верно?

Qiuyu Gu 31.03.2023 19:30

Другие вопросы по теме