yolox微调训练日记

20250516

今天在测试视频的时候发现在某些角度,Alphapose不能识别运动员的位姿,思来想去应该是yolo的问题,alphapose是一个先识别人体再使用hrnet或者resnet进行识别的一个网络,所以如果连人的框都没有就不用提能不能识别位姿了,yolov3训练是势在必行了,但是alphapose里面的yolov3是一个印度人写的,并不是纯正血统的yolo3,并且没有训练教程,并且还是使用torch编写的darknet进行部署,darknet的部署是用.weight文件,而当前官方使用的是.pt文件,把我恶心坏了。

正当我想今晚大干要训练一下这个yolox的时候,天无绝人之路,我突然想到alphapose是支持yolox的,并且是纯正血统的yolox,测试发现本身的yolo识别运动员的概率还更高,所以目前的结论是:我得微调训练一个yolox的权重

另外今晚发现一个事情,我带着我的没有预训练的权重到北京测试那里的视频,发现竟然没有识别,我以为是放在.cache文件里面的权重也会进行训练而我并没有复制过来导致的,今天通过计算哈希的方法发现经过训练之后的在cache中的权重并没有变化,然后又测试了在北京测试的没有识别成功的视频,发现在家是识别不了这些视频的,所以结论是:我的不是通过微调训练的,而是重新完全训练的权重,在训练数据集上过拟合了,而且过拟合的程度非常高,即使同样是运动员,换了新的视频就无法识别了,所以我之后也只能微调训练

建立COCO数据集

这里不讲。我这里直接用自己建立好的,里面只有person一种类别

微调YOLOX-l模型

因为发现yolox-l性能最适合,所以微调这个模型,微调过程中只需要注意exp这个文件夹,exp/default中是默认的yolox参数,这里是一个官方的参考参数,以及部署时候应该使用的参数。

注意的是,每个yolox_*.py中的self.depth和self.width是给每个模型定义的参数,比如如果你想训练或者使用yolo-s,那你的参数为self.depth = 0.33 self.width = 0.50,如果你想训练或者使用yolo-l,那你的参数为self.depth = 1.0 self.width = 1.0。

保持这里的default文件夹不要动,我们重新在exps/example/custom里建立我们训练和部署用的参数。比如复制yolox_l.py到exps/example/custom中并重命名为yolox_l_pose.py。编写文件如下,修改其中的训练数据位置和训练批次

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Exp(MyExp):
def __init__(self):
super(Exp, self).__init__()
self.depth = 1.0
self.width = 1.0
self.exp_name = os.path.split(os.path.realpath(__file__))[1].split(".")[0]

# Define yourself dataset path
self.data_dir = "/home/houbosen/AlphaPose/data/coco"
self.train_ann = "/home/houbosen/AlphaPose/data/coco/annotations/person_keypoints_train2017.json"
self.val_ann = "/home/houbosen/AlphaPose/data/coco/annotations/person_keypoints_val2017.json"

self.num_classes = 80
# self.num_classes = 1

self.max_epoch = 100
self.data_num_workers = 4
self.eval_interval = 20

修改训练类别数

注意如果你想修改训练类别,那设置yolox_l_pose.py文件中的num_classes为需要的类别,注意默认是80而不是71

1
self.num_classes = 1

然后在YOLOX/yolox/data/datasets/coco_classes.py修改对应的具体类别名称,我这里只有一个person类别。

1
2
3
COCO_CLASSES = (
"person",
)

然后进行训练,注意加载预训练模型的时候会警告说预训练权重是输出80个类的,但是这里只需要1个类,没关系

1
2
3
4
5
6
7
# 应该是类似的输出,就是说后面的head层size不一致
size mismatch for head.cls_preds.0.weight: copying a param with shape torch.Size([1, 128, 1, 1]) from checkpoint, the shape in current model is torch.Size([80, 128, 1, 1]).
size mismatch for head.cls_preds.0.bias: copying a param with shape torch.Size([1]) from checkpoint, the shape in current model is torch.Size([80]).
size mismatch for head.cls_preds.1.weight: copying a param with shape torch.Size([1, 128, 1, 1]) from checkpoint, the shape in current model is torch.Size([80, 128, 1, 1]).
size mismatch for head.cls_preds.1.bias: copying a param with shape torch.Size([1]) from checkpoint, the shape in current model is torch.Size([80]).
size mismatch for head.cls_preds.2.weight: copying a param with shape torch.Size([1, 128, 1, 1]) from checkpoint, the shape in current model is torch.Size([80, 128, 1, 1]).
size mismatch for head.cls_preds.2.bias: copying a param with shape torch.Size([1]) from checkpoint, the shape in current model is torch.Size([80]).
1
2
3
4
5
6
7
8
9
10
11
12
13
CUDA_VISIBLE_DEVICES=0,1,2,3 python -m yolox.tools.train \
-f exps/example/custom/yolox_l_pose1.py \
-d 4 \ # 用4张卡
-b 32 \ # 一般是卡数*8
--fp16 \ #混合精度
-c yolox_l.pth #下载官方的预训练权重,不用预训练的权重过拟合很严重

CUDA_VISIBLE_DEVICES=3 python -m yolox.tools.train \
-f exps/example/custom/yolox_s_pose1.py \
-d 1 \
-b 8 \
--fp16 \
-c ./YOLOX_outputs/yolox_s_coco2_num1epoth100BestHuang/best_ckpt.pth

注意一点,如果你想要推理的时候,就不要加载默认的参数文件了,否则会报错说网络框架应该输出80个类别但是训练之后的权重只有一个类别输出,推理的时候加在的参数文件还得是yolox_l_pose.py

1
2
3
4
5
6
7
8
9
python tools/demo.py image 
-f exps/example/custom/yolox_l_pose.py
-c /path/to/your/yolox_s.pth
--path assets/dog.jpg
--conf 0.25
--nms 0.45
--tsize 640
--save_result
--device [cpu/gpu]

为什么要注意这一点呢?因为在alphapose里默认加载的是default/yolox_l.py,然后权重和模型架构不一致就会导致报错,所以如果在其他项目中比如人体关键点检测项目中发现了用到了yolox,那你训练了一个只输出一个类别的权重,那你需要修改default文件夹中的参数。

通过tensorboard查看当前训练状态

1
2
3
4
5
6
7
8
9
10
tensorboard --logdir YOLOX_outputs/yolox_s_pose1/tensorboard --port=0
# 输出如下,打开网页即可
TensorFlow installation not found - running with reduced feature set.

NOTE: Using experimental fast data loading logic. To disable, pass
"--load_fast=false" and report issues on GitHub. More details:
https://github.com/tensorflow/tensorboard/issues/4784

Serving TensorBoard on localhost; to expose to the network, use a proxy or pass --bind_all
TensorBoard 2.11.2 at http://localhost:35245/ (Press CTRL+C to quit)

image-20250517102809079

后面发现训练的内存还会被占用,用htops杀掉

1
2
3
4
htop
空格选择程序
F9杀掉程序
enter确认

做完一定要测试一下效果

1
2
# 输出在YOLOX_outputs中的yolox_s里面,是按照时间确定的视频,发现训练的依托
python tools/demo.py video -f exps/example/custom/yolox_s.py -c YOLOX_outputs/yolox_s_pose1/yolos_ckpt_num80epoth12.pth --conf 0.5 --nms 0.4 --tsize 640 --save_result --device gpu --path 09040032_Miqus_5_28519.avi

主播的疑问,每次训练到某个epoth就不动了,比如训练yolox-s到epoth12就代码不动了