从零到一:基于PySKL与STGCN++构建自定义动作识别模型
1. 动作识别模型开发入门指南第一次接触动作识别领域时我被各种专业术语和复杂流程搞得晕头转向。经过几个项目的实战我发现用PySKL框架结合STGCN模型是最适合新手的入门方案。这个组合就像乐高积木一样既保留了科研级的性能又提供了足够友好的开发接口。动作识别本质上是通过分析视频中的人体运动模式来分类行为类型。想象一下教小朋友认识动物不是通过静态图片而是观察动物的行走、奔跑等动态特征。STGCN就是这样一个善于捕捉时空特征的智能观察者它能同时分析关节点在空间上的排列和时间上的变化。选择PySKL框架有三个实际理由首先它集成了MMDetection和MMPose等成熟工具链省去了环境配置的麻烦其次提供了STGCN等前沿模型的预训练配置最重要的是其模块化设计让开发者能快速替换数据输入、模型组件等部分。我在首次尝试时用Weizmann数据集包含10类简单动作仅用半天就完成了从数据准备到模型训练的完整流程。2. 数据准备与预处理实战2.1 数据集组织规范数据就像模型的粮食质量直接影响最终效果。以Weizmann数据集为例我建议采用这样的目录结构Weizmann/ ├── train/ │ ├── daria_0.avi │ └── lyova_3.avi └── test/ ├── denis_1.avi └── eli_4.avi关键点在于视频命名要包含类别信息比如lyova_3.avi中的3表示动作类别ID。这种命名方式后续处理时会非常方便。我遇到过因命名不规范导致标签错乱的坑后来写了这个自动检查脚本import os def validate_naming(dataset_path): for split in [train, test]: videos os.listdir(f{dataset_path}/{split}) for vid in videos: if _ not in vid or not vid.split(_)[-1].split(.)[0].isdigit(): print(fInvalid naming: {vid})2.2 标注文件生成技巧PySKL需要两种标注文件JSON格式的元数据文件和列表文件。通过以下代码可以自动生成import json import os def generate_annotations(video_dir, output_json): annotations [] for vid in os.listdir(video_dir): frames len(decord.VideoReader(f{video_dir}/{vid})) annotations.append({ vid_name: vid.split(.)[0], label: int(vid.split(_)[-1].split(.)[0]), start_frame: 0, end_frame: frames }) with open(output_json, w) as f: json.dump(annotations, f)列表文件更简单每行包含视频路径和标签即可。建议用Python的f-string来生成lines [f{os.path.join(video_dir, vid)} {vid.split(_)[-1].split(.)[0]} for vid in os.listdir(video_dir)]3. 骨架提取关键步骤3.1 检测模型选型经验骨架提取是动作识别的核心环节这里需要两个模型人体检测器和关节点检测器。经过多次测试我推荐这样的配置组合组件类型推荐模型性能指标显存占用检测模型Faster RCNN (Res50-FPN)mAP 38.4约3GB姿态模型HRNet-w32PCKh 0.87约2GB在实际项目中遇到过检测框丢失的问题通过调整这两个参数显著改善效果parser.add_argument(--det-score-thr, typefloat, default0.7) # 置信度阈值 parser.add_argument(--det-area-thr, typefloat, default1300) # 最小检测区域3.2 骨架数据处理技巧运行custom_2d_skeleton.py时可能会卡在模型初始化步骤。这是因为默认会尝试分布式训练单卡环境下需要修改这部分代码# 原始问题代码 # init_dist(pytorch, backendnccl) # 修改后方案 rank 0 world_size 1生成的pkl文件包含每个视频的骨架序列数据结构是这样的多维数组keypoints.shape (人数, 帧数, 17个关节点, 3) # 最后维度是(x,y,score)建议用这个代码片段验证数据质量import mmcv data mmcv.load(train.pkl) print(fTotal videos: {len(data)}) print(fKeypoints shape: {data[0][keypoint].shape})4. STGCN模型训练详解4.1 配置文件调整要点STGCN的配置文件需要针对自定义数据集调整主要修改这几个关键部分model dict( cls_headdict(num_classes10)) # 改为实际类别数 data dict( traindict( datasetdict( ann_filepath/to/your.pkl, # 指向生成的pkl文件 splitxsub_train))) # 需与pkl中的split键一致训练策略对结果影响很大推荐以下参数组合optimizer dict(typeSGD, lr0.1, momentum0.9) # 学习率很关键 lr_config dict(policyCosineAnnealing, min_lr0) total_epochs 100 # Weizmann这样的小数据集需要更多epoch4.2 分布式训练实操启动训练时使用dist_train.sh脚本注意第二个参数是GPU数量# 单卡训练 bash tools/dist_train.sh configs/stgcn/your_config.py 1 # 多卡示例如4卡 bash tools/dist_train.sh configs/stgcn/your_config.py 4训练过程中可以通过work_dir查看日志重点关注这两个指标top1_acc - 最高置信度预测的准确率 top5_acc - 前五预测包含正确答案的概率遇到loss震荡时可以尝试降低学习率或增加batch size。我在Weizmann数据集上最终达到90%的top1准确率关键就是调整了学习率衰减策略。5. 模型测试与部署5.1 性能评估方法测试阶段不仅要看准确率还要分析混淆矩阵。使用这个命令生成详细测试结果bash tools/dist_test.sh your_config.py your_checkpoint.pth 1 \ --out results.json --eval top_k_accuracy mean_class_accuracy对于实时应用需要关注推理速度。STGCN在GTX 1080Ti上的表现输入长度推理时间显存占用100帧45ms1.2GB200帧78ms2.1GB5.2 可视化演示技巧PySKL提供的demo_skeleton.py脚本可以直接生成带预测结果的可视化视频python demo/demo_skeleton.py input.mp4 output.mp4 \ --config your_config.py \ --checkpoint best_model.pth \ --label-map tools/data/label_map/your_labels.txt标签文件格式很简单每行一个类别名称按类别ID排序bend jack jump ...在处理长视频时建议采用滑动窗口策略。这是我使用的分段处理代码片段clip_len 100 # 与训练时保持一致 overlap 30 # 重叠帧数避免漏检 for i in range(0, total_frames, clip_len - overlap): clip video[i:iclip_len] # 送入模型处理