ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

SlowFast行为识别实战:从零环境配置到源码解析与调试

SlowFast行为识别实战:从零环境配置到源码解析与调试 上周帮一个研究生朋友调试行为识别项目他拿着导师给的代码和论文卡在环境配置这一步整整三天。不是 CUDA 版本不对就是某个依赖包冲突要么就是数据集路径死活读不对。最后我们花了一个下午从零开始绕开所有“教程”里没提的坑才把 SlowFast 模型跑起来。这让我意识到很多所谓的“完整教程”其实只讲了“理想路径”而真正决定项目能否跑通的往往是那些环境、路径、版本和配置的细节。SlowFast 作为 Facebook AI Research (FAIR) 开源的双路径行为识别框架在 Kinetics、AVA 等数据集上表现优异是很多学术研究和毕业设计的首选。但它的官方仓库更像是一个“研究实现”的展示而非一个“开箱即用”的工具包。直接git clone然后python tools/run_net.py大概率会遭遇一连串的报错。这篇文章我就从一个工程落地的角度带你走一遍从零搭建环境、理解项目结构、调试运行到初步看懂源码的全过程。目标不是复现论文而是让你能把这份代码实实在在地跑起来并理解它为什么这样设计从而能将其用于你自己的实验或毕设。1. 环境搭建避开“理想教程”里的所有坑环境搭建是第一步也是最容易劝退的一步。网上很多教程会直接说“安装 PyTorch、Detectron2 等依赖”但魔鬼全在细节里。1.1 核心依赖的版本锁定别用最新版SlowFast 对版本极其敏感。PyTorch、CUDA、Detectron2 之间必须保持严格的兼容性。根据官方仓库的requirements.txt和常见实践我强烈建议锁定以下版本组合这是经过大量验证的稳定搭配Python: 3.8 或 3.9。不推荐 3.10部分依赖可能尚未完全适配。PyTorch: 1.9.0 或 1.9.1。这是与后续 Detectron2 版本兼容性最好的。CUDA: 10.2 或 11.1。请务必与你的显卡驱动匹配。使用nvidia-smi查看驱动支持的 CUDA 最高版本。Detectron2: 0.6。这是关键Detectron2 的 API 变化较快必须安装与 PyTorch/CUDA 版本对应的预编译版本。安装命令不能简单地pip install torch。正确的姿势是去 PyTorch 历史版本官网 找到对应命令。例如对于 CUDA 10.2# 安装 PyTorch 1.9.0 CUDA 10.2 pip install torch1.9.0cu102 torchvision0.10.0cu102 torchaudio0.9.0 -f https://download.pytorch.org/whl/torch_stable.html # 安装对应版本的 Detectron2 python -m pip install detectron2 -f https://dl.fbaipublicfiles.com/detectron2/wheels/cu102/torch1.9/index.html如果你用的是 CUDA 11.1则需要找到对应的 PyTorch 1.9.0cu111 和 Detectron2 的 wheel 文件链接。注意不要使用conda install pytorch默认的版本它很可能不匹配。使用pip并指定完整的版本字符串是最可控的方式。1.2 项目克隆与依赖安装注意路径和权限SlowFast 的仓库包含了一些子模块和自定义的 C 扩展需要编译。# 1. 克隆主仓库 git clone https://github.com/facebookresearch/SlowFast.git cd SlowFast # 2. 递归克隆子模块主要是 Detectron2 的一些适配代码 git submodule update --init --recursive # 3. 安装 Python 依赖 pip install -r requirements.txt这里可能遇到的坑权限问题如果在 Linux 下遇到权限错误建议在用户目录下操作或使用--user参数安装 pip 包避免使用系统 Python。编译错误安装过程中可能会编译一些扩展如PyAV或slowfast自带的 C 操作。确保你的系统已安装gcc、g和make。在 Ubuntu 上可以运行sudo apt-get install build-essential。数据集工具requirements.txt里可能包含fvcore、simplejson等这些一般没问题。但如果遇到moviepy或opencv-python安装失败可以尝试先升级pip和setuptools。1.3 环境验证写一个最简单的测试脚本环境装好后不要急着跑训练。写一个几行代码的脚本验证核心库是否能正常导入以及 GPU 是否可用。# test_env.py import torch import detectron2 import slowfast print(fPyTorch version: {torch.__version__}) print(fCUDA available: {torch.cuda.is_available()}) print(fCUDA version: {torch.version.cuda}) print(fDetectron2 version: {detectron2.__version__}) # 尝试导入 SlowFast 的一个核心模块 from slowfast.models import build_model print(Environment check passed!)运行python test_env.py。如果一切正常你会看到版本信息和 “Environment check passed!”。如果出现ImportError根据报错信息回头检查对应的包是否安装成功。2. 理解项目结构从“一团乱麻”到“心中有图”SlowFast 的代码库继承了 Detectron2 的风格对于新手来说目录结构可能有些复杂。我们不必一开始就深入每个文件但必须搞清楚几个核心目录的作用这样才能知道数据该放哪配置该改哪结果去哪找。SlowFast/ ├── configs/ # 所有模型的配置文件核心 │ ├── Kinetics/ # Kinetics 数据集配置 │ ├── AVA/ # AVA 数据集配置 │ └── ... # 其他数据集配置 ├── datasets/ # 数据集准备和加载相关代码 │ ├── dataset.py # 数据集基类 │ └── kinetics.py # Kinetics 数据集具体实现 ├── demo/ # 演示脚本 ├── slowfast/ # 核心源码目录 │ ├── config/ # 配置加载和默认配置 │ ├── datasets/ # 数据预处理和增强 │ ├── models/ # 模型定义SlowFast 网络、ResNet 等 │ ├── optimizer/ # 优化器 │ └── utils/ # 日志、检查点、分布式等工具 ├── tools/ # 训练、测试、可视化等工具脚本 │ ├── train_net.py # 训练入口 │ └── run_net.py # 通用运行入口更常用 ├── requirements.txt └── README.md对于使用者来说你最需要关注的是三个地方configs/这里是所有实验的“总控室”。每个 YAML 文件定义了一个完整的实验包括模型结构、数据集、训练参数、优化器等。你几乎所有的自定义都是从复制并修改一个这里的配置文件开始的。tools/run_net.py这是最常用的入口脚本。它负责加载配置、构建模型、数据加载器然后执行训练或测试。datasets/和slowfast/datasets/这里定义了数据如何被读取、解码和增强。如果你要使用自己的数据集主要需要修改或参考这里的代码。这种结构的好处是配置驱动换模型、换数据集、改超参通常只需改配置文件而不用动代码。但坏处是对初学者来说配置文件里层层嵌套的参数让人眼花缭乱。3. 运行第一个例子用预训练模型进行推理在尝试训练之前强烈建议先用预训练模型跑通推理流程。这能验证你的环境、代码路径、数据加载环节是否全部正常。3.1 下载预训练模型SlowFast 官方提供了在 Kinetics-400 上预训练的模型。我们需要下载它。 通常模型会放在 Facebook AI Research 的公共存储桶。你可以从官方 README 找到下载链接或者直接使用如下路径链接可能变化请以官方仓库为准# 假设我们在 SlowFast 项目根目录 mkdir -p checkpoints cd checkpoints # 下载 SlowFast 模型例如8x8 配置ResNet50 骨干 wget https://dl.fbaipublicfiles.com/pyslowfast/model_zoo/kinetics400/SLOWFAST_8x8_R50.pkl3.2 准备一段示例视频你需要准备一个短视频文件如example.mp4用于测试。将其放在项目根目录或一个专门的demo_videos文件夹里。视频内容最好包含清晰的人类动作比如“走路”、“挥手”、“打球”。3.3 运行推理脚本SlowFast 仓库通常提供一个demo.py或类似的脚本。如果没有我们可以用tools/run_net.py配合一个只做推理的配置。更简单的方法是直接使用tools/run_net.py并指定NUM_GPUS 0仅用CPU或NUM_GPUS 1以及TRAIN.ENABLE False和TEST.ENABLE True。但这里涉及到配置文件的修改。一个更直接的实践是参考demo文件夹如果有里的代码自己写一个简单的推理脚本。核心步骤包括加载配置文件。根据配置构建模型。加载预训练权重。准备视频数据并预处理成模型输入的格式裁剪、缩放、帧采样等。运行模型前向传播。将输出分数映射到 Kinetics-400 的类别标签上得到预测结果。由于篇幅限制这里不贴出完整脚本但流程是清晰的。这个步骤的关键目的不是得到多准的结果而是验证从“视频文件”到“模型预测”的整个链路是通的。你会遇到视频解码、帧提取、数据归一化等问题解决它们的过程就是理解数据流的过程。4. 看懂核心源码双路径网络到底在做什么跑通流程后我们深入一点看看 SlowFast 的核心思想。论文讲得很清楚但代码是如何实现的呢4.1 模型构建入口模型构建的入口在slowfast/models/build.py的build_model函数。它根据配置文件中的MODEL.ARCH例如slowfast来选择合适的模型类。在slowfast/models/目录下你会发现video_model_builder.py这里定义了ResNet和SlowFast等模型类。我们重点关注SlowFast类。4.2 SlowFast 类解析SlowFast类通常继承自torch.nn.Module。它的__init__方法会创建两条路径Slow 路径高空间分辨率用来捕捉外观、纹理等静态信息低时间分辨率帧采样稀疏。Fast 路径低空间分辨率牺牲细节高时间分辨率帧采样密集用来捕捉快速运动。在forward方法中输入的视频片段一个 5D Tensor:[batch, channel, time, height, width]会被拆分成两份分别经过不同的预处理如不同的帧采样率后送入两个独立的骨干网络通常是两个 ResNet。4.3 关键操作横向连接 (Lateral Connection)这是 SlowFast 的灵魂。代码中如何实现“将 Fast 路径的特征融合到 Slow 路径” 在slowfast/models/slowfast.py中你会看到类似lateral_connection的模块。它通常是一个卷积层如 1x1x1 卷积加上一个上采样操作如时间维度的插值负责将 Fast 路径的某个中间层特征变换后与 Slow 路径的对应层特征相加。# 伪代码示意 class LateralConnection(nn.Module): def __init__(self, in_channels, out_channels): self.conv nn.Conv3d(in_channels, out_channels, kernel_size1) self.upsample nn.Upsample(scale_factor(时间缩放因子, 1, 1), modenearest) def forward(self, fast_feat): out self.conv(fast_feat) out self.upsample(out) # 使时间维度与 slow 路径对齐 return out # 在 SlowFast.forward 中 slow_feat self.slow_path(slow_input) fast_feat self.fast_path(fast_input) # 在某个阶段将处理后的 fast_feat 加到 slow_feat 上 slow_feat slow_feat self.lateral_conn(fast_feat)通过阅读这部分代码你就能直观地理解“双路径”和“信息融合”是如何在张量操作层面实现的。4.4 数据流从视频到标签另一个重点是数据流。视频是如何被加载、解码、采样最终变成模型输入的 这主要在slowfast/datasets/下的代码中。你会看到VideoDataset类它使用decoder如 PyAV, torchvision, cv2来解码视频然后使用sampler如UniformClipSampler来从长视频中按照配置的帧率和片段长度采样出多个剪辑 (clips)。预处理裁剪、缩放、翻转和格式化从 HWC 到 CHW归一化也在这里完成。理解这部分对你后续处理自己的视频数据至关重要。5. 为自己的任务定制从“跑通”到“能用”对于毕设或研究你通常需要在 SlowFast 基础上做改动。无非是以下几个方向5.1 使用自己的数据集这是最常见的需求。你需要准备数据将你的视频文件整理成固定的目录结构并生成一个标注文件如 CSV 或 JSON。标注文件至少需要包含视频路径和标签。编写数据集类在slowfast/datasets/下参考kinetics.py创建一个新的文件如mydataset.py。你需要继承BaseDataset并实现__len__、__getitem__以及load_video等关键方法。核心是__getitem__它需要返回一个字典包含“frames”视频帧 Tensor和“label”类别索引等信息。注册数据集在slowfast/datasets/__init__.py中使用dataset_catalog.register()函数注册你的数据集给它一个名字如“my_dataset_train”。修改配置文件复制一份 Kinetics 的配置文件将DATA.PATH_TO_DATA_DIR指向你的数据根目录将DATA.PATH_PREFIX指向视频文件前缀如果有并将DATA.TRAIN/DETECT_FILES改为你的标注文件名。最重要的是将DATA.TRAIN/DETECT_DATASET和DATA.TEST.DATASET改为你刚才注册的数据集名字。修改类别数在配置文件中将MODEL.NUM_CLASSES改为你的数据集的类别数。如果是从预训练模型微调可能需要处理分类头权重加载的问题通常可以设置MODEL.FINETUNE相关参数或手动处理权重加载。5.2 修改模型结构如果你想尝试不同的融合方式、更换骨干网络等定位修改点模型代码主要在slowfast/models/。确定你想改的是骨干网络 (backbone)、颈部网络 (neck)、头部 (head) 还是融合层 (lateral_connection)。小范围修改建议先在一个新的模型类中继承原有的SlowFast然后重写你想改的部分。例如创建一个MySlowFast类在__init__中修改 lateral connection 的结构。注册新模型在slowfast/models/build.py中将你的MySlowFast类添加到_VIDEO_MODELS字典里。更新配置在配置文件中将MODEL.ARCH改为你注册的新模型名字。5.3 调整训练策略学习率、优化器、调度器、数据增强等都在配置文件中调整。SOLVER部分控制优化器SOLVER.OPTIMIZING_METHOD、基础学习率SOLVER.BASE_LR、学习率调度器SOLVER.LR_POLICY等。DATA部分控制数据增强如随机裁剪大小DATA.TRAIN_CROP_SIZE、水平翻转概率DATA.TRAIN_RANDOM_FLIP_PROB等。TRAIN和TEST部分控制训练和测试的批次大小、周期数等。一个非常重要的建议任何修改尤其是模型结构和训练超参务必先在小数据集或原数据集的一个小子集上快速跑通几个迭代确保没有语法错误、维度不匹配、梯度爆炸等问题再放到全量数据上长时间训练。6. 调试与排错当代码跑不起来时即使按照教程你也一定会遇到问题。以下是常见的排查顺序报错信息仔细阅读 Python 的 Traceback。错误发生在哪一行是什么错误ImportError,KeyError,RuntimeError,CUDA out of memory数据加载如果错误发生在训练开始不久很可能是数据加载问题。检查数据集路径是否正确配置文件中的路径是绝对路径还是相对路径标注文件的格式是否正确标签索引是否从0开始且不超过NUM_CLASSES-1视频文件能否被解码器如 PyAV正常读取尝试用代码单独读一个视频看看。模型构建如果错误发生在模型构建时检查配置文件中的MODEL.ARCH是否拼写正确MODEL.NUM_CLASSES是否与数据集匹配如果修改了模型维度计算是否正确可以用一个小的随机输入torch.randn测试一下前向传播。GPU 内存CUDA out of memory是最常见的错误之一。解决方法减小TRAIN/EVAL_BATCH_SIZE。减小DATA.TRAIN_CROP_SIZE输入图像尺寸。使用梯度累积如果代码支持。使用更小的模型如将SLOWFAST_8x8_R50换成SLOWFAST_4x16_R50。依赖版本如果遇到奇怪的AttributeError或TypeError回想一下是否严格遵循了第1部分的版本要求。Detectron2 的 API 不兼容是常见祸首。日志和可视化SlowFast 通常使用 TensorBoard 或 WandB 记录日志。即使程序能跑也要关注训练损失是否正常下降验证精度是否在提升。如果损失为 NaN可能是学习率太大、数据有异常值或模型初始化问题。从环境搭建到源码理解再到自定义修改这个过程本质上是在学习一个中型研究代码库的标准打开方式。SlowFast 不仅仅是一个行为识别模型它更是一个如何组织深度学习实验代码的范本。理解它的配置系统、模型注册机制、数据流水线比你单纯调出一个高几个点的准确率更有长期价值。当你下次面对另一个开源项目时这套“先理清结构再跑通Demo最后深入核心模块”的方法会同样有效。
返回列表