参考:https://www.jianshu.com/p/e9d535b906fa
model.evaluate()
和 compile()
之间的关系?
evaluate()
并不会“调用” compile(),但它依赖 compile 的结果。
模型使用前必须先 .compile()
,否则 .fit()
和 .evaluate()
都不能用。
compile()
:设置好模型的“规则”(优化器 optimizer, 损失函数 loss, 评估指标 metrics等)evaluate()
:在预测完成后,会用你在compile
中指定的指标,来评估结果并返回
所以它们的关系是:
compile()
先设置好规则 👉evaluate()
才能使用这些规则进行打分。
evaluate()
里确实没有写 compile()
,但它默认用的就是你之前 .compile()
时设置的内容
test_loss, test_acc, test_auc, test_precision, test_recall = self.model.evaluate(
X_test,
{'output_1': y_test, 'output_2': np.zeros((len(y_test), ...))},
verbose=0
)
并 没有再次显式调用 compile()
,因为:
- 之前已经运行过
self.model.compile(...)
(比如在compile_model()
函数里) - 所以现在
.evaluate()
会自动使用之前设置的损失函数和评估指标 - 只需要提供输入数据
X_test
和目标输出y_test
✅ 它背后的机制是:
# 假设你之前已 compile:
model.compile(loss=..., metrics=['accuracy', AUC(), ...])
# 现在可以直接调用
model.evaluate(X_test, y_test)
# evaluate 会自动用你在 compile 时定义的规则返回:
# loss, accuracy, auc, ...
为什么 .evaluate()
只输入 X_test
和 y_test
,却能输出多个指标?
因为:
模型已经在
.compile()
阶段 提前“绑定”好了损失函数和评估指标,这些并不是在.evaluate()
时才传入的,而是早就存储在模型内部了。
可以理解成这样一个过程:
模型结构 = 一种“函数”
model = tf.keras.Model(...) # 定义好了结构,但还不能跑
compile()
= 给这个“函数”附加了规则:
model.compile(
optimizer=Adam(...),
loss={...}, # 指定损失函数
metrics={'output_1': [...]} # 指定评估指标
)
此时模型内部就已经存储好这些指标和损失的计算方法了。
所以:你只需要在 .evaluate()
时喂数据,模型就会:
- 自动把
X_test
喂进网络前向传播,得到预测结果y_pred
- 调用你 compile 时配置的 loss 函数,计算
y_test vs y_pred
的损失 - 调用你配置的 metrics,计算 accuracy、AUC、precision、recall……
- 然后按顺序返回这些值
.evaluate()
返回指标顺序怎么知道?
你可以查看它的指标名称列表:
print(model.metrics_names)
# ➜ ['loss', 'output_1_accuracy', 'output_1_auc', 'output_1_precision', 'output_1_recall']
所以如果你写:
loss, acc, auc, precision, recall = model.evaluate(...)
这就是多变量赋值,顺序必须与 metrics_names
一致。
.evaluate()
中的损失是怎么计算的?为什么说它是 y_test vs y_pred
?
.evaluate()
的本质就是:
使用 训练好的模型,对测试集
X_test
做预测(y_pred
),然后 和真实值y_test
比较,计算“损失”和“指标”。
损失不是简单“差值”,而是根据你设置的 损失函数(loss function) 来定义的。
例如:
任务类型 | 常见损失函数 | 作用 |
---|---|---|
二分类 | 'binary_crossentropy' | 衡量预测概率和真实标签之间的差异(比简单差值更合理) |
回归 | 'mse' (均方误差) | 用平方差来衡量预测值和真实值之间的差异 |
多分类 | 'categorical_crossentropy' | 衡量一个概率分布(预测)和目标分布之间的距离 |
所以当你在 .compile()
中写了:
loss={'output_1': 'binary_crossentropy'}
Keras 在 .evaluate()
时就会按照 交叉熵函数 来计算每个 y_pred
和 y_test
之间的损失值,而不是简单地 abs(y_pred - y_test)
或平方差。
损失函数定义了“什么叫预测得不好”,不同任务有不同标准,这就是它的价值。
.predict()
vs .evaluate()
的区别?
方法 | 作用 | 输出 | 是否需要标签 (y_test ) | 计算指标 |
---|---|---|---|---|
predict() | 仅做前向预测 | y_pred (模型输出) | ❌ 不需要 | ❌ 不计算损失、准确率等 |
evaluate() | 做预测 + 计算损失与指标 | loss , accuracy , AUC , … | ✅ 需要 y_test | ✅ 会计算并返回所有定义好的指标 |
举例说明:
用 .predict()
:
y_pred = model.predict(X_test)
你只会得到预测结果(比如概率或类别),但你得 自己写代码去评估预测得好不好(比如计算准确率、绘制 ROC)。
用 .evaluate()
:
loss, acc, auc = model.evaluate(X_test, y_test)
模型自动预测 + 自动根据你 .compile()
中定义的规则,计算 loss 和指标,一步完成。
总结
.predict()
是预测;.evaluate()
是预测 + 比较(用 compile 中定义的损失函数和指标)。