📊 Stage 06 · 模型评估 + Stage 07 · 保存测试

不会评估,等于没做

评估决定模型命运。混淆矩阵、ROC曲线、误差分析、数据迭代,这是让模型从"能用"到"好用"的关键环节。

🎯 混淆矩阵 + 指标计算(交互式)

调整下面的滑块,实时观察 Accuracy/Precision/Recall/F1 的变化

预测 vs 实际(二分类)
预测: 正
预测: 负
实际: 正
85
TP
15
FN
实际: 负
10
FP
90
TN
TP (真正例)85
FN (假负例)15
FP (假正例)10
TN (真负例)90
评估指标
Accuracy
--
整体正确率
Precision
--
查准率
Recall
--
查全率
F1-Score
--
平衡指标
📐 指标公式速查
Accuracy = (TP+TN) / (TP+FP+FN+TN)
Precision = TP / (TP+FP)
Recall = TP / (TP+FN)
F1 = 2 × P × R / (P + R)
💡 这是一个均衡的混淆矩阵,Precision和Recall相对平衡

🔍 误差分析:让模型真正变好

📉 欠拟合 vs 过拟合

欠拟合(高偏差)
训练集和验证集都很差
解决方案:
• 增加模型复杂度
• 增加特征维度
• 训练更久
过拟合(高方差)
训练好但验证差
解决方案:
• 增加训练数据
• 加正则化
• 早停 / 剪枝

🧩 常见错误类型

  • ⚠️
    类别混淆:模型把A类预测成B类 → 检查两类样本差异、增加区分性特征
  • ⚠️
    边界样本:分布边缘的样本容易错 → 主动学习收集更多边界样本
  • ⚠️
    困难样本:噪声/遮挡/极端角度 → 单独标注处理或数据增强
  • ⚠️
    类别不均衡:少数类召回率低 → 过采样/欠采样/加权损失

🔄 数据迭代闭环

📊
误差分析
🎯
定位问题
📥
补充数据
🏋️
重新训练
📈
验证提升
📊
误差分析

💡 行业经验:每迭代一轮,效果提升 2-5%。3-5轮迭代后通常能达到上线标准。

💾 模型保存与推理测试

📦 保存最佳实践

# 方法1:保存state_dict(推荐)
torch.save(model.state_dict(), 'models/final/best_model.pt')

# 方法2:保存完整模型
torch.save(model, 'models/final/best_model.pt')

# 方法3:ONNX格式(跨平台部署)
dummy = torch.randn(1, 3, 224, 224)
torch.onnx.export(model, dummy, 'model.onnx')

# 方法4:TorchScript(移动端)
traced = torch.jit.trace(model, dummy)
traced.save('model_scripted.pt')

# 方法5:保存训练状态(断点续训)
torch.save({
    'epoch': epoch,
    'model_state_dict': model.state_dict(),
    'optimizer_state_dict': optimizer.state_dict(),
    'best_val_acc': best_acc,
}, 'checkpoint.pth')

🔍 推理测试代码

import torch
from PIL import Image
from torchvision import transforms

# 1. 加载模型
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = MyModel(num_classes=5)
model.load_state_dict(torch.load('models/best.pt', map_location=device))
model = model.to(device)
model.eval()  # 重要!切换到评估模式

# 2. 数据预处理(必须和训练时一致!)
transform = transforms.Compose([
    transforms.Resize((224, 224)),
    transforms.ToTensor(),
    transforms.Normalize([0.485], [0.229])
])

# 3. 推理
def predict(image_path):
    img = Image.open(image_path).convert('RGB')
    tensor = transform(img).unsqueeze(0).to(device)  # 加batch维度
    
    with torch.no_grad():  # 关闭梯度计算
        output = model(tensor)
        probs = torch.softmax(output, dim=1)
        pred_idx = probs.argmax(1).item()
        confidence = probs[0, pred_idx].item()
    
    return {
        'class': class_names[pred_idx],
        'confidence': f'{confidence:.2%}',
        'all_probs': {class_names[i]: f'{p:.2%}' for i, p in enumerate(probs[0])}
    }

result = predict('test_image.jpg')
print(result)
← 返回训练调优 最终章:部署上线 →