4. 训练环境搭建:Docker容器化、PyTorch/TensorRT环境配置、数据集准备与标注格式转换
环境搭建这事儿,看着简单,其实坑不少。我见过太多团队,算法调得挺好,一到部署就翻车。说白了,就是环境不一致闹的。
这一章,咱们就把工业缺陷检测的环境搭建捋清楚。从Docker容器化开始,到PyTorch训练环境,再到TensorRT推理优化,最后聊聊数据集那点事儿。
4.1 Docker容器化:让环境“随身携带”
为什么要用Docker?你想想看,算法工程师的电脑是Ubuntu 20.04,现场工控机是CentOS 7,库版本对不上,驱动装不上,这种事我遇到过不下十次。
Docker的好处就是:一次构建,到处运行。把整个环境打包成镜像,到哪都能跑。
4.1.1 Dockerfile编写要点
我习惯用NVIDIA的官方镜像做基础层。别自己从零装CUDA,太容易出问题。
# 基础镜像:Ubuntu 20.04 + CUDA 11.8
FROM nvidia/cuda:11.8.0-cudnn8-devel-ubuntu20.04
# 设置非交互模式
ENV DEBIAN_FRONTEND=noninteractive
# 安装系统依赖
RUN apt-get update && apt-get install -y \
python3.8 \
python3-pip \
libgl1-mesa-glx \
libglib2.0-0 \
libsm6 \
libxext6 \
libxrender-dev \
libgomp1 \
&& rm -rf /var/lib/apt/lists/*
# 设置工作目录
WORKDIR /workspace
# 安装Python依赖
COPY requirements.txt .
RUN pip3 install --no-cache-dir -r requirements.txt
# 设置时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime
我的习惯:requirements.txt里只写核心依赖,版本号锁死。比如torch==1.13.1,别用>=,否则不同时间构建的镜像可能不一样。
4.1.2 构建与运行命令
# 构建镜像
docker build -t defect-detection:v1.0 .
# 运行容器(挂载数据卷和GPU)
docker run -it --gpus all \
-v /home/user/data:/workspace/data \
-v /home/user/models:/workspace/models \
--shm-size=16g \
defect-detection:v1.0
注意:--shm-size一定要设。PyTorch DataLoader多进程读取数据时,共享内存不够会报错。我一开始没设,排查了半天。
4.2 PyTorch环境配置:选对版本很重要
PyTorch版本和CUDA版本要匹配。这个表我经常翻,直接贴出来:
| PyTorch版本 | CUDA版本 | cuDNN版本 | 适用场景 |
|---|---|---|---|
| 1.10.x | 11.3 | 8.2 | 老项目兼容 |
| 1.13.x | 11.7 / 11.8 | 8.5 | 工业部署主流 |
| 2.0.x | 11.8 / 12.1 | 8.7 | 新项目推荐 |
我个人建议:工业项目用PyTorch 1.13 + CUDA 11.8。这个组合最稳,TensorRT支持也最好。
4.2.1 安装命令
# PyTorch 1.13.1 + CUDA 11.8
pip3 install torch==1.13.1+cu118 torchvision==0.14.1+cu118 \
--extra-index-url https://download.pytorch.org/whl/cu118
验证安装:
python3 -c "import torch; print(torch.cuda.is_available())"
# 输出 True 才算成功
4.3 TensorRT环境配置:推理加速的关键
TensorRT能把模型推理速度提升2-5倍。但配置起来有点麻烦。
4.3.1 TensorRT版本选择
记住一个原则:TensorRT版本必须和CUDA版本对应。我用的是TensorRT 8.5.3 + CUDA 11.8。
# 下载TensorRT(需要NVIDIA账号)
# 选择:TensorRT 8.5.3 for Ubuntu 20.04 and CUDA 11.8
# 安装
dpkg -i nv-tensorrt-repo-ubuntu2004-cuda11.8-trt8.5.3.0-ga-20230314_1-1_amd64.deb
apt-get update
apt-get install tensorrt
# 验证
python3 -c "import tensorrt; print(tensorrt.__version__)"
避坑指南:我曾经在Docker里装TensorRT,忘了装pycuda,结果跑的时候报错。记得一起装上:
pip3 install pycuda
4.3.2 ONNX导出与TensorRT转换
这是模型移植的核心流程:
- PyTorch模型 → ONNX:固定输入尺寸,设置动态轴
- ONNX → TensorRT:选择精度(FP32/FP16/INT8)
- TensorRT推理:序列化引擎,保存为.engine文件
# PyTorch转ONNX
import torch
import torch.onnx
model = torch.load('model.pth')
dummy_input = torch.randn(1, 3, 640, 640)
torch.onnx.export(
model,
dummy_input,
'model.onnx',
opset_version=11,
input_names=['input'],
output_names=['output'],
dynamic_axes={'input': {0: 'batch_size'}}
)
# ONNX转TensorRT(命令行)
trtexec --onnx=model.onnx \
--saveEngine=model.engine \
--fp16 \
--workspace=4096
注意:转INT8需要校准数据集,不然精度掉得厉害。我有个项目INT8后mAP掉了5个点,后来改FP16才稳住。
4.4 数据集准备与标注格式转换
工业缺陷检测的数据集,格式五花八门。VOC、COCO、YOLO、自定义格式... 转换起来很烦。
4.4.1 常见标注格式对比
| 格式 | 存储方式 | 标注内容 | 适用场景 |
|---|---|---|---|
| VOC | XML文件 | 边界框 + 类别 | 分类、检测 |
| COCO | JSON文件 | 边界框 + 分割掩码 | 检测、分割 |
| YOLO | TXT文件 | 归一化坐标 | 实时检测 |
| 自定义 | CSV/TXT | 按项目定义 | 特殊需求 |
4.4.2 格式转换脚本(VOC转YOLO)
这是我项目里常用的转换脚本:
import xml.etree.ElementTree as ET
import os
def voc_to_yolo(xml_file, output_dir, classes):
tree = ET.parse(xml_file)
root = tree.getroot()
# 获取图像尺寸
size = root.find('size')
width = int(size.find('width').text)
height = int(size.find('height').text)
# 解析每个目标
yolo_lines = []
for obj in root.iter('object'):
class_name = obj.find('name').text
if class_name not in classes:
continue
class_id = classes.index(class_name)
bbox = obj.find('bndbox')
# VOC格式:xmin, ymin, xmax, ymax
xmin = int(bbox.find('xmin').text)
ymin = int(bbox.find('ymin').text)
xmax = int(bbox.find('xmax').text)
ymax = int(bbox.find('ymax').text)
# 转YOLO格式:中心点 + 宽高(归一化)
x_center = (xmin + xmax) / 2.0 / width
y_center = (ymin + ymax) / 2.0 / height
w = (xmax - xmin) / width
h = (ymax - ymin) / height
yolo_lines.append(f"{class_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}")
# 写入文件
txt_name = os.path.splitext(os.path.basename(xml_file))[0] + '.txt'
with open(os.path.join(output_dir, txt_name), 'w') as f:
f.write('\n'.join(yolo_lines))
# 使用示例
classes = ['scratch', 'dent', 'crack'] # 缺陷类别
voc_to_yolo('annotations/001.xml', 'labels/', classes)
我的经验:转换后一定要可视化检查。写个脚本把YOLO标签画回图片上,看一眼就知道对不对。我吃过亏,坐标转换公式写反了,训练了三天才发现。
4.4.3 数据集划分
工业场景下,我建议按产线批次划分,而不是随机划分。这样可以避免同一批次的数据既在训练集又在验证集。
# 按批次划分
train_batches = ['batch_01', 'batch_02', 'batch_03']
val_batches = ['batch_04']
test_batches = ['batch_05']
# 生成文件列表
train_images = []
for batch in train_batches:
train_images.extend(glob.glob(f'data/{batch}/*.jpg'))
关键指标:
- 训练集:验证集:测试集 = 7:2:1
- 每个缺陷类别至少100张
- 正负样本比例不超过1:10
4.5 本章知识结构
下面这张图,把环境搭建的整个流程串起来了:
4.6 常见问题与解决方案
| 问题 | 原因 | 解决方案 |
|---|---|---|
| Docker内无法调用GPU | 未安装nvidia-docker | 安装nvidia-docker2并重启 |
| PyTorch报CUDA版本错误 | PyTorch与CUDA不匹配 | 卸载重装对应版本 |
| TensorRT转换失败 | ONNX算子不支持 | 简化模型结构,替换自定义算子 |
| 标注坐标偏移 | 格式转换公式错误 | 可视化检查,修正公式 |
最后提醒一句:环境搭建别图快。每装一个组件,都验证一下。我见过太多人一口气装完,跑不起来,又从头排查,反而更慢。