You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取训练/测试集单值性能指标?解决Epoch重复打印问题

问题分析与解决方案

你的代码存在的核心问题

  1. 重复输出+指标无法捕获:test函数每次被调用(不管传入训练集还是测试集Loader),都会直接打印所有指标、弹出PR曲线和混淆矩阵图。主循环每个epoch会调用两次test,导致每个epoch重复输出两次指标;同时test只返回了准确率(Acc),精确率、召回率等其他指标你在主循环里拿不到,没法统一整理输出。
  2. 缺少梯度禁用:test函数里仅用了model.eval()但没加torch.no_grad(),评估阶段会保留计算图,浪费显存,甚至可能影响结果稳定性。

解决方案:重构代码,统一控制指标输出

1. 修改test函数,返回所有需要的指标

把打印、画图逻辑从test中剥离,让它只负责计算指标并返回,这样你可以在主循环里统一控制输出节奏:

import torch
from sklearn.metrics import precision_score, recall_score, classification_report, confusion_matrix
from sklearn.metrics import PrecisionRecallDisplay
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np

def test(loader):
    output_predictions = []
    target = []
    model.eval()
    correct = 0

    # 禁用梯度计算,节省显存
    with torch.no_grad():
        for data in loader:
            model_output = my_model(data)
            predictions = model_output.argmax(dim=1)
            correct += predictions.eq(data.y).sum().item() 
            output_predictions.extend(predictions.tolist())
            target.extend(data.y.tolist())

    # 计算所有指标
    acc = correct / len(loader.dataset)
    class_likelihood = class_likelihood_ratios(target, output_predictions, labels=[0,1])
    cls_report = classification_report(target, output_predictions, labels=[0,1])
    precision = precision_score(target, output_predictions, labels=[0,1])
    recall = recall_score(target, output_predictions, labels=[0,1])
    conf_matrix = confusion_matrix(target, output_predictions)

    # 返回所有指标,不在这里打印/画图
    return acc, precision, recall, class_likelihood, cls_report, conf_matrix, target, output_predictions

2. 单独写可视化函数(可选)

把画图逻辑抽成独立函数,方便控制是否/何时画图:

def plot_eval_metrics(target, predictions, conf_matrix, set_name):
    # 绘制PR曲线
    fig, ax = plt.subplots()
    PrecisionRecallDisplay.from_predictions(target, predictions, ax=ax)
    ax.set_title(f"{set_name} 精确率-召回率曲线")
    plt.show()

    # 绘制归一化混淆矩阵
    plt.figure()
    sns.heatmap(conf_matrix/np.sum(conf_matrix), annot=True, fmt='.2%', 
                xticklabels=[1,0], yticklabels=[1,0])
    plt.title(f"{set_name} 混淆矩阵(归一化)")
    plt.show()

3. 主循环统一打印汇总结果

在主循环里调用test获取所有指标,一次性输出每个epoch的训练/测试性能:

for epoch in range(1, 50):
    train()
    # 获取训练集所有指标
    train_acc, train_p, train_r, train_lh, train_cr, train_conf, train_target, train_pred = test(train_loader)
    # 获取测试集所有指标
    test_acc, test_p, test_r, test_lh, test_cr, test_conf, test_target, test_pred = test(test_loader)

    # 统一打印当前epoch的结果
    print(f"=== 第 {epoch:03d} 轮训练 ===")
    print("训练集:")
    print(f"准确率: {train_acc:.4f}, 精确率: {train_p:.4f}, 召回率: {train_r:.4f}")
    print("分类报告:\n", train_cr)
    print("正负类似然比:", train_lh)
    
    print("\n测试集:")
    print(f"准确率: {test_acc:.4f}, 精确率: {test_p:.4f}, 召回率: {test_r:.4f}")
    print("分类报告:\n", test_cr)
    print("正负类似然比:", test_lh)

    # 可选:每隔N轮画一次图,避免频繁弹窗
    if epoch % 5 == 0:
        plot_eval_metrics(train_target, train_pred, train_conf, "训练集")
        plot_eval_metrics(test_target, test_pred, test_conf, "测试集")

效果说明

现在每个epoch只会打印一次汇总的训练/测试指标,精确率、召回率都是单个数值,完全符合你的预期。你可以根据需求调整打印内容,比如只保留关键指标,把分类报告等详细内容写入日志文件,避免控制台杂乱。

内容的提问来源于stack exchange,提问作者Susan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 12:58:19