基于python3.12
时间: 2025-06-12 13:22:41 浏览: 14
<think>我们正在使用YOLOv8,并且需要在Python3.12环境中自定义训练指标并记录日志。根据之前讨论的方法,我们将通过自定义回调函数来实现,并在训练过程中记录到TensorBoard和CSV文件。注意,YOLOv8的最新版本(如ultralytics8.x)支持在Python3.12中运行。步骤:1.创建一个自定义回调类,用于计算自定义指标(例如精确率、召回率等),并在验证结束后将指标添加到训练器的metrics中。2.使用TensorBoard或自定义的CSV记录器记录这些指标。3.在训练时注入该回调函数。注意:在自定义指标计算中,我们可以利用验证器(validator)返回的预测结果和真实标签。不过,YOLOv8在验证过程中已经计算了许多指标,我们可以在其基础上添加。具体实现:首先,我们导入必要的模块,并定义一个回调类。这个回调类将在每个验证阶段结束时被调用。</think>
### 在Python 3.12中为YOLOv8自定义训练指标并记录日志
以下是完整的实现指南,基于YOLOv8的最新架构(截至2024年)适配Python 3.12环境:
#### 一、核心实现步骤
1. **创建自定义回调类**
```python
from ultralytics.engine.trainer import BaseTrainer
from ultralytics.utils import LOGGER
import numpy as np
from sklearn.metrics import f1_score
class CustomMetricsCallback:
def __init__(self, prefix='custom_'):
self.prefix = prefix
self.f1_history = []
def on_val_end(self, trainer: BaseTrainer):
"""验证结束后计算自定义指标"""
# 获取预测结果和真实标签
preds = np.array([p.boxes.cls.cpu().numpy() for p in trainer.validator.pred])
targets = np.array([t['cls'].cpu().numpy() for t in trainer.validator.targets])
try:
# 计算F1分数(示例)
f1 = f1_score(targets.flatten(), preds.flatten(), average='macro')
# 更新训练器指标
trainer.metrics[self.prefix + 'f1'] = f1
self.f1_history.append(f1)
# 日志记录
LOGGER.info(f"{self.prefix}f1: {f1:.4f}")
except Exception as e:
LOGGER.error(f"计算F1分数失败: {str(e)}")
trainer.metrics[self.prefix + 'f1'] = 0.0
```
2. **创建日志记录系统**
```python
class EnhancedLogger:
def __init__(self, log_dir: str):
import os
from torch.utils.tensorboard import SummaryWriter
os.makedirs(log_dir, exist_ok=True)
self.tb_writer = SummaryWriter(log_dir)
self.csv_path = os.path.join(log_dir, 'custom_metrics.csv')
# 初始化CSV文件
with open(self.csv_path, 'w') as f:
f.write('epoch,f1_score,lr\n')
def log_metrics(self, epoch, metrics, lr):
"""记录到TensorBoard和CSV"""
# TensorBoard
self.tb_writer.add_scalar('Custom/F1', metrics.get('custom_f1', 0), epoch)
self.tb_writer.add_scalar('Custom/LR', lr, epoch)
# CSV
with open(self.csv_path, 'a') as f:
f.write(f'{epoch},{metrics.get("custom_f1",0):.4f},{lr:.6f}\n')
```
#### 二、集成到训练流程
```python
from ultralytics import YOLO
# 初始化组件
model = YOLO('yolov8n.yaml')
metric_callback = CustomMetricsCallback(prefix='custom_')
logger = EnhancedLogger('custom_logs')
# 自定义训练循环
for epoch in range(1, 11): # 示例:10个epoch
# 训练+验证
results = model.train(
data='coco128.yaml',
epochs=1, # 单epoch训练
resume=True if epoch > 1 else False,
callbacks={'on_val_end': [metric_callback.on_val_end]}
)
# 记录自定义指标
current_lr = model.optimizer.param_groups[0]['lr']
logger.log_metrics(epoch, results, current_lr)
# 添加动态学习率调整示例
if metric_callback.f1_history and metric_callback.f1_history[-1] < 0.7:
for param_group in model.optimizer.param_groups:
param_group['lr'] *= 0.9 # 降低学习率
LOGGER.info(f"F1<0.7, 新学习率: {model.optimizer.param_groups[0]['lr']:.6f}")
# 关闭记录器
logger.tb_writer.close()
```
#### 三、关键技术要点(Python 3.12适配)
1. **数据类型处理**
```python
# Python 3.12中更严格的类型检查
preds = preds.astype(np.int64) # 确保整型一致
targets = targets.astype(np.int64)
```
2. **协程与异步支持**
```python
import asyncio
async def async_logging(logger, data):
await asyncio.to_thread(logger.log_metrics, *data)
```
3. **错误处理增强**
```python
except (ValueError, RuntimeError) as e:
LOGGER.warning(f"指标计算警告: {e!r}")
```
#### 四、验证与可视化
1. **TensorBoard查看**
```bash
tensorboard --logdir=custom_logs --port=6006
```
2. **结果分析**
```python
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv('custom_logs/custom_metrics.csv')
plt.figure(figsize=(12, 5))
plt.subplot(121)
plt.plot(df.epoch, df.f1_score, 'o-', label='F1 Score')
plt.subplot(122)
plt.semilogy(df.epoch, df.lr, 's-', label='Learning Rate')
plt.savefig('custom_metrics_trend.png')
```
#### 五、最佳实践
1. **多阶段指标计算**
```python
def on_train_end(self, trainer):
# 计算所有epoch的平均F1
trainer.metrics[self.prefix + 'avg_f1'] = np.mean(self.f1_history)
```
2. **分布式训练适配**
```python
if trainer.world_size > 1: # 多GPU训练
all_f1 = [torch.zeros(1).to(trainer.device) for _ in range(trainer.world_size)]
torch.distributed.all_gather(all_f1, torch.tensor([f1]).to(trainer.device))
f1 = torch.cat(all_f1).mean().item()
```
3. **模型保存条件**
```python
if f1 > max(self.f1_history, default=0):
trainer.save_model() # 保存最佳模型
```
> **关键优势**:该方法避免修改YOLOv8源码,保持框架兼容性,通过回调机制实现高度可定制化[^1]。自定义日志可直接整合进YOLO的Result对象,支持后续分析管道[^2]。
阅读全文
相关推荐

















