学生课堂专注度分析系统,光听名字就知道这活儿不轻松:你得把摄像头拍到的课堂画面,实时变成每个学生的专注状态。人脸朝向、眼睛睁开闭上、身体姿态、头部角度,这些信息要从一帧一帧的画面里提出来,再交给时序模型去判断“这人是在记笔记还是在发呆”。我接到这个项目的第一件事,不是写模型结构,而是把环境搭明白——因为后面所有的训练、推理、调试全部压在环境上。这篇就完整记录我用YOLOv8+PyTorch做专注度分析时,在Windows下通过WSL2搭建整套开发环境的过程,包括每个命令、每个版本的选型理由,以及我踩过的坑。给正在做类似视觉分析项目、卡在环境搭建这一步的同学一个可以照抄的作业。
1. 先想清楚技术路线:专注度分析为什么选了YOLOv8+PyTorch这套组合
环境搭建不是上来就敲命令,你得先知道自己在给什么项目搭环境。学生课堂专注度分析系统的完整链路是这样的:摄像头采集高清画面,经过目标检测模型把人脸和上半身定位出来,再用姿态估计或人脸关键点模型提取细粒度特征(眼睛开合度、头部欧拉角、手部动作频率),最后把这些特征序列喂给一个时序分类器,输出“专注/走神/瞌睡/举手”之类的状态标签。
这条链路里,检测和后处理部分是算力消耗的大头,也是环境搭建首先要服务的对象。
1.1 YOLOv8在课堂场景下到底好在哪
选YOLOv8不是跟风。课堂场景有几个硬指标:人多、遮挡多、姿态变化大、需要实时性。学生坐在课桌前互相遮挡非常严重,后排学生人脸只有很小一块区域,这对小目标检测能力要求很高。YOLOv8相比之前v5/v7系列,在COCO数据集上的小目标AP值提升明显,C2f模块替换了C3模块之后,模型对细粒度特征的提取能力更强,检测头也换成了解耦头(Decoupled Head),分类和回归分支互不干扰。实测下来,在同样分辨率下YOLOv8s比YOLOv5s的mAP50-95高出大概3到5个点,课堂密集场景下差距会更明显。
另一个很实际的原因是模型文件统一。后来我们要同时训检测模型和姿态模型,YOLOv8官方仓库直接内置了pose模型分支,一套环境装完,检测和姿态两个任务都能跑,不需要再单独装OpenPose那套又老又重的依赖。这对环境搭建来说省了大事。
1.2 PyTorch生态才是真正决定成败的环节
检测模型其实用什么框架都行,但整个系统要串联的东西太多了:人脸关键点要用到OpenCV和dlib或者mediapipe,时序分类要上LSTM或者Transformer,数据预处理要接albumentations,可视化要接matplotlib——PyTorch在这些库的兼容性上做得最平滑。TensorFlow也可以跑,但版本升级带来的API断裂问题在长周期项目里面非常要命,我前一个项目就吃过TF2.0到2.4大版本接口不兼容的亏。
而且PyTorch的生态有一块比较隐蔽的优势:和ONNX、TensorRT的转换工具链配合成熟。后期我们要把模型部署到边缘盒子或者用TensorRT做推理加速,PyTorch导出的模型在兼容性上踩坑最少。这一点在做环境选型时很少有人提,但在实际项目周期里非常重要。
1.3 Windows开发、Linux训练:WSL2是唯一的解
做深度学习开发,绕不开一个现实问题:Windows上用PyTorch做GPU训练,性能损耗很大,而且很多底层编译工具链(比如编译自定义CUDA算子)在纯Windows环境下就是灾难。但直接装双系统,切换麻烦,虚拟机性能又扛不住GPU训练。WSL2(Windows Subsystem for Linux version 2)是折中方案里最接近完美的那个——它的架构是用轻量级虚拟机跑一个真正的Linux内核,和系统调用完全兼容,不像WSL1那样靠翻译层,CUDA可以直接透传调用Windows侧的显卡驱动,GPU训练性能损失控制在个位数百分比。
从我搜的资料来看,"pytorch环境搭建wsl"这个搜索量一直居高不下,说明现在有大量的人在做同样的事。这篇文章我全程在WSL2里的Ubuntu 20.04上操作,这套流程在Ubuntu 22.04上同样适用,只是apt源版本略有差异。
2. WSL2的搭建:把Ubuntu 20.04安装并配置到能扛得住深度学习的程度
很多教程一上来就让你装CUDA、装PyTorch,但我见过太多人卡在前面WSL本身都没装利索。WSL2的安装有几个版本迭代,Windows 10和Windows 11的步骤不完全一样,这里我把完整流程和原理一起讲清楚。
2.1 开启Windows虚拟化平台
WSL2依赖Windows的虚拟化功能,所以第一步是确认BIOS里开了虚拟化(Intel VT-x或者AMD SVM),然后在Windows功能里勾选“适用于Linux的Windows子系统”和“虚拟机平台”。这一步点完需要重启电脑。Windows 11用户可以直接在管理员PowerShell里执行wsl --install,它会一次性装好所有需要的功能组件。Windows 10用户建议手动勾选,因为自动安装脚本有时会漏掉“虚拟机平台”这一项,导致后面WSL2起不来或者显示版本是1。
检查是否开启成功的办法是在PowerShell里执行:
wsl --status如果输出里有“默认版本:2”,说明内核已经在走WSL2;如果显示版本1,需要执行wsl --set-default-version 2强制切换。
2.2 安装Ubuntu 20.04发行版
发行版的选择看起来是个小决定,实际上影响后续所有依赖的版本。我这个项目用的很多视觉库(比如libgl1、libglib2.0-0)在Ubuntu 22.04的源里已经换成了更新版本,反而会和老版CUDA的依赖产生冲突。Ubuntu 20.04是兼容性最稳的版本,NVIDIA官方对它的Container Toolkit支持也最成熟。
安装方式我建议从Microsoft Store搜索“Ubuntu 20.04”安装,不要用wsl --install -d Ubuntu-20.04命令行安装。Store版本在创建用户时会引导你设置UNIX用户名和密码,命令行版本有时候会跳过这个交互直接以root身份默认创建,后面文件权限会乱套。装好后进入Ubuntu终端,第一件事是换apt源:
sudo sed -i 's/archive.ubuntu.com/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list sudo apt update && sudo apt upgrade -y注意,如果你用的是国内网络,不换源的apt update会慢到怀疑人生,而且经常超时,这一步千万别省。
2.3 WSL2的内存和CPU配置优化
WSL2默认的内存配额是宿主机内存的一半,CPU核数不限,磁盘空间支持动态扩容。但对深度学习这种动辄占几十GB显存和内存的负载来说,默认配置并不合理。我需要手动创建C盘用户目录下(或者用\\wsl$\访问也行)的.wslconfig文件,路径是C:\Users\<你的用户名>\.wslconfig。
[wsl2] memory=16GB processors=8 swap=8GB localhostForwarding=true这里memory建议给到物理内存的一半以上但不能全给,否则Windows本体卡死。swap设到8GB是为了防止某个数据集加载瞬间内存爆掉。改完这个文件之后,在PowerShell里执行wsl --shutdown再重新进入Ubuntu,配置才会生效。
还有一个很多人不知道的优化点:WSL2的虚拟磁盘文件(ext4.vhdx)默认放在C盘,C盘空间紧张会导致磁盘扩容失败或者性能骤降。通过wsl --export和wsl --import可以把整个发行版迁移到D盘,具体命令是:
wsl --export Ubuntu-20.04 D:\wsl\ubuntu.tar wsl --unregister Ubuntu-20.04 wsl --import Ubuntu-20.04 D:\wsl\ubuntu D:\wsl\ubuntu.tar注意用--import方式迁移后的默认用户会变成root,需要再单独用ubuntu2004.exe config --default-user <用户名>恢复普通用户身份,否则后面所有文件操作都要加sudo,很闹心。
2.4 在WSL2里配置必要的开发工具链
深度学习环境不是光有conda就完事,系统层面的编译工具链必须先装好。PyTorch在安装时会编译一些C++扩展,比如后面要装Torchvision的某些算子,没有GCC的裸环境会直接报错。我习惯在装任何Python库之前,先把这些系统依赖一次装齐:
sudo apt install -y build-essential gcc g++ make cmake git wget curl sudo apt install -y libgl1 libglib2.0-0 libsm6 libxrender1 libxext6 sudo apt install -y libopenblas-dev libatlas-base-dev liblapack-devlibgl1和libglib2.0-0这两个是OpenCV的运行时依赖,不装的话后面import cv2必报libGL.so.1: cannot open shared object file错误。这个错误在深度学习环境搭建里出现频率极高,几乎是新手致命的第一个坑,提前装好能省一次排错。
3. GPU驱动和CUDA版本匹配:专为PyTorch训练做的一套底层层
环境搭建的核心风险集中在GPU这一层。CUDA工具包的版本和PyTorch的预编译版本必须对齐,差一个版本小版本都会出现torch.cuda.is_available()返回False这种让人抓狂的情况。
3.1 显卡驱动在WSL2里的特殊性
首先必须明确:WSL2里不需要安装Linux版NVIDIA驱动。WSL2的GPU透传机制是直接把Windows侧的GPU驱动映射进Linux内核的,所以Windows宿主机上只要装了较新的NVIDIA驱动(建议460版本以上),WSL2里执行nvidia-smi就能直接看到显卡信息。这一步经常会有人搞错,在Ubuntu里跑sudo apt install nvidia-driver-xxx,结果装坏了整个WSL2的内核模块,最后只能重置发行版。
验证驱动是否透传成功:
nvidia-smi如果输出正常显示显卡型号和驱动版本,恭喜,底层GPU通路已经通了。版本号建议记录一下,后面选CUDA版本要用。
3.2 CUDA工具包和cuDNN的版本选型逻辑
PyTorch各版本对CUDA版本有明确对应关系,比如PyTorch 2.x系列同时支持CUDA 11.8和12.1两个分支。我个人的选型原则是:选PyTorch官方预编译里标注为“stable”的那一档CUDA版本,不要追最新,也不要用老掉牙的版本。截至本文写作时间,PyTorch 2.1.0对应CUDA 11.8/12.1均稳定,我用的是CUDA 11.8,因为它在WSL2里的兼容记录最干净,TensorRT配套的转件也支持得最全。
安装CUDA Toolkit时,NVIDIA官网给的命令是一套runfile安装方式,但在WSL2里并不推荐。WSL2环境里只需要装CUDA Toolkit这个开发工具包,不需要装驱动模块,用runfile安装时切记加--toolkit参数:
wget https://developer.download.nvidia.com/compute/cuda/11.8.0/local_installers/cuda_11.8.0_520.61.05_linux.run sudo sh cuda_11.8.0_520.61.05_linux.run --toolkit --silent装完后配置环境变量:
echo 'export PATH=/usr/local/cuda-11.8/bin:$PATH' >> ~/.bashrc echo 'export LD_LIBRARY_PATH=/usr/local/cuda-11.8/lib64:$LD_LIBRARY_PATH' >> ~/.bashrc source ~/.bashrc nvcc --versioncuDNN的安装也不复杂,去NVIDIA官网下载适配CUDA 11.8的cuDNN 8.9.x版本,按照安装包的tar文件解压后复制到CUDA目录即可。
3.3 创建conda虚拟环境:隔离才是环境搭建的核心课题
深度学习项目的依赖管理必须用虚拟环境,这是一个老生常谈但又总有人忽略的问题。同一个机器上不同项目要求的PyTorch版本、OpenCV版本可能截然不同,全装在base环境里,到后期升级依赖就是一场灾难。我用miniconda而不是Anaconda,因为Anaconda预装了一堆我用不到的包,体积大而且容易带进来不兼容的传递依赖。
wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-py39_23.3.1-0-Linux-x86_64.sh bash Miniconda3-py39_23.3.1-0-Linux-x86_64.sh安装完conda之后配好清华源,然后创建项目专用的环境。这个环境对应项目标题里的系统名,我直接取名叫attention:
conda create -n attention python=3.9 -y conda activate attentionPython版本选3.9而不是最新的3.11,是因为PyTorch虽然已经在跟进新版本,但很多相关的视觉库(比如某些老版本的OpenCV、dlib)在3.10以上的编译支持不完全。3.9是生态兼容性最平衡的选择。
3.4 安装PyTorch和Torchvision
PyTorch的安装是环境搭建的分水岭——装好了,后面所有东西都能跑;装坏了,你会在各种报错里挣扎一整晚。官方给出的conda安装命令是:
conda install pytorch==2.1.0 torchvision==0.16.0 torchaudio==2.1.0 pytorch-cuda=11.8 -c pytorch -c nvidia但是,直接执行这个命令在国内容易因为访问外网下载慢而失败。我的做法是先在conda源里配置好PyTorch的国内镜像,再把安装命令跑通。配置~/.condarc文件添加pytorch的镜像通道,然后执行上述安装命令时去掉-c pytorch -c nvidia参数,让它走镜像源。
装完之后立刻验证GPU可用性:
python -c "import torch; print(torch.__version__); print(torch.cuda.is_available()); print(torch.cuda.get_device_name(0))"正确的输出应该类似:2.1.0、True、NVIDIA GeForce RTX 3060之类的显卡型号。如果is_available()返回了False,不要急着怀疑安装过程,先检查前面nvidia-smi是否能正常工作。大概率是驱动透传问题或者CUDA环境变量没刷新生效。
4. 项目骨架搭建:把课堂专注度分析系统需要的依赖一次装齐
环境搭建的下一个环节是围绕项目本身去准备代码和依赖。这个项目虽然叫“专注度分析”,但最底层的模块是目标检测和姿态估计,所以我会把ultralytics(YOLOv8的官方仓库)作为核心依赖,再铺开其他工具库。
4.1 核心依赖清单和安装命令
进入虚拟环境,在项目目录下执行安装。这里我强调一下:所有项目依赖都要在虚拟环境里装,不要用sudo pip去装系统的Python包,那样会把环境搞得一塌糊涂。
pip install ultralytics pip install opencv-python pip install albumentations pip install onnx onnxruntime pip install scikit-learn scipy matplotlib pandas pip install tqdm tensorboardultralytics这个包很厚道,它会帮你把torch、torchvision、opencv、numpy等一堆基础依赖自动拉进来,版本兼容性管理得比我自己手动装要稳妥得多。装完opencv-python之后,跑一下python -c "import cv2; print(cv2.__version__)"验证一下。很多人在这一步会卡在libGL.so.1的报错上,如果你前面按照第2.4节装了libgl1 libglib2.0-0,这里应该一次通过。
4.2 设计项目目录结构:环境搭建不只是装库
一个条理清晰的项目目录结构是环境搭建的一部分,它决定了后面数据怎么组织、训练日志往哪里写、模型权重存哪里。我自己用的是这套目录结构:
attention_analysis_system/ ├── data/ │ ├── raw/ # 原始课堂视频数据 │ ├── annotations/ # 标注文件 │ └── processed/ # 预处理后的数据 ├── models/ # 训练好的权重文件 │ ├── detection/ # 检测模型权重 │ └── pose/ # 姿态模型权重 ├── configs/ # 所有配置文件 │ ├── dataset.yaml # 数据集配置 │ └── train.yaml # 训练超参数配置 ├── scripts/ # 数据处理脚本 ├── src/ # 核心代码 │ ├── detection/ # 检测相关 │ ├── pose/ # 姿态估计相关 │ ├── attention/ # 专注度分析逻辑 │ └── utils/ # 工具函数 └── runs/ # 训练和推理的输出这套结构的好处是:数据、代码、输出彻底分离,训练过程产生的日志和权重不会污染代码目录。配合YOLOv8自带的推理输出文件夹也不冲突。
4.3 跑通第一个YOLOv8推理Demo
环境搭得对不对,拿一个真实模型跑一遍推理是最直接的验证。YOLOv8官方仓库里带了预训练权重,下载一个yolov8n.pt在公开视频上做目标检测测试:
from ultralytics import YOLO model = YOLO('yolov8n.pt') results = model.predict(source='https://ultralytics.com/images/bus.jpg', save=True, project='runs/inference', name='demo')如果环境正常,几秒钟之后就能在runs/inference/demo/目录看到带检测框标注的输出图片。这一步验证的不只是YOLOv8能不能跑,真正验证的是OpenCV读取图像、NumPy数组处理、PyTorch张量推理这一整条数据流水线是否通畅。
跑通检测Demo后顺手验证姿态模型:
model = YOLO('yolov8n-pose.pt') results = model.predict(source='https://ultralytics.com/images/bus.jpg', save=True, project='runs/inference/pose_demo')姿态模型能跑通,意味着后续提取人脸关键点和身体关键点这条主线是从底层就通的。
4.4 数据预处理依赖的补充:聚焦课堂视频场景
课堂场景的视频流有自己的特点:长时间连续、码率高、分辨率大。后面做数据预处理会大量用到视频抽帧、图片缩放、数据增强这些操作。这部分在环境上就要提前备好工具库:
pip install ffmpeg-python imageio imageio-ffmpeg sudo apt install -y ffmpegffmpeg在Linux上的安装尤其要提醒一下:在WSL2里直接sudo apt install ffmpeg装的是系统版本,imageio-ffmpeg则会自带一个独立可执行文件,两者并存有时候会导致编码器冲突。我的经验是优先让imageio-ffmpeg接管Python侧的调用,系统级ffmpeg只在命令行做视频切割或转码时用,两边不要混着调用同一个文件。
5. 搭建过程中的问题排查记录:我在这个环境上踩过的坑
环境搭建最大的特点就是确定性低,明明照着教程一步步来,就是有人会翻车。这部分我把自己在这次搭建中真实遇到的几个问题完整记录下来,包括排查思路和最终解法,希望你能直接绕过去。
5.1 问题一:torch.cuda.is_available()返回False
现象是PyTorch装好后,GPU抱怨连接不上。排查链路是这样的:先跑nvidia-smi,确认显卡驱动正常透传;再跑nvcc --version,确认CUDA工具包版本和PyTorch编译的CUDA版本一致——装的是CUDA 11.8,PyTorch也必须选pytorch-cuda=11.8这个变体;最后检查conda环境里是否有多个CUDA相关的环境变量残留。最后定位是.bashrc里导出的CUDA路径和conda环境冲突,把LD_LIBRARY_PATH里手动添加的路径注释掉,重启终端后恢复正常。
这个过程教会我的一个判断逻辑是:nvidia-smi输出的是驱动支持的CUDA最高版本,而这个数字是上限而不是当前生效版本。PyTorch真正用的是自己编译时的CUDA Runtime库,两者数字不一定要一样,但PyTorch的Runtime版本不能超过驱动支持上限。很多教程把这两者混为一谈,是各种误判的根源。
5.2 问题二:libGL.so.1缺失导致OpenCV无法导入
这个问题在新装的Ubuntu 20.04 WSL2环境里几乎必现。报错内容长这样:
ImportError: libGL.so.1: cannot open shared object file: No such file or directory根因是OpenCV的Python包依赖了系统的OpenGL库,但干净的Ubuntu默认不装。解法是sudo apt install -y libgl1 libglib2.0-0。这个坑我在第2.4节已经提前打了预防针,但如果你没装到那一步,这里再补一次。
5.3 问题三:YOLOv8训练时内存溢出(OOM)
课堂场景数据集图片分辨率高,YOLOv8训练时batch size稍大就会把16GB内存吃满。排查发现WSL2默认分配的内存才宿主机一半,而且.wslconfig设置没生效——原因是文件放到了错误的用户目录。WSL2读取的是Windows当前登录用户目录下的.wslconfig,不是Linux侧的/home目录。修正后重新wsl --shutdown再进,内存配额变成16GB,训练基本稳定。
5.4 问题四:pip install ultralytics很慢或卡死
国内网络环境下装任何大型Python包都会遇到这个问题。解法是配置pip镜像源:
pip config set global.index-url https://mirrors.tuna.tsinghua.edu.cn/pip/simple紧接着还有个细节:YOLOv8下载预训练权重时走的是 GitHub 的 release 地址,国内访问极不稳定。我的做法是手动下载yolov8n.pt文件和yolov8n-pose.pt文件放到models/目录下,再用YOLO('models/yolov8n.pt')指定路径加载,绕开自动下载。
5.5 问题五:conda激活环境后命令行出现(base)想删掉
这个不算报错,但容易让人困惑。WSL2里安装Miniconda后,每次打开终端都会自动进入base环境,对并不需要默认激活的人来说很烦。执行conda config --set auto_activate_base false然后重新打开终端即可。
还有一个提升日常用感的配置:把conda和pip的默认缓存目录从系统盘挪到数据盘,避免Cache占满C盘。原理和WSL2迁移是一样的,环境搭建阶段多花十分钟,后面能省出一堆磁盘空间。
6. 自检清单:环境搭建到什么程度算真正完成
很多人在装完PyTorch之后就觉得环境搭建任务结束了,实际上后面模型一跑就会出现问题。我给自己定了一个自检清单,从底层往上逐项验收,每项都通过才敢说环境是合格的。
| 检查层级 | 检查命令/代码 | 期望结果 |
|---|---|---|
| 系统层 | uname -a | Linux 5.x及以上内核 |
| GPU层 | nvidia-smi | 正常显示显卡型号和驱动 |
| CUDA层 | nvcc --version | 显示CUDA 11.8 |
| Python层 | python --version | 3.9.x |
| PyTorch层 | python -c "import torch; print(torch.cuda.is_available())" | True |
| OpenCV层 | python -c "import cv2; print(cv2.__version__)" | 无报错 |
| YOLO层 | 运行一次推理Demo | 输出带检测框的图片 |
| 数据层 | python -c "import albumentations, onnx, tensorboard" | 全部无报错 |
每一项都过完,这套环境才真正具备了启动项目开发的条件。我遇到过不少人前面几步全过,但到YOLO推理Demo这一步卡了好几天,就是因为在OpenCV或者权重下载这些细节上翻车。
自检之后,还有一类容易被忽略的工作是给后面协作的人写README。不管你是自己做还是团队一起做,把上述所有安装步骤、版本号和坑位整理成一个ENV.md文件放进项目根目录,能省掉大量“你环境怎么配的”这类沟通成本。我每次都写,因为搭过一遍环境的人都懂:记忆并不可靠,文档才是真的。
7. 一些实战心得:环境搭建的心态与节奏
最后聊聊这次的体会。
第一,环境搭建不要一口气全装完再验证。最好的节奏是每装一个关键节点就立刻验证,比如装完CUDA就验nvcc,装完PyTorch就验GPU可用性,装完OpenCV就验导入,全部通过再进入下一层。一旦哪一步失败,排查范围能立刻锁定在那一个环节,而不是要从头开始猜。
第二,版本锁定是环境搭建的灵魂。我安装时把conda环境里所有关键包写进了一个requirements-lock.txt:
pip freeze > requirements-lock.txt后面不管是重装环境还是给同事复现,直接照着这个文件恢复,版本完全一致,避免了“在我机器上明明能跑”的经典甩锅现场。
第三,WSL2无论多方便,它依然不是物理Linux。如果你后面要做对硬件延迟极其敏感的实时视频处理,或者要直接操作多个USB摄像头做多路采集,建议在开发环境稳定后,再准备一台物理Linux服务器做正式训练和推理测试。WSL2适合开发和调试,真正的生产环境还是要跑在裸Linux上,这一点项目初期就应该想清楚。