Keras中的损失函数与类比函数不匹配

时间:2020-01-09 11:30:24

标签: python numpy tensorflow keras

我比较了通过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',张量流='2.1.0'。

2 个答案:

答案 0 :(得分:2)

这是因为model.predict的输出形状与Y_valid不同。如果您得到了预测的转置,它将给您几乎相同的损失。

>>> Y_valid.shape                                                          
(2000,)
>>> preds.shape                                                            
(2000, 1)
>>> np.abs(Y_valid - np.transpose(preds)).mean()

答案 1 :(得分:1)

这是一个棘手的问题,但实际上很容易解决:

您的目标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)的两个数组。您基本上是在计算每个预测目标与 all 目标之间的差异,而不仅仅是相应的目标。显然,这样做的平均值会更大。

tl; dr:model.evaluate是正确的。由于有趣的广播,手动计算不正确。您可以通过将预测重塑为(2000,)(或将目标重塑为(2000, 1)来修正它:

preds = model.predict(X_valid)[:, 0]
np.abs(Y_valid - preds).mean()