Функция потерь в Керасе не соответствует аналогичной функции - PullRequest
1 голос
/ 09 января 2020

Я сравнил результаты, полученные с помощью model.evaluate(...), и результаты с помощью numpy. Как видите, они сильно различаются. Ядро только что было перезапущено. Не могу найти, где проблема.

import numpy as np
import keras
from keras.layers import Dense
from keras.models import Sequential
import keras.backend as K

X = np.random.rand(10000)
Y = X + np.random.rand(10000) / 5

X_train, X_valid = X[:8000], X[8000:]
Y_train, Y_valid = Y[:8000], Y[8000:]

model = Sequential([
    Dense(1, input_shape=(1,), activation='linear'),
])
model.compile('adam', 'mae')
model.fit(X_train, Y_train, epochs=1, batch_size=2000, validation_data=(X_valid, Y_valid))

print(model.evaluate(X_valid, Y_valid))
>>> 0.15643194556236267

preds = model.predict(X_valid)
np.abs(Y_valid - preds).mean()
>>> 0.34461398701699736

Версии: keras = '2.3.1', tenorflow = '2.1.0'.

Ответы [ 2 ]

2 голосов
/ 09 января 2020

Это потому, что форма вывода model.predict не совпадает с Y_valid. Если вы получите транспонирование прогнозов, это даст вам почти такую ​​же потерю.

>>> Y_valid.shape                                                          
(2000,)
>>> preds.shape                                                            
(2000, 1)
>>> np.abs(Y_valid - np.transpose(preds)).mean()
1 голос
/ 09 января 2020

Это сложная задача, но на самом деле ее легко исправить:

Ваши цели Y_valid имеют форму (2000,), то есть просто массив из 2000 чисел. Однако сетевые выходы имеют форму (2000, 1). Затем выражение Y_valid - preds пытается вычесть фигуру (2000, 1) из фигуры (2000,) ... Эти два несовместимы и должны быть переданы. Стандартные правила вещания будут действовать следующим образом:

1. Align like  
(      2000,) 
(2000, 1)`

2. add extra dimension in front
(1,    2000,)  
(2000, 1)

3. broadcast to make compatible
(2000, 2000)
(2000, 2000)

... и поэтому вы фактически вычитаете два массива размером (2000, 2000) друг из друга. Вы в основном вычисляете разницу между каждым прогнозом и всеми целями вместо только соответствующего. Очевидно, что среднее значение этого будет гораздо больше.

tl; др: model.evaluate правильно. Ручное вычисление некорректно из-за забавного вещания. Вы можете исправить это, изменив прогнозы на (2000,) (или цели на (2000, 1):

preds = model.predict(X_valid)[:, 0]
np.abs(Y_valid - preds).mean()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...