YOLOv8源码实战:从环境搭建到训练部署全指南
发布时间:2026/9/26 12:33:42来源:尧图网络
简介这是一份 YOLOv8 目标检测源码资源包面向计算机视觉研究者与深度学习开发者旨在帮助读者深入理解实时目标检测系统的实现细节。包内包含模型定义、训练与推理流程、数据预处理、损失函数计算和模型优化等核心模块并附有结构示意图与说明文档方便对照源码快速梳理整体框架。资源共 81 个文件以 62 个 Python 源码文件为主覆盖网络搭建、工具函数、训练引擎等另有 17 个 YAML 配置文件用于定义模型结构及训练超参数整体压缩包约 287KB轻量便携。目前已有 9039 人学习下载具备较高参考热度。通过研读该源码读者可掌握 YOLOv8 的主干网络、特征融合、多尺度检测头及 NMS 后处理等关键实现也能学习在 PyTorch 或 TensorFlow 等框架下构建、训练与调优检测模型的实用思路为后续研究或应用开发提供扎实基础。1. 拿到“YOLOv8源码.rar”之后你真正要解决的是这三件事把一个几百 MB 的压缩包从网盘拖下来解压看到ultralytics、yolov8n.pt、data、runs这些目录很多人第一反应是“源码有了跑起来不就完了”。结果要么是 import 直接报ModuleNotFoundError要么是torch的 CPU 版本跑一晚都出不来一张图。YOLOv8 源码包本质上是一套完整的训练、推理、导出工具链而不是一个可以双击运行的软件你要解决的是环境依赖、数据格式和训练参数这三件事才能让它真正产出可用的权重。这篇笔记面向两类人一类刚下载完源码包、在 Ubuntu 或 Windows 上准备搭环境的入门者另一类是已经在用其他检测框架、想把数据集迁移到 YOLOv8 的工程师。它不能帮你下载源码但能让你把下载到的源码跑透。2. 解压与目录结构先看清源码包里的每一块再动手2.1 RAR 混进了 YOLOv8 源码第一步是校验和解压从网盘拉回来的.rar文件第一件事不是双击解压而是校验完整性。常见做法是先用WinRAR或7-Zip的“测试”功能跑一遍确认压缩包没有 CRC 错误。这一步能省掉后面所有莫名其妙的报错。解压时我一般会指定一个不带空格的路径比如D:\yolov8-src或~/yolov8-src源码里很多脚本会拼路径空格和中文目录会导致cv2.imread读到空对象这是一个隐藏很深的坑。# Linux / Ubuntu 20.04 下解压 mkdir -p ~/yolov8-src unzip -o YOLOv8源码.rar -d ~/yolov8-src # 如果系统里没有 unrar先安装 sudo apt-get install unrar unrar x YOLOv8源码.rar ~/yolov8-src/解压参数说明-o表示覆盖已存在文件-d指定解压目标目录unrar x会保留压缩包内的目录层级比e只解文件到当前目录更适合源码包。若不放心压缩包内的文件是否齐全解压完成后用find . -type f | wc -l对比你拿到的文件清单数量。2.2 源码目录逐一说透ultralytics/cfg/models 才是核心YOLOv8 源码包解压后核心目录是ultralytics里面按功能拆成了cfg、data、engine、models、utils这几块。很多人第一次看会蒙以为入口是train.py实际上 YOLOv8 从 v8.0 开始就没有独立的train.py了训练入口是ultralytics/yolo/下的 CLI 和 Python API。ultralytics/cfg/models/v8/下有几个关键 yamlyolov8.yaml、yolov8n.yaml、yolov8s.yaml。它们的区别不是网络结构而是scale参数也就是深度和宽度倍率。yolov8n是 nano 版本适合 CPU 跑和快速验证yolov8x是超大版本精度最高但对显存要求也最高。ultralytics/cfg/datasets/里放的是数据集配置文件比如coco128.yaml点开能看到path、train、val、nc、names这些字段。runs/目录是训练和推理的输出目录默认会按train、detect、segment分类每次运行生成exp、exp2、exp3这样的递增序号。weights/目录里放的是权重文件但我发现很多网盘里的源码包会附带一个yolov8n.pt或yolov8s.pt如果没带也没关系源码会自动从官方地址下载。2.3 在 Ubuntu 20.04 上搭 CPU 版环境最小可用命令热搜里“ubuntu20.04搭建yolov8环境cpu版本”是被问得最多的场景。CPU 版的核心是装对torch的 CPU 版本不要装成 CUDA 版否则后面会有一堆libcublas报错。Python 版本建议 3.8 到 3.10Ubuntu 20.04 默认的 Python 3.8 可以直接用。cd ~/yolov8-src python3.8 -m venv venv source venv/bin/activate pip install --upgrade pip # CPU 版 PyTorch注意 index-url 必须指定 cpu 源 pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu pip install -e .pip install -e .是源码包安装它会读取pyproject.toml把ultralytics注册为可导入的包同时自动安装opencv-python、numpy、pandas、matplotlib这些依赖。这里最关键的一点必须用-e而不是普通pip install .因为后者装的是拷贝你后面改ultralytics里的源码不会生效。验证环境是否就绪可以跑python -c from ultralytics import YOLO; model YOLO(yolov8n.yaml); print(model)能输出模型结构信息说明环境已经通了。注意这里用的是yaml而不是pt表示只加载网络结构不加载预训练权重。2.4 有显卡时换成 GPU 环境CUDA 与 cuDNN 的版本匹配GPU 版环境的核心难点是 CUDA、cuDNN 和 PyTorch 三者的版本匹配。我踩过的坑是torch的 CUDA 版本和系统里nvcc -V看到的版本不一致导致torch.cuda.is_available()返回 False。最稳妥的做法是直接用 PyTorch 官方提供的安装命令它会自动匹配对应的 CUDA 运行时。# 先确认显卡驱动支持的最高 CUDA 版本 nvidia-smi # CUDA 12.1 对应 torch 2.x 的 cu121 版本 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121 pip install -e . python -c import torch; print(torch.cuda.is_available(), torch.cuda.get_device_name(0))输出True和显卡型号才说明 GPU 环境可用。GTX 1660 Ti 这类 6GB 显存的卡跑yolov8s或yolov8m没问题但跑yolov8l就容易爆显存后面避坑章节会细说。硬件选型和 batch size 的对应关系我一般默认 6GB 显存用 nano 或 smallbatch size 不超过 16。3. 跑通官方预训练模型先看到目标框再谈训练3.1 用 CLI 一行命令做推理环境搭好之后先用官方预训练权重跑通推理是验证环境正确性的最直接手段。源码包默认支持yolov8n.pt、yolov8s.pt、yolov8m.pt等权重模型会自动从 GitHub 下载放在~/.cache/ultralytics/目录下。如果网速不好也可以手动下载后放到当前目录。# 使用 yolov8n 预训练权重推理一张图片 yolo detect predict modelyolov8n.pt sourcehttps://ultralytics.com/images/bus.jpg # 推理本地图片目录 yolo detect predict modelyolov8s.pt source./test_images/ saveTrue命令参数说明detect指定任务类型为检测predict是推理子命令model指定权重路径source指定图片路径或 URLsaveTrue表示把标注结果保存到runs/detect/exp/下。默认情况下推理结果会保存为image.jpg同名文件叠加了检测框和类别标签。3.2 用 Python API 做推理并理解 Predictor 的工作流CLI 适合快速验证但如果要批量处理图片或把检测嵌入到自己的程序里需要用 Python API。这里我会直接操作源码包里的YOLO类把整个推理流程拆开看。from ultralytics import YOLO # 加载模型传入 .pt 文件时源码会自动把权重和网络结构绑定 model YOLO(yolov8n.pt) # 推理results 是一个 Results 对象列表每张图一个元素 results model.predict( sourcetest_images/, imgsz640, conf0.25, devicecpu, ) # 取出第一张图的检测结果 r results[0] boxes r.boxes # 包含 xyxy、conf、cls 三个属性 for box in boxes: x1, y1, x2, y2 box.xyxy[0].tolist() # 左上角右下角坐标 conf box.conf[0].item() # 置信度 cls int(box.cls[0].item()) # 类别索引 print(f检测到目标: 坐标({x1:.0f},{y1:.0f})-({x2:.0f},{y2:.0f}), 置信度{conf:.2f}, 类别{cls})参数说明imgsz640是输入分辨率越大检测越慢但小目标越容易检出conf0.25是置信度阈值低于该值的框会被过滤devicecpu显式指定 CPU 推理不传的话源码会自动选 GPU。r.boxes是Boxes对象内部张量默认在 GPU 上用.tolist()或.item()转成 Python 原生类型否则打印出来只是张量描述。这里有个容易误解的点model.predict()返回Results对象列表而不是直接返回张量。每个Results对象还包含orig_img原始图像、orig_shape原始尺寸、names类别名列表等属性这些在画框和做业务逻辑时都会用到。3.3 快速可视化网络结构从 yaml 到模型图YOLOv8 的网络结构定义在 yaml 文件里不是写在 Python 代码中。想画出网络结构图可以用源码自带的model.info()和torchviz导出。from ultralytics import YOLO # 从 yaml 创建模型不加载权重 model YOLO(yolov8n.yaml) # 打印每一层的输出形状和参数数量 model.info(verboseTrue) # 导出网络结构图需要安装 torchviz # pip install torchviz from torchviz import make_dot import torch x torch.randn(1, 3, 640, 640) y model.model(x) dot make_dot(y, paramsdict(model.model.named_parameters())) dot.render(yolov8n_arch, formatpng)model.info(verboseTrue)会逐层打印from、n、params、module、arguments这些字段对理解yolov8网络结构图很有帮助。make_dot生成的计算图会非常庞大建议只导出yolov8n并且把expand参数设为False控制深度。实际调试时我更习惯直接改 yaml 文件而不是看计算图。3.4 保存和查看推理结果save、save_txt、save_conf 参数的差异推理结果的保存方式有三个参数经常被混淆save、save_txt、save_conf。saveTrue是保存画了框的图片save_txtTrue是保存检测结果的纯文本每行格式为class x_center y_center width height conf这个格式和训练数据的标签格式完全一致save_confTrue是额外把置信度写入 txt。写业务代码时如果要把检测结果接进上下游系统通常在predict里开save_txtTrue再结合save_confTrue这样输出的 txt 可以直接当标签复用。results model.predict( sourcetest_images/, saveTrue, # 保存标注图片 save_txtTrue, # 保存标签文件 .txt save_confTrue, # 在 txt 里附上置信度 projectruns/detect,# 输出目录 namebus_test, # 子目录名 exist_okTrue, # 允许覆盖同名目录 )需要注意exist_okTrue这个参数很实用。默认情况下重名目录会自动递增为bus_test2写脚本循环调参时会生成一堆无用目录开了这个参数就会覆盖上次结果。这也是源码包里一个容易被忽略但很提升体验的细节。4. 训练自己的数据集从 labelme 标注到跑完一个 epoch4.1 数据集目录规范与 labelme 标注训练自己的数据集是热搜词“yolov8训练自己的数据集”里最核心的需求。YOLOv8 要求数据集按固定目录组织图像和标签分离标签是.txt文件每行一个目标格式为class x_center y_center width height坐标全部归一化到 0~1。目录结构示例dataset/ ├── images/ │ ├── train/ │ │ ├── img_001.jpg │ │ └── img_002.jpg │ └── val/ │ ├── img_100.jpg │ └── img_101.jpg ├── labels/ │ ├── train/ │ │ ├── img_001.txt │ │ └── img_002.txt │ └── val/ │ └── img_100.txt └── data.yamllabelme 标注得到的是一份 JSON记录了polygon或rect形状。YOLOv8 不直接用 labelme 的 JSON需要转成上述 txt 格式。这一步要注意labelme 的多边形坐标是绝对像素值必须除以图片宽高归一化类别名要映射成数字索引从 0 开始。漏掉归一化是新手最常见的翻车点训练出来的模型会诡异到框完全偏掉。4.2 把 labelme 的 JSON 转成 YOLO 格式 txt转换脚本与四个边界坑我每次做数据集转换都会遇到几个固定的边界问题这里给出一份可直接用的转换脚本。import json import os from glob import glob from PIL import Image def convert_labelme_json(json_path, out_dir, class_names): 把单个 labelme JSON 转为 YOLO 格式 txt class_names: [person, car, dog] 顺序决定了类别索引 with open(json_path, r, encodingutf-8) as f: data json.load(f) img_path data[imagePath] # 坑1: imagePath 有时是绝对路径有时只有文件名这里需要拼接 if not os.path.isabs(img_path): base os.path.dirname(json_path) img_path os.path.join(base, img_path) # 坑2: labelme 的 imageData 字段可能为空必须从磁盘读图拿宽高 with Image.open(img_path) as img: w, h img.size txt_name os.path.splitext(os.path.basename(json_path))[0] .txt out_txt os.path.join(out_dir, txt_name) with open(out_txt, w, encodingutf-8) as f: for shape in data[shapes]: label shape[label] if label not in class_names: # 坑3: 标注里混入了未定义类别跳过而不是报错 continue cls_id class_names.index(label) points shape[points] if shape[shape_type] rectangle: # 矩形只有两个点左上角和右下角 (x1, y1), (x2, y2) points else: # 多边形取外接矩形 xs [p[0] for p in points] ys [p[1] for p in points] x1, y1, x2, y2 min(xs), min(ys), max(xs), max(ys) # 坑4: 归一化并限制在 0~1越界坐标会导致训练 loss 异常 x_center ((x1 x2) / 2) / w y_center ((y1 y2) / 2) / h box_w (x2 - x1) / w box_h (y2 - y1) / h x_center min(max(x_center, 0.0), 1.0) y_center min(max(y_center, 0.0), 1.0) box_w min(max(box_w, 0.0), 1.0) box_h min(max(box_h, 0.0), 1.0) f.write(f{cls_id} {x_center:.6f} {y_center:.6f} {box_w:.6f} {box_h:.6f}\n) # 批量转换所有 JSON json_files glob(labelme_data/*.json) os.makedirs(dataset/labels/train, exist_okTrue) class_names [person, car] # 按你的实际类别调整 for jf in json_files: convert_labelme_json(jf, dataset/labels/train, class_names)代码逻辑说明脚本先读 JSON 里的imagePath定位原图再从图片实际宽高获得归一化分母。使用Image.open而不依赖 JSON 里的imageWidth字段是因为 labelme 在“只保存 JSON、不嵌入图片数据”的模式下imageWidth可能是 0读取原图是最可靠的。输出时用.6f保留 6 位小数避免浮点误差累积。这四个坑各自对应一种真实报错路径错会导致标签文件生成但内容空的“黑匣子”宽高错会导致标签全部偏移未定义类别会导致训练时AssertionError: class index out of range越界坐标会导致 loss 不收敛。4.3 data.yaml 与模型 yaml 的修改要点数据集转换完成后需要写data.yaml告诉训练器去哪里找图、有几类。data.yaml的nc字段必须和class_names长度一致名字顺序也必须一致否则会出现“模型训练一切正常、但预测出来的标签全是错的”这种最隐蔽的问题。# dataset/data.yaml path: /home/user/yolov8-src/dataset # 数据集根目录最好写绝对路径 train: images/train # 训练集图片目录 val: images/val # 验证集图片目录 nc: 2 # 类别数量 names: [person, car] # 类别名列表顺序与转换脚本 class_names 一致path字段写相对路径时源码会以path为基准再拼接train和val。如果你把data.yaml放在数据集根目录里train直接写images/train即可如果data.yaml放在项目的ultralytics/cfg/datasets/下path就必须要写绝对路径否则源码会告诉你dataset not found这是一个很多人卡住的点。模型 yaml 的修改则要看你改哪一版。用yolov8n.yaml时nc会自动从data.yaml读取不需要手动改模型文件。但如果你自己改了模型的nc又和data.yaml不一致源码会直接抛出异常这反而是好事至少比静默出错强。4.4 训练命令、超参数含义与损失函数曲线怎么看训练命令的模板如下我一般会把参数显式写全避免依赖默认值。yolo detect train \ modelyolov8n.yaml \ datadataset/data.yaml \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ device0 \ projectruns/train \ nameperson_car_v1超参数含义epochs是训练轮数小数据集 100 轮起步通常 200 轮以内能看到收敛batch是单次送入的图片数CPU 环境建议 8 以内GPU 看显存余量lr0是初始学习率默认 0.01 适合大多数任务但如果你从预训练权重继续训练比如用yolov8n.pt而不是 yaml建议调成 0.001否则微调阶段 loss 容易震荡device0指定第一张显卡CPU 训练就写devicecpu。训练完成后源码会在project/name目录下生成results.csv和results.png。results.png包含损失曲线、精度曲线、召回率曲线等 8 张图。损失曲线里最关键的是train/box_loss、train/cls_loss和val/box_loss——如果你的 train loss 在下降但 val loss 从某个 epoch 开始上升那就是过拟合的典型信号应该提前停止或增大数据增强。很多人在看损失曲线时只盯着train/loss却忘了看val/loss这是不对的。训练日志里还有一个P精确率和R召回率的横条P 高说明预测框准确率高R 高说明漏检少两个都高是理想状态。import pandas as pd import matplotlib.pyplot as plt # 读取训练日志并画损失曲线 df pd.read_csv(runs/train/person_car_v1/results.csv) plt.figure(figsize(10, 4)) plt.plot(df[epoch], df[train/box_loss], labeltrain box_loss) plt.plot(df[epoch], df[val/box_loss], labelval box_loss) plt.xlabel(epoch) plt.ylabel(loss) plt.legend() plt.grid(True) plt.savefig(loss_curve.png, dpi150)这段脚本的核心是读取results.csv中对应列画成可单独查看的损失曲线文件。默认的results.png是一张大图包含所有指标缩放后看不清细节分开画可以放大观察过拟合的拐点。初次训练时如果发现train/box_loss在第一个 epoch 就掉到接近 0要检查是不是数据集里图片数量太少导致的过拟合而不是模型的功劳。5. 避坑YOLOv8 源码包最常见的 5 个翻车现场5.1 RAR 解压失败报 CRC 或“文件损坏密码错误”现象双击解压到一半弹出红字CRC 失败或者某几个文件解压出来是 0KB。原因主要有三种网络盘传输损坏、压缩包本身分包未下载完全、解压工具版本过旧不支持新版 RAR5 格式。解决先用WinRAR 6.0以上版本打开点击“工具→修复压缩文件”尝试重建压缩包如果修复无效重新下载并对比文件大小是否与网盘标注一致。源码包里的.pt权重文件如果是 0KB训练时会报Error loading data from blob这个信息能反向定位到是哪个文件坏了。5.2 训练时报错AssertionError: class index out of range现象数据转换完执行 train 没跑几个 batch 就崩溃提示class index out of range。原因labelme 里有未定义类别或者class_names列表索引和data.yaml的names顺序不一致。解决先检查txt文件中第一列数字是否都小于nc再检查data.yaml的names顺序和转换脚本的class_names是否完全一致。我曾经因为names里写了[person,car]而转换脚本里是[car,person]训练全程没报错但推理结果所有类别标签都是反的这种“逻辑错乱但不报错”的问题比直接报错更坑。5.3 CPU 训练慢到像死机epoch跑十几分钟一动不动现象Ubuntu 20.04 CPU 环境下训练日志epoch那一行刷了很久还在 0。原因CPU 推理和训练本来慢加上batch默认可能较大、数据加载没有开多进程。解决把batch调到 4 或 2同时把workers参数调大。yolo detect train modelyolov8n.yaml datadataset/data.yaml epochs100 imgsz640 batch4 workers8 devicecpuworkers8能让数据加载子进程并行预处理图片这一步对 CPU 环境提升非常明显。还有一个隐蔽点源码默认会在每个 epoch 结束后做验证如果val集图片很大验证阶段的耗时甚至超过训练阶段。这时可以加上valFalse跳过前 N 个 epoch 的验证等 loss 有下降趋势再开。CPU 训练本来就是验证流程用的指望拿它跑出可用的工业模型不现实建议先只跑 5 epoch 确认流程通。5.4 首次推理卡在Downloading https://github.com/ultralytics/assets/releases/...现象执行predict时报下载超时一直卡在下载yolov8n.pt。原因源码会自动从 GitHub 下载预训练权重访问受限或网速不稳定。解决不折腾代理直接找镜像站或让有条件的同事帮忙下载.pt文件然后放到当前工作目录。源码查找权重的逻辑是先找本地路径找不到再下载所以你把yolov8n.pt放到项目根目录即可。另外可以设置环境变量YOLO_CONFIG_DIR来修改缓存路径但一般没必要。下载权重后要确认文件大小yolov8n.pt大约 6MByolov8s.pt大约 22MB如果只有几 KB 说明下载失败或文件损坏。5.5 推理结果全空白图片能跑、框也有但保存的图片上什么都没有现象predict正常执行终端打印的results里每个对象都有boxes但saveTrue保存的图片上没有框。原因这类问题大多数时候是conf阈值设置过高比如conf0.7时模型把低置信度的检测都过滤掉了而你的目标恰恰是小而模糊的物体。解决把conf调低到 0.1 或 0.05 试试。yolo detect predict modelyolov8n.pt sourcetest_images/ saveTrue conf0.05如果调低conf后还是没有框再用model.predict()手动打印boxes张量的内容确认是模型真的没检测到还是画框逻辑出问题。更多时候是第二个原因你传入的图片中有中文路径cv2.imread返回None源码不会报错直接静默跳过这张图。把图片重命名为纯英文路径是成本最低的解法。5.6 显存不足 OOMCUDA out of memory但换小 batch 还是崩现象GTX 1660 Ti 6GB 跑yolov8m.pt训练或推理时CUDA out of memory把batch1还是崩。原因显存占用不只是batch决定imgsz对显存的影响是平方关系——640x640是320x320的 4 倍显存开销。解决先降imgsz到 416 或 320再降batch。推理模式下可以加device0 halfTrue用 FP16 半精度推理显存占用直接减半。训练模式下不要用half梯度更新会不稳定。yolo detect predict modelyolov8n.pt sourcetest_images/ imgsz320 device0 halfTruehalfTrue是一个非常好用的技巧但要注意它只支持 GPUCPU 环境会直接报错。如果你的 GPU 是 10 系显卡Pascal 架构FP16 的加速效果有限这也是很多人测下来发现half没有提升的原因。6. 把源码包改造成自己的Head 微调与部署导出的路线6.1 在源码里改检测头以增加 P2 检测层为例“yolov8 head改进”是源码包进阶绕不开的需求。YOLOv8 默认从 P3、P4、P5 三个尺度输出检测如果你要检测小目标可以把 P2原图的 1/4 尺度加进检测头。改法不是直接改 Python 代码而是改ultralytics/cfg/models/v8/yolov8.yaml在head部分增加一层。先画网络结构图再用model.info()确认输出张量的形状是否符合预期。这里最常犯的错是在head里引用了一个不存在的层索引源码会在载入模型时直接报KeyError。如果不想动 yaml也可以试试社区常见的“在 backbone 后拼接注意力模块”的做法本质都是改head层数。6.2 导出 ONNX 并用 RK3588 部署的思路训练好的.pt要上板子比如 RK3588 这类边缘设备需要先导出 ONNX再转成 RKNN 格式。yolo export modelruns/train/person_car_v1/weights/best.pt formatonnx opset12 imgsz640导出命令参数说明opset12是 ONNX 的算子版本RKNN 工具链对高版本 opset 支持不一定及时建议先用 12 试。导出的.onnx用onnxruntime验证一遍输出再用 RKNN-Toolkit2 转成.rknn。这个链路里最容易翻车的不是导出而是导出前后精度不一致——通常是因为源码里使用了torch.where这类在 ONNX 里表达不一致的算子。验证方法是用同一张图跑.pt和.onnx对比输出张量的数值差异差异超过 1e-3 就要考虑换算子。6.3 验证训练效果的几个自检手段训练完别急着部署先用以下方法做自检。第一在验证集上跑model.val()看mAP50和mAP50-95这两个指标mAP50 是 IoU 阈值 0.5 下的平均精度业务上更关心第二随机抽 10 张没参与训练的图片推理用肉眼确认框的位置和类别第三把训练日志里的results.png保存下来对比train/box_loss和val/box_loss的收敛趋势。养成一个习惯每次训练都在runs/train/下保留data.yaml、args.yaml和results.csv这三个文件记录了训练的完整参数和结果方便后续复现和横向对比。这一步的成本极低但能让你少走很多弯路希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网