如何自定义data.yaml并基于YOLO11x.pt实现单模型目标行为检测?
单模型实现目标检测+行为分类的YOLO11x训练方案
1. 标注数据直接复用,无需修改格式
你的标注格式class_id x_center y_center width height behavior_id可以直接保留,训练时让模型同时读取目标类别与行为类别标签即可。
2. 自定义data.yaml配置
在原有配置基础上,补充行为类别的参数,示例如下:
train: ./train/images val: ./val/images test: ./test/images # 目标检测类别配置 nc: 7 names: ['类别0', '类别1', '类别2', '类别3', '类别4', '类别5', '类别6'] # 替换为你的真实类别名称 # 行为分类类别配置 nb: 2 behavior_names: ['walking', 'standing']
3. 修改YOLO11x模型结构,新增行为分类分支
复制Ultralytics官方的YOLO11x.yaml文件,在检测头后新增行为分类分支,核心修改片段如下:
# 原YOLO11检测头部分(保留官方原有代码) head: # 此处省略官方YOLO11x检测头的其余层代码 - [-1, 1, Detect, [nc]] # nc=7,输出目标框与目标类别 # 新增行为分类头 - [-1, 1, Conv, [128, 1, 1]] # 压缩特征通道数 - [-1, 1, nn.AdaptiveAvgPool2d, [1]] # 全局平均池化 - [-1, 1, Flatten, []] # 展平特征张量 - [-1, 1, nn.Linear, [128, nb]] # nb=2,输出行为类别概率
4. 调整训练逻辑,同时计算两类损失
要让模型同时学习检测与分类任务,需修改数据集加载和损失计算逻辑:
- 数据集加载:在Ultralytics的
YOLODataset类中,修改__getitem__方法,读取标注里的第6个值(behavior_id)并作为额外标签返回,代码片段:
def __getitem__(self, index): # 原有加载图像、目标框、目标类别的代码保持不变 label_path = self.label_files[index] with open(label_path, 'r') as f: lines = f.read().splitlines() boxes = [] cls = [] behavior_labels = [] for line in lines: parts = list(map(float, line.split())) cls.append(int(parts[0])) boxes.append(parts[1:5]) behavior_labels.append(int(parts[5])) # 转换为张量格式 boxes = torch.tensor(boxes, dtype=torch.float32) cls = torch.tensor(cls, dtype=torch.long) behavior_labels = torch.tensor(behavior_labels, dtype=torch.long) # 返回包含行为标签的字典 return img, dict(boxes=boxes, cls=cls, behavior=behavior_labels)
- 损失计算:修改训练循环中的损失逻辑,将检测损失(CIoU损失+目标类别交叉熵损失)与行为分类的交叉熵损失加权求和,比如设置
loss = detection_loss + 0.5 * behavior_loss,权重可根据实际效果调整。
5. 推理与结果可视化
训练完成后,推理时模型会同时输出目标框、目标类别、行为类别,可视化时将两类标签合并标注在框上,示例代码:
from ultralytics import YOLO # 加载训练好的自定义模型 model = YOLO('runs/detect/train/weights/best.pt') # 单图推理 results = model('test_image.jpg') # 可视化并保存结果 for result in results: # 遍历每个检测框,匹配对应的目标类别与行为类别 for box, cls_idx, behavior_idx in zip(result.boxes.xyxy, result.boxes.cls, result.behavior): cls_name = model.names[int(cls_idx)] behavior_name = model.behavior_names[int(behavior_idx)] # 自定义标签内容 result.boxes.labels = [f"{cls_name} - {behavior_name}"] # 保存带标注的图像 result.save('output_result.jpg')
内容的提问来源于stack exchange,提问作者himanshu
相关产品推荐
相关产品推荐

