1. 为什么要在云端跑ST-GCN:本地环境的三个硬伤
做过骨架动作识别的人多半都听过ST-GCN这个名字。它把图卷积和时间卷积拼在一起,专门处理人体骨架序列这种"节点+连接"结构的数据,在动作识别、行为分析这类任务里算是绕不开的经典方案。但真正动手的人会发现,卡住大多数人的不是模型本身,而是环境。
我前后在本地机器上折腾过好几轮ST-GCN的环境,踩的坑基本集中在三块。第一块是依赖版本打架。ST-GCN的官方实现基于比较早期的PyTorch,而它依赖的图卷积库又对PyTorch版本、CUDA版本、Python版本都有隐性要求,三者只要有一个对不上,import阶段就直接报错。第二块是显卡资源。骨架数据的训练虽然比图像轻,但ST-GCN在NTU这类数据集上跑起来,显存和算力需求并不低,本地一张消费级卡跑完整训练经常要熬通宵。第三块是环境不可复现。本地装好了,换台机器或者过两个月重装系统,同样的步骤未必能跑通,因为中间某个包悄悄更新了。
云端方案正好把这三点都绕开了。用云端笔记本环境跑ST-GCN,最大的好处是环境隔离——每次开一个新实例就是一张白纸,装坏了直接扔掉重开,不会污染本地。其次是算力弹性,需要跑大实验的时候切到带GPU的运行时,平时调试用CPU就够。再就是可复现,把安装步骤写成代码块,下次照着跑一遍就行,不依赖本地任何残留状态。
这篇内容适合两类人:一类是刚接触骨架动作识别、想快速把ST-GCN跑起来看效果的新手;另一类是在本地被环境折磨过、想找个干净环境做实验的老手。我会把整个配置过程拆开讲,重点不是"照着敲命令",而是每一步为什么这么做、哪里最容易翻车、翻车了怎么救。全程用云端笔记本环境演示,不需要你本地有任何GPU。
提示:下面所有操作都在云端笔记本的代码单元格里完成,建议按顺序执行,不要跳步。每一步执行完留意输出,报错信息往往比你想的更有用。
2. 开工前的环境盘点:先搞清楚你手里有什么
2.1 确认运行时类型和Python版本
云端笔记本默认给的运行时不一定带GPU。第一步永远是先确认自己拿到的是什么环境,否则后面装了一堆GPU版本的包,结果发现根本没显卡,白忙活。
在第一个单元格里跑这几行:
import sys import torch print("Python版本:", sys.version) print("PyTorch版本:", torch.__version__) print("CUDA是否可用:", torch.cuda.is_available()) if torch.cuda.is_available(): print("显卡型号:", torch.cuda.get_device_name(0))这里有个经验点:云端笔记本预装的PyTorch版本会随时间变化。可能这个月预装的是2.x,下个月就变了。所以不要假设预装版本一定适合ST-GCN,先看清楚再决定是沿用还是重装。
如果torch.cuda.is_available()返回False,说明当前运行时没挂GPU。这时候要去运行时设置里把硬件加速器切成GPU。切完之后必须重新连接运行时,否则环境不会刷新。这一步很多人会忘,切完直接跑代码,结果还是CPU,然后纳闷为什么这么慢。
2.2 判断是否需要重装PyTorch
ST-GCN的官方代码对PyTorch版本比较敏感。我实测下来,PyTorch 1.10到1.13这个区间兼容性最好,太新的版本(比如2.1以上)在部分图卷积算子上会有API变动,太老的(1.4以下)又缺一些必要的函数。
判断逻辑是这样的:如果预装版本落在1.10到1.13之间,可以直接用;如果超出这个范围,建议重装一个指定版本。重装的时候要注意,PyTorch版本、torchvision版本、CUDA版本三者要配套,不能随便组合。
下面这张表是我整理出来的几组经过验证的配套关系,供参考:
| PyTorch版本 | torchvision版本 | 适配CUDA | 备注 |
|---|---|---|---|
| 1.10.0 | 0.11.0 | 11.3 | 稳定,推荐 |
| 1.11.0 | 0.12.0 | 11.3 | 稳定 |
| 1.12.1 | 0.13.1 | 11.3 | 稳定 |
| 1.13.1 | 0.14.1 | 11.6 | 较新,可用 |
| 2.0.1 | 0.15.1 | 11.7 | 部分算子需微调 |
重装的命令大致长这样(以1.12.1为例):
pip install torch==1.12.1+cu113 torchvision==0.13.1+cu113 -f https://download.pytorch.org/whl/torch_stable.html注意:重装PyTorch之后一定要重启运行时,否则内存里还是旧的库,import的时候会混乱。重启完再跑一遍2.1的检查代码确认版本对了。
2.3 云端环境的存储特性要心里有数
云端笔记本的存储分两块:一块是临时的运行目录,一块是可以挂载的持久化存储。临时目录里的东西,运行时一断开就没了。这意味着你clone下来的代码、下载的数据集、训练出来的权重,如果不放到持久化目录,下次连接就全丢了。
我的习惯是:代码和数据都放在持久化挂载的目录下,比如/content/drive/MyDrive/这类路径。这样即使运行时断了好几次,重新连上之后代码和数据还在,只需要重新装一遍依赖就行。依赖装起来快,数据重新下载才是真的费时间。
另外提醒一句,云端笔记本的磁盘空间有限,NTU RGB+D这种数据集动辄几十GB,下载前先确认空间够不够。用!df -h看一眼剩余空间,别下到一半爆盘。
3. 依赖安装的完整链路与版本锁定技巧
3.1 从代码仓库到依赖清单
ST-GCN的代码结构不算复杂,核心就是模型定义、数据处理、训练脚本三块。但它的依赖清单里藏着几个"版本刺客",不处理干净后面必炸。
先把代码拉下来:
git clone https://github.com/your-repo/st-gcn.git cd st-gcn拉下来之后别急着装依赖,先看一眼requirements.txt或者setup.py里列了什么。ST-GCN常见的依赖包括:numpy、scipy、pandas、matplotlib、scikit-learn、pyyaml、tqdm,以及最关键的图卷积相关库。
这里有个大坑:图卷积库的版本和PyTorch版本强绑定。早期ST-GCN用的是某个特定的图卷积实现,它对PyTorch的C++扩展接口有要求。如果PyTorch版本不对,编译阶段就会失败,报一堆看不懂的C++错误。
3.2 逐个击破:依赖安装的正确顺序
安装顺序很重要,我总结的顺序是:先基础科学计算库,再图卷积库,最后其他辅助库。原因是图卷积库在安装时会检查numpy等基础库的版本,如果基础库没装好,它会装一个自己认为合适的版本,可能和你需要的冲突。
第一步,装基础库并锁定版本:
pip install numpy==1.23.5 scipy==1.9.3 pandas==1.5.3 pip install matplotlib==3.6.3 scikit-learn==1.2.2为什么锁这些版本?因为numpy 1.24以上移除了一些旧API,而部分老代码还在用;scipy 1.10以上也有类似问题。锁在1.23和1.9这个区间,兼容性最稳。
第二步,装图卷积库。这一步是整个安装过程中最容易出问题的。如果用的是需要编译的版本,要确保运行时有编译工具链。云端笔记本一般自带gcc,但有时候缺python3-dev之类的头文件。可以先跑:
apt-get install -y build-essential python3-dev然后再装图卷积库。如果编译过程中报错,重点看错误信息里提到的PyTorch头文件路径和C++标准版本。常见的一个问题是代码用了C++14的特性但编译器默认按C++11处理,这时候需要在编译参数里加-std=c++14。
第三步,装辅助库:
pip install pyyaml tqdm tensorboard3.3 用pip freeze固化环境
所有依赖装完之后,立刻做一件事:把当前环境导出成清单。
pip freeze > requirements_locked.txt这个文件是你的"环境快照"。下次重开运行时,直接pip install -r requirements_locked.txt就能一键还原,不用再一步步回忆装了什么版本。我吃过亏,有一次装完没导出,过了一周重开环境,怎么装都装不回原来的状态,最后只能从头排查,浪费了大半天。
提示:导出的清单里会包含一些云端环境自带的包,还原的时候可能会和预装环境冲突。更稳妥的做法是只导出你手动装的那几个关键包,或者用虚拟环境隔离。不过云端笔记本用虚拟环境稍微麻烦一点,新手可以先直接用全局环境,把清单存好就行。
4. 数据准备与路径配置:让代码找得到数据
4.1 骨架数据的两种常见格式
ST-GCN吃的是骨架序列数据,常见的有两种格式:一种是原始坐标格式,每个帧记录所有关节点的二维或三维坐标;另一种是预处理后的张量格式,把坐标整理成模型直接能读的数组。
原始坐标格式通常来自姿态估计算法的输出,比如用某种人体姿态检测器从视频里逐帧提取关节点。这种格式的好处是通用,坏处是需要自己写预处理脚本转成模型输入。预处理后的格式一般是.npy或.pkl文件,直接就是模型要的形状,省事但依赖特定的预处理流程。
我建议新手先用预处理好的小样本数据跑通流程,确认模型能训练、能推理之后,再回头处理自己的原始数据。这样能把"环境问题"和"数据问题"分开排查,不至于两头都乱。
4.2 目录结构要提前规划
ST-GCN的代码通常对目录结构有约定,比如数据放在data/下,配置放在config/下,权重存在work_dir/下。如果你不按它的约定放,就得改代码里的路径,改多了容易漏。
我的做法是:先按代码默认的目录结构建好文件夹,再把数据放进去。具体来说:
mkdir -p data/processed mkdir -p config mkdir -p work_dir mkdir -p resource然后把预处理好的数据放到data/processed/下,配置文件放到config/下。这样跑训练脚本的时候基本不用改路径。
如果数据放在持久化目录里,可以用软链接把它链到工作目录,避免复制大文件浪费时间:
ln -s /content/drive/MyDrive/stgcn_data/processed data/processed软链接的好处是数据只存一份,工作目录里看起来就像本地文件一样。但要注意,软链接在运行时重启后可能失效,因为临时目录被清空了。所以每次重开运行时,如果发现路径找不到,先检查软链接还在不在,不在就重建一下。
4.3 配置文件里的路径要改成绝对路径
ST-GCN的配置文件里通常写的是相对路径。在本地跑没问题,但在云端环境里,工作目录可能和你以为的不一样,相对路径就容易指错地方。
稳妥的做法是把配置文件里的关键路径改成绝对路径。比如把data/processed改成/content/st-gcn/data/processed。改的时候注意,配置文件里可能有多处路径,包括数据路径、权重保存路径、日志路径,都要检查一遍。
改完路径之后,先跑一个最小验证:用一小批数据跑一个epoch,看能不能正常读取、正常前向传播、正常反向传播。这一步过了,说明环境和数据都通了,再上完整训练。
5. 跑通第一个训练:从报错到出结果
5.1 最小可运行命令的构造
第一次跑训练,不要直接上完整配置。我的习惯是构造一个"最小可运行命令":最小的数据量、最小的batch size、最少的epoch,目标是快速验证流程通不通,而不是追求效果。
比如原本配置是batch size 64、跑80个epoch,第一次跑就改成batch size 4、跑1个epoch。命令大概长这样:
python main.py --config config/default.yaml --batch-size 4 --epochs 1 --debug如果代码里没有--debug这种参数,就手动改配置文件里的对应字段。关键是让整个流程能在几分钟内跑完,这样报错了也能快速迭代。
5.2 常见报错与对应处理
第一次跑大概率会报错,这很正常。我把常见的几类报错和处理方式列一下:
| 报错关键词 | 可能原因 | 处理方式 |
|---|---|---|
ModuleNotFoundError | 某个依赖没装 | 按报错里的模块名补装 |
CUDA out of memory | 显存不够 | 减小batch size,或清理缓存 |
size mismatch | 数据形状和模型输入不匹配 | 检查数据预处理和配置里的关节数 |
KeyError | 配置文件缺字段 | 对照默认配置补全 |
RuntimeError: expected scalar type | 数据类型不一致 | 检查输入张量的dtype |
其中size mismatch是最常见的。ST-GCN的输入形状通常是(N, C, T, V, M),分别代表batch大小、通道数、帧数、关节数、人数。如果你的数据关节数是25(NTU标准),但配置里写的是18,就会报这个错。解决方法是对齐配置里的关节数和实际数据的关节数。
CUDA out of memory也很常见。云端笔记本给的GPU显存有限,batch size开大了就爆。处理方式是先把batch size降到能跑的最小值,跑通之后再逐步往上加,找到显存的上限。另外,PyTorch的缓存有时候不会自动释放,可以在代码里手动加torch.cuda.empty_cache()。
5.3 训练过程中的监控要点
跑起来之后,别干等着。要盯几个关键指标:
- loss是否在下降。如果loss一直不降或者变成nan,说明学习率太大或者数据有问题。
- 显存占用。用
nvidia-smi看一眼,如果接近上限,后面加batch size要谨慎。 - 每个epoch的耗时。这个数据帮你估算完整训练要多久,决定要不要调整策略。
云端笔记本有个好处是可以边跑边看输出。如果发现loss异常,可以随时中断,改完再跑,不用像本地那样等半天。
注意:云端笔记本的运行时如果长时间不操作可能会自动断开。跑长训练的时候,要么保持页面活跃,要么把训练脚本改成能断点续训的形式,把checkpoint定期存到持久化目录。不然跑到一半断了,前面的都白跑。
6. 几个让我印象深刻的坑和绕行方案
6.1 图卷积库编译失败的排查链路
有一次我在新开的运行时里装图卷积库,编译阶段报了一长串C++错误。当时第一反应是版本不对,换了几个版本还是报错。后来静下心看错误信息,发现关键的一句是fatal error: torch/extension.h: No such file or directory。
这说明编译器找不到PyTorch的头文件。原因是PyTorch装在了用户目录下,而编译器默认只查系统路径。解决办法是在编译前设置环境变量,把头文件路径加进去:
export CPLUS_INCLUDE_PATH=$(python -c "import torch; print(torch.utils.cpp_extension.include_paths()[0])"):$CPLUS_INCLUDE_PATH设完之后再编译就过了。这个坑的教训是:编译类错误一定要看第一行和最后一行,第一行告诉你缺什么,最后一行告诉你哪个文件出的问题,中间那一大堆往往是连锁反应。
6.2 运行时重启后环境"失忆"的应对
云端笔记本的运行时一旦断开重连,之前pip装的东西全没了,又回到初始状态。第一次遇到的时候我很崩溃,以为要重新装一遍。后来发现,只要把安装步骤写成一个脚本,重连之后跑一遍脚本就行,几分钟的事。
我的做法是维护一个setup.sh,里面按顺序写好所有安装命令,包括版本锁定、环境变量设置、软链接重建。重连之后第一件事就是跑这个脚本。脚本内容大致是:
#!/bin/bash pip install numpy==1.23.5 scipy==1.9.3 pandas==1.5.3 pip install torch==1.12.1+cu113 torchvision==0.13.1+cu113 -f https://download.pytorch.org/whl/torch_stable.html pip install pyyaml tqdm tensorboard # 重建软链接 ln -sf /content/drive/MyDrive/stgcn_data/processed data/processed echo "环境就绪"这样每次重连只需要跑一个命令,省心很多。脚本本身存在持久化目录里,不会丢。
6.3 数据加载慢导致的训练卡顿
ST-GCN训练时如果数据加载成了瓶颈,GPU会经常空转等数据。表现是GPU利用率忽高忽低,训练速度上不去。
原因通常是数据读取没有并行化,或者数据存在慢速存储上。解决办法有两个:一是把数据预加载到内存,如果数据量不大(比如几个GB),直接一次性读进内存,训练时从内存取,速度快很多;二是增加数据加载的worker数量,在DataLoader里把num_workers调大,让多个进程并行读数据。
云端笔记本的CPU核心数有限,num_workers不要设太大,一般设成CPU核心数的一半左右比较合适。设太大反而会因为进程切换开销导致变慢。
7. 把环境固化成可复用的模板
配置环境这件事,做一次是折腾,做两次是浪费,做成模板才是正解。我现在的做法是:把整个配置过程写成一个带注释的笔记本,从环境检查、依赖安装、数据准备到最小验证,每一步都有说明和预期输出。下次不管是我自己还是别人要用,直接打开这个笔记本从头跑一遍就行。
这个笔记本里我会特别标注几个地方:哪些步骤是必须按顺序的,哪些步骤的输出需要人工确认,哪些步骤在报错时应该怎么处理。这样即使是不太熟悉的人,照着跑也能把环境搭起来。
另外,把requirements_locked.txt和setup.sh一起放在持久化目录里,和笔记本配套。笔记本负责讲清楚"为什么",脚本负责"快速执行",两者配合,复现环境就是几分钟的事。
最后分享一个小心得:每次环境配置成功后,立刻做一次完整的"从零复现"测试。就是把运行时断开,重新连上,然后完全按照你写的步骤再走一遍,看能不能顺利跑通。这一步能帮你发现步骤里遗漏的细节,比如某个环境变量忘了设、某个软链接忘了建。我靠这个习惯揪出过好几个隐藏问题,省下了后面无数次排查的时间。