Matplotlib-绘制训练曲线指南
Matplotlib-绘制训练曲线指南
- 一、训练曲线的核心要素
- 二、基础实现:绘制损失与准确率曲线
- 1. 准备模拟训练数据
- 2. 绘制单幅损失曲线
- 3. 绘制准确率曲线(双图布局)
- 三、进阶美化:让曲线更具可读性
- 1. 自定义线条样式与颜色
- 2. 添加关键标注:最佳epoch与过拟合点
- 3. 调整坐标轴范围与刻度
- 4. 保存高清图像
- 四、实战技巧:处理真实训练日志
- 1. 解析训练日志
- 2. 绘制平滑曲线
- 五、常见问题与解决方案
- 1. 曲线抖动剧烈
- 2. 训练与验证曲线差距过大(过拟合)
- 3. 多模型对比曲线
模型训练过程中,训练曲线通过可视化训练集与验证集的损失值、准确率等指标随迭代次数的变化,能够帮我们判断模型是否过拟合、欠拟合,或是需要调整学习率。
一、训练曲线的核心要素
训练曲线的核心是迭代次数与模型指标的对应关系,常见的指标包括:
- 损失值(Loss):模型预测值与真实值的差距,通常随训练下降
- 准确率(Accuracy):分类任务中预测正确的样本比例,通常随训练上升
- 精确率(Precision)、召回率(Recall):用于不平衡数据集的性能评估
一个完整的训练曲线通常包含两条线:
- 训练集指标曲线(如
train_loss
) - 验证集指标曲线(如
val_loss
)
通过对比两条曲线的走势,可快速判断模型状态: - 若两者差距小且均趋于稳定:模型拟合良好
- 若训练集指标优但验证集指标差:过拟合
- 若两者指标均较差:欠拟合
二、基础实现:绘制损失与准确率曲线
1. 准备模拟训练数据
首先生成模拟的训练过程数据(实际应用中可从模型训练日志中提取):
import numpy as np
import matplotlib.pyplot as plt# 生成迭代次数(100个epoch)
epochs = np.arange(1, 101)# 生成训练损失(逐渐下降,带轻微波动)
train_loss = 3.0 * np.exp(-0.05 * epochs) + 0.2 * np.random.random(100)
# 生成验证损失(先降后升,模拟轻微过拟合)
val_loss = 2.5 * np.exp(-0.04 * epochs) + 0.3 * np.random.random(100) + 0.1 * (epochs > 50)# 生成训练准确率(逐渐上升)
train_acc = 0.5 + 0.4 * (1 - np.exp(-0.05 * epochs)) + 0.02 * np.random.random(100)
# 生成验证准确率
val_acc = 0.45 + 0.35 * (1 - np.exp(-0.04 * epochs)) + 0.02 * np.random.random(100)
2. 绘制单幅损失曲线
使用plt.plot()
绘制训练与验证损失曲线,并添加必要的标签和标题:
plt.figure(figsize=(10, 6)) # 设置画布大小# 绘制损失曲线
plt.plot(epochs, train_loss, label='Training Loss', color='blue', linewidth=2)
plt.plot(epochs, val_loss, label='Validation Loss', color='red', linewidth=2, linestyle='--')# 添加标签与标题
plt.xlabel('Epochs', fontsize=12)
plt.ylabel('Loss', fontsize=12)
plt.title('Training and Validation Loss', fontsize=14, pad=20)# 添加网格与图例
plt.grid(alpha=0.3) # 网格线透明度
plt.legend(fontsize=12)# 调整布局
plt.tight_layout()
plt.show()
3. 绘制准确率曲线(双图布局)
为了同时展示损失和准确率,可使用plt.subplots()
创建双子图布局:
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5)) # 1行2列布局# 左图:损失曲线
ax1.plot(epochs, train_loss, label='Train Loss', color='blue')
ax1.plot(epochs, val_loss, label='Val Loss', color='red', linestyle='--')
ax1.set_xlabel('Epochs')
ax1.set_ylabel('Loss')
ax1.set_title('Loss Curves')
ax1.grid(alpha=0.3)
ax1.legend()# 右图:准确率曲线
ax2.plot(epochs, train_acc, label='Train Acc', color='green')
ax2.plot(epochs, val_acc, label='Val Acc', color='orange', linestyle='--')
ax2.set_xlabel('Epochs')
ax2.set_ylabel('Accuracy')
ax2.set_title('Accuracy Curves')
ax2.grid(alpha=0.3)
ax2.legend()plt.tight_layout()
plt.show()
三、进阶美化:让曲线更具可读性
1. 自定义线条样式与颜色
选择合适的线条样式和颜色能让曲线更易区分:
plt.figure(figsize=(10, 6))# 训练曲线:实线、深蓝色、圆点标记
plt.plot(epochs, train_loss, label='Train Loss', color='#1f77b4', linewidth=2, marker='o', markersize=3, markevery=5)# 验证曲线:虚线、深红色、方块标记
plt.plot(epochs, val_loss, label='Val Loss', color='#ff4d4d', linewidth=2, linestyle='--', marker='s', markersize=3, markevery=5)plt.xlabel('Epochs', fontsize=12)
plt.ylabel('Loss', fontsize=12)
plt.title('Loss Curves with Custom Styles', fontsize=14)
plt.grid(alpha=0.3, linestyle=':') # 虚线网格
plt.legend(fontsize=10)
plt.show()
- 使用十六进制颜色码(如
#1f77b4
)可精确控制颜色 markevery=5
表示每隔5个点显示一个标记,避免线条过密
2. 添加关键标注:最佳epoch与过拟合点
在曲线上标注关键节点(如验证损失最低的epoch),增强分析价值:
plt.figure(figsize=(10, 6))
plt.plot(epochs, train_loss, label='Train Loss', color='blue')
plt.plot(epochs, val_loss, label='Val Loss', color='red', linestyle='--')# 找到验证损失最小的epoch
best_epoch = np.argmin(val_loss) + 1 # 注意epochs从1开始
best_loss = val_loss[best_epoch - 1]# 添加标注点
plt.scatter(best_epoch, best_loss, color='green', s=100, zorder=5) # zorder确保点在曲线上方
# 添加文本标注
plt.annotate(f'Best Epoch: {best_epoch}', xy=(best_epoch, best_loss),xytext=(best_epoch + 5, best_loss + 0.2),arrowprops=dict(facecolor='black', shrink=0.05))plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.title('Loss Curves with Best Epoch Annotation')
plt.legend()
plt.grid(alpha=0.3)
plt.show()
3. 调整坐标轴范围与刻度
合理设置坐标轴范围可避免曲线过于紧凑:
plt.figure(figsize=(10, 6))
plt.plot(epochs, train_acc, label='Train Acc', color='green')
plt.plot(epochs, val_acc, label='Val Acc', color='orange', linestyle='--')# 设置y轴范围(准确率通常在0-1之间)
plt.ylim(0.4, 1.0)
# 设置x轴刻度间隔
plt.xticks(np.arange(0, 101, 10)) # 每10个epoch显示一个刻度plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.title('Accuracy Curves with Adjusted Axes')
plt.legend()
plt.grid(alpha=0.3)
plt.show()
4. 保存高清图像
使用plt.savefig()
保存图像时,设置dpi
参数可确保高清显示:
plt.figure(figsize=(10, 6))
# ... 绘制曲线代码 ...# 保存为PNG格式,分辨率300dpi
plt.savefig('training_curves.png', dpi=300, bbox_inches='tight')
# 保存为PDF格式(矢量图,适合论文)
plt.savefig('training_curves.pdf', bbox_inches='tight')
bbox_inches='tight'
可去除图像周围多余空白
四、实战技巧:处理真实训练日志
在实际项目中,训练曲线的数据通常来自模型训练过程的日志(如PyTorch或TensorFlow的训练记录)。以下是一个从日志文件中提取数据并绘图的示例:
1. 解析训练日志
假设日志文件train_log.txt
内容如下:
Epoch 1: train_loss=2.302, val_loss=2.201, train_acc=0.30, val_acc=0.35
Epoch 2: train_loss=2.001, val_loss=1.950, train_acc=0.40, val_acc=0.45
...
解析代码:
# 读取日志文件
with open('train_log.txt', 'r') as f:lines = f.readlines()# 提取数据
epochs = []
train_losses = []
val_losses = []
train_accs = []
val_accs = []for line in lines:parts = line.strip().split(', ')epoch = int(parts[0].split()[1])train_loss = float(parts[0].split('=')[1])val_loss = float(parts[1].split('=')[1])train_acc = float(parts[2].split('=')[1])val_acc = float(parts[3].split('=')[1])epochs.append(epoch)train_losses.append(train_loss)val_losses.append(val_loss)train_accs.append(train_acc)val_accs.append(val_acc)# 转换为numpy数组
epochs = np.array(epochs)
train_losses = np.array(train_losses)
# ... 其他数组同理
2. 绘制平滑曲线
若训练曲线波动较大,可使用滑动平均进行平滑:
def smooth_curve(points, factor=0.9):"""滑动平均平滑曲线"""smoothed = []for point in points:if smoothed:smoothed_val = smoothed[-1] * factor + point * (1 - factor)smoothed.append(smoothed_val)else:smoothed.append(point)return np.array(smoothed)# 平滑损失曲线
train_loss_smoothed = smooth_curve(train_losses)
val_loss_smoothed = smooth_curve(val_losses)# 绘制平滑曲线
plt.plot(epochs, train_loss_smoothed, label='Smoothed Train Loss')
plt.plot(epochs, val_loss_smoothed, label='Smoothed Val Loss')
五、常见问题与解决方案
1. 曲线抖动剧烈
- 原因:batch_size过小或学习率过大
- 解决:绘制平滑曲线,或在训练时增加batch_size、减小学习率
2. 训练与验证曲线差距过大(过拟合)
- 解决方案:在图中添加垂直虚线标记正则化开始生效的epoch
plt.axvline(x=50, color='gray', linestyle='--', label='Regularization Applied')
3. 多模型对比曲线
如需对比不同超参数的模型性能,可在同一图中绘制多条曲线:
# 模型1:学习率0.01
plt.plot(epochs, val_acc_model1, label='LR=0.01', color='blue')
# 模型2:学习率0.001
plt.plot(epochs, val_acc_model2, label='LR=0.001', color='green')
# 模型3:学习率0.1
plt.plot(epochs, val_acc_model3, label='LR=0.1', color='red')
That’s all, thanks for reading~~
觉得有用就点个赞
、收进收藏
夹吧!关注
我,获取更多干货~