我比较了通过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'。
答案 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()