2. PyTorch模型基础:环境搭建与YOLOv8初探

说实话,很多同学一上来就急着跑模型,结果环境配了两天还没跑通。我当年也踩过这个坑——记得第一次配深度学习环境,CUDA版本不对,折腾了一整晚。所以这一章,咱们先把地基打牢。

2.1 PyTorch环境搭建

我个人习惯用conda来管理环境,干净、隔离、好清理。你想想看,项目多了,每个依赖版本都不一样,用conda能省不少心。

推荐环境配置:

  • Python 3.10+
  • PyTorch 2.0+(CUDA 11.8或12.1)
  • CUDA Toolkit + cuDNN(版本匹配)
  • Ultralytics(YOLOv8官方库)

搭建步骤其实就三步:

  1. 创建虚拟环境:conda create -n yolov8 python=3.10 -y
  2. 安装PyTorch:去官网选对应CUDA版本,比如 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
  3. 安装Ultralytics:pip install ultralytics

避坑指南:我曾经因为CUDA版本和显卡驱动不匹配,训练时直接报"CUDA error: out of memory"。后来发现是驱动太老,不支持新CUDA。建议先跑 nvidia-smi 看驱动版本,再选对应的CUDA。

2.2 YOLOv8源码下载与结构

YOLOv8的源码托管在GitHub上,Ultralytics团队维护得很勤快。下载方式有两种:

  • pip安装:pip install ultralytics,直接当库用
  • git clone:git clone https://github.com/ultralytics/ultralytics.git,方便改源码

我个人更推荐第二种,因为后面做ONNX导出时,可能需要调整一些细节。

YOLOv8的核心结构,说白了就是三部分:

模块 作用 关键组件
Backbone 特征提取 CSPDarknet + Conv + C2f
Neck 特征融合 FPN + PAN结构
Head 检测输出 Decoupled Head + Loss

嗯,这里有个关键点——YOLOv8把之前的耦合头换成了解耦头(Decoupled Head)。分类和回归分支分开,收敛更快。我在项目里对比过,确实比v5好调。

YOLOv8 整体结构 Backbone CSPDarknet + C2f Neck FPN + PAN Head Decoupled Head 关键说明 • 输入:640×640 RGB图像 • Backbone输出:多尺度特征图(P3/P4/P5) • Neck融合后:Head输出检测结果 • 输出:边界框 + 类别 + 置信度

2.3 模型加载与推理测试

环境搭好了,源码也下了,咱们先跑个推理试试。说白了,就是验证一下整个链路通不通。

小技巧:第一次跑推理,建议用官方预训练权重,别自己从头训。我刚开始总想自己训,结果显卡烧了三天,效果还不如人家预训练的。

加载模型就两行代码:

from ultralytics import YOLO

# 加载预训练模型
model = YOLO('yolov8n.pt')  # n: nano, s: small, m: medium, l: large, x: xlarge

推理更简单:

# 对图片进行推理
results = model('bus.jpg')

# 查看结果
for r in results:
    print(r.boxes)  # 边界框
    print(r.names)  # 类别名称

嗯,这里要注意——results 返回的是一个列表,每个元素对应一张图的结果。如果你传了一张图,那就是一个元素。

2.4 理解模型输入输出

做部署,最怕的就是输入输出搞不清楚。我见过有人把输入尺寸搞错,结果ONNX导出来推理全是错的。

输入格式:

  • 形状:[1, 3, 640, 640](batch, channel, height, width)
  • 数据类型:float32
  • 归一化:像素值除以255,范围[0,1]
  • 颜色通道:RGB(注意OpenCV默认是BGR!)

输出格式:

  • 形状:[1, 84, 8400](以YOLOv8n为例)
  • 84 = 4个坐标 + 80个类别概率
  • 8400 = 所有检测框(不同尺度特征图加起来)

为什么是8400?

YOLOv8在三个尺度上做检测:80×80、40×40、20×20。加起来就是 6400 + 1600 + 400 = 8400。每个格子预测一个框,所以总共8400个候选框。

输出后处理一般要经过:

  1. 阈值过滤:去掉置信度低的框(比如 < 0.5)
  2. NMS:非极大值抑制,去掉重复框
  3. 坐标转换:从归一化坐标转回原图坐标

我建议你写个简单的后处理函数,把结果可视化出来,这样心里有数。代码大概长这样:

import cv2
import numpy as np

def postprocess(output, img_shape, conf_thres=0.5):
    # output: [1, 84, 8400]
    # 转置为 [8400, 84]
    pred = output[0].transpose(1, 0)
    
    # 过滤低置信度
    mask = pred[:, 4] > conf_thres
    pred = pred[mask]
    
    # 取类别
    class_ids = np.argmax(pred[:, 5:], axis=1)
    confidences = pred[:, 4]
    boxes = pred[:, :4]
    
    return boxes, class_ids, confidences

好了,这一章的内容就到这儿。环境搭好了,模型能跑了,输入输出也搞清楚了——后面做ONNX导出和TensorRT部署,心里就有底了。