使用YOLOv11训练自定义目标检测模型:从数据准备到模型部署全流程指南(钢材表面缺陷检测为例+附完整源码)
我们完成了基于YOLOv11的钢材表面缺陷检测从数据到部署的全流程实践。整个过程不仅涵盖了模型训练、损失监控与性能评估的核心技术环节,更展现了AI为传统工业质检带来的精准与效率提升。
文章目录
前言
YOLOv11由Ultralytics于2024年发布,在精度与速度上优势显著。尽管已有YOLO26等更新版本,但YOLOv11在成熟度、bug修复、环境适应及训练资源丰富性上更优,能确保高效稳定地完成自定义目标检测训练。文将详细介绍如何使用YOLOv11训练自定义目标检测模型,涵盖数据准备、模型训练、评估验证的完整流程钢材表面缺陷检测。
1. 训练结果演示

2. YOLOv11系列模型的性能对比图

3. 环境准备
3.1 安装所需要软件
推荐安装Anaconda3+Pycharm,安装教程->最新版Pycharm与Anaconda详细安装教程——小白入手可操作版
- Anaconda3安装 : Anaconda由于是国外网站下载较慢,推荐通过清华镜像源安装。清华园下载链接。选后缀“…Windows…exe ”字样下载。建议使用Anaconda发行版,便于环境管理和依赖包安装
- 集成开发坏境(IDE)安装 : 推荐使用PyCharm,如果使用VSCode,VSCode 需安装Python扩展和Qt Tools插件。且PyCharm Professional版提供完整的PyQt5开发支持。PyCharm下载入口
3.2 创建虚拟环境
打开Anaconda prompt终端,默认进入的是(base)环境,创建虚拟环境是为了隔离项目依赖,避免包版本冲突和环境混乱。

3.2.1 使用conda搭建
- 默认路径(默认C盘)
# 创建虚拟环境
conda create --name myenv python=3.11
# 激活
conda activate myenv
# 停用
conda deactivate
}
- 创建的环境到自定义路径(其他盘符)
conda create -p /your/custom/path/my_custom_env python=3.11
让我详细解释这条命令的每个部分:
- conda create:这是 Conda 创建新环境的核心命令
- -p /your/custom/path/my_custom_env:这是关键部分!
-p标志表示指定完整路径(而不是使用默认位置)/your/custom/path/替换为你想要的实际路径,例如 /home/username/my_project/envs/my_custom_env是你给环境起的名称 - python=3.11:指定要安装的 Python 版本(这里以 3.11 为例,可根据需要调整)
注意事项
- 确保Python版本在3.8以上
- 如果有GPU,建议安装CUDA版本的PyTorch
- 如果安装过程中出现冲突,可以尝试创建新的虚拟环境
3.3 安装Python所依赖第三方包
创建一个requirements.txt文件,用于列出 Python 项目所依赖的所有第三方包及其具体版本。所有依赖包如下:建议使用pip安装
# requirements.txt
annotated-types==0.7.0
anyio==4.10.0
argon2-cffi==25.1.0
argon2-cffi-bindings==25.1.0
arrow==1.3.0
asttokens==3.0.0
async-lru==2.0.5
attrs==25.3.0
babel==2.17.0
beautifulsoup4==4.13.4
bleach==6.2.0
blinker==1.9.0
certifi==2025.1.31
cffi==1.17.1
charset-normalizer==3.4.1
click==8.1.8
colorama==0.4.6
coloredlogs==15.0.1
comm==0.2.3
contourpy==1.3.2
cryptography==40.0.2
cycler==0.12.1
debugpy==1.8.16
decorator==5.2.1
defusedxml==0.7.1
executing==2.2.0
fastjsonschema==2.21.2
filelock==3.18.0
Flask==3.0.3
flatbuffers==25.2.10
fonttools==4.58.2
fqdn==1.5.1
fsspec==2024.6.1
gdown==5.2.0
h11==0.16.0
httpcore==1.0.9
httpx==0.28.1
humanfriendly==10.0
idna==3.10
imageio==2.37.0
imgviz==1.7.6
ipykernel==6.30.1
ipython==9.4.0
ipython_pygments_lexers==1.1.1
ipywidgets==8.1.7
isoduration==20.11.0
itsdangerous==2.2.0
jedi==0.19.2
Jinja2==3.1.4
json5==0.12.1
jsonpointer==3.0.0
jsonschema==4.25.1
jsonschema-specifications==2025.4.1
jupyter==1.1.1
jupyter-console==6.6.3
jupyter-events==0.12.0
jupyter-lsp==2.2.6
jupyter_client==8.6.3
jupyter_core==5.8.1
jupyter_server==2.16.0
jupyter_server_terminals==0.5.3
jupyterlab==4.4.6
jupyterlab_pygments==0.3.0
jupyterlab_server==2.27.3
jupyterlab_widgets==3.0.15
kiwisolver==1.4.8
labelImg==1.8.6
lark==1.2.2
lazy_loader==0.4
loguru==0.7.3
lxml==6.0.0
MarkupSafe==3.0.2
matplotlib==3.10.3
matplotlib-inline==0.1.7
mistune==3.1.3
mpmath==1.3.0
natsort==8.4.0
nbclient==0.10.2
nbconvert==7.16.6
nbformat==5.10.4
nest-asyncio==1.6.0
networkx==3.5
notebook==7.4.5
notebook_shim==0.2.4
numpy==2.2.6
onnxruntime==1.22.0
opencv-python==4.12.0.88
osam==0.2.3
overrides==7.7.0
packaging==25.0
pandas==2.3.1
pandocfilters==1.5.1
parso==0.8.4
pillow==11.2.1
platformdirs==4.3.8
prometheus_client==0.22.1
prompt_toolkit==3.0.51
protobuf==6.31.1
psutil==7.0.0
pure_eval==0.2.3
py-cpuinfo==9.0.0
pycparser==2.22
pydantic==2.11.5
pydantic_core==2.33.2
Pygments==2.19.2
pyparsing==3.2.3
PyQt5==5.15.11
PyQt5-Qt5==5.15.2
PyQt5_sip==12.17.0
pyreadline3==3.5.4
PySocks==1.7.1
python-dateutil==2.9.0.post0
python-json-logger==3.3.0
pytz==2025.2
pywin32==311
pywinpty==3.0.0
PyYAML==6.0.2
pyzmq==27.0.1
referencing==0.36.2
requests==2.32.5
rfc3339-validator==0.1.4
rfc3986-validator==0.1.1
rfc3987-syntax==1.1.0
rpds-py==0.27.0
scikit-image==0.25.2
scipy==1.15.3
Send2Trash==1.8.3
setuptools==78.1.1
six==1.17.0
sniffio==1.3.1
soupsieve==2.7
stack-data==0.6.3
sympy==1.13.3
terminado==0.18.1
tifffile==2025.6.1
tinycss2==1.4.0
#torch==2.8.0+cu128
torch==2.8.0
torchvision==0.23.0
tornado==6.5.2
tqdm==4.67.1
traitlets==5.14.3
types-python-dateutil==2.9.0.20250809
typing-inspection==0.4.1
typing_extensions==4.14.0
tzdata==2025.2
ultralytics==8.3.180
ultralytics-thop==2.0.15
uri-template==1.3.0
urllib3==1.26.15
wcwidth==0.2.13
webcolors==24.11.1
webencodings==0.5.1
websocket-client==1.8.0
Werkzeug==3.1.3
wheel==0.45.1
widgetsnbextension==4.0.14
win32_setctime==1.2.0
}
注意:
- 出现ERROR: No matching distribution found for torch==2.8.0+cu128等是因为python版本不对!
- 根据电脑有无有英伟达显卡,来选择安装“torch库”

3.3.1 另外安装torch库
- 安装pytorch(GPU版)
打开命令行界面输入conda activate …进入自己创建的虚拟环境,之后输入下方命令即可安装pytorch,耐心等待安装完成
pip install torch==2.0.0+cu128 torchvision==0.15.1+cu128 --extra-index-url https://download.pytorch.org/whl/cu128
- 安装pytorch(CPU版)
有英伟达显卡的按照上述流程安装后即可跳过本部分,无英伟达显卡则需要按照下述方法进行,
pip install torch==2.0.0 torchvision==0.15.1 torchaudio==2.0.1 --index-url https://download.pytorch.org/whl/cpu
3.4 安装ultralytics库
YOLO11(ultralytics)源码获取官网:https://github.com/ultralytics/ultralytics。也可以去网盘获取。获取到进行安装。
pip install ultralytics
4. 数据集准备与划分
将你的原始图像数据按以下结构存放,也可以网上找大佬归纳好的数据集,比如:东北大学钢材表面缺陷数据集
dataset_org/
├── images/ # 存放所有图片文件
│ ├── image1.jpg
│ ├── image2.jpg
│ └── ...
└── labels/ # 存放对应的标注文件
├── image1.txt
├── image2.txt
└── ...
4.1 划分数据集代码详解
# split_dataset.py - 数据集划分脚本
import os
import shutil
import random
# 🎯 需要修改的部分开始
# 设置划分比例:训练集70%,验证集20%,测试集10%
split_rate = [0.7, 0.2, 0.1]
split_names = ["train", "valid", "test"]
# 🎯 修改为你的原始数据集路径
image_folder = r"E:\yolop\train\images" # 修改为你的图片文件夹路径
label_folder = r"E:\yolop\train\labels" # 修改为你的标签文件夹路径
# 是否打乱数据顺序(建议设为True)
shuffle = True
# 🎯 需要修改的部分结束
def replace_expand_name(file_name, ex_name):
"""替换文件扩展名"""
return ".".join(file_name.split(".")[:-1] + [ex_name])
# 创建新的数据集目录
if os.path.exists("dataset"):
shutil.rmtree("dataset") # 删除已存在的dataset文件夹
os.makedirs("dataset")
# 创建子目录结构
for name in split_names:
os.makedirs(os.path.join("dataset", name, "images"))
os.makedirs(os.path.join("dataset", name, "labels"))
# 获取所有图片文件
image_files = os.listdir(image_folder)
if shuffle:
random.shuffle(image_files) # 随机打乱顺序
# 生成对应的标签文件名
label_files = [replace_expand_name(name, 'txt') for name in image_files]
def write_files(image_files, label_files, split):
"""将文件复制到对应的分割目录"""
for image_file, label_file in zip(image_files, label_files):
# 复制图片文件
shutil.copy(
os.path.join(image_folder, image_file),
os.path.join("dataset", split, "images", image_file)
)
# 复制标签文件
shutil.copy(
os.path.join(label_folder, label_file),
os.path.join("dataset", split, "labels", label_file)
)
# 计算各分割集的数量
data_len = len(image_files)
train_count = int(split_rate[0] * data_len)
valid_count = int(split_rate[1] * data_len)
# 执行文件划分和复制
write_files(image_files[:train_count], label_files[:train_count], split_names[0]) # 训练集
write_files(image_files[train_count:train_count+valid_count],
label_files[train_count:train_count+valid_count], split_names[1]) # 验证集
write_files(image_files[train_count+valid_count:],
label_files[train_count+valid_count:], split_names[2]) # 测试集
print(f"数据集划分完成!总共 {data_len} 个样本")
print(f"训练集: {train_count} 个样本")
print(f"验证集: {valid_count} 个样本")
print(f"测试集: {data_len - train_count - valid_count} 个样本")
运行说明:
- 修改 image_folder和 label_folder路径为你的实际路径
- 运行脚本:python split_dataset.py
- 脚本会自动创建 dataset文件夹并完成数据划分
5. 创建数据配置文件
创建 data.yaml文件,告诉YOLO数据集的位置和类别信息:
# data.yaml - 数据配置文件
# 🎯 需要修改的路径部分
train: F:\FZ\yolop\dataset\train\images # 修改为你的训练集路径
val: F:\FZ\yolop\dataset\valid\images # 修改为你的验证集路径
test: F:\FZ\yolop\dataset\test\images # 修改为你的测试集路径
# 类别数量(根据你的数据集修改)
nc: 6
# 类别名称(根据你的数据集修改) #以钢材缺陷“六种缺陷类型”为例
names: ['crazing', 'inclusion', 'patches', 'pitted_surface', 'rolled-in_scale', 'scratches']
重要说明
- 路径使用正斜杠 /或双反斜杠 \
- nc必须与你的类别数量一致
- names列表中的顺序必须与标注文件中的类别ID对应
6. 模型训练
6.1 YOLOv11训练代码
# train.py
from ultralytics import YOLO
if __name__ == "__main__":
# 🎯 模型选择:根据硬件条件选择合适的模型
# yolo11n.pt - 轻量级(适合低配置)
# yolo11m.pt - 中量级(平衡精度和速度)
# yolo11l.pt - 重量级(高精度,需要大显存)
model = YOLO(r"weights\yolov11\yolo11m.pt") # 修改为你的预训练模型路径
# 🎯 训练参数配置
model.train(
data="data.yaml",
epochs=300,
batch=8,
imgsz=640,
workers=2,
device=0,
# device='cpu',
patience=50,
lr0=0.01,
lrf=0.01,
momentum=0.937,
weight_decay=0.0005,
warmup_epochs=3.0,
warmup_momentum=0.8,
box=7.5,
cls=0.5,
dfl=1.5,
)
- 基础数据与目标设置
- data=”data.yaml”:指定数据集配置文件 data.yaml的路径。该文件定义了训练集、验证集的路径、类别数量及名称。
- epochs=300:设置训练总共要遍历整个数据集的轮数为300轮。
- batch=8:设置每批输入到模型的图片数量为8。较大的批次可能加速训练但需要更多显存。
- imgsz=640:将输入图像统一缩放或填充至 640x640 像素。
- workers=2:设置数据加载的子进程数为2,用于在后台预读取下一批数据,提高数据加载效率。
- device=0:指定使用第1块GPU进行训练。如果使用CPU,则需将其注释掉,并启用下一行 device=’cpu’。
- 优化器与学习率策略
- patience=50:早停机制的耐心值。如果验证集指标在连续50个epoch内没有改善,则提前终止训练以防止过拟合。
- lr0=0.01:初始学习率,是优化器调整模型参数步长的起点。
- lrf=0.01:最终学习率衰减系数。训练结束时的学习率将为 lr0 * lrf = 0.0001。这是一个余弦退火策略。
- momentum=0.937:优化器的动量参数,帮助加速梯度下降并在正确方向上前进,避免震荡。
- weight_decay=0.0005:权重衰减系数,一种正则化手段,通过对大权值进行惩罚来防止模型过拟合。
- 训练策略
- warmup_epochs=3.0:学习率预热轮数。在前3个epoch,学习率将从0缓慢线性增加到lr0,这有助于训练初期稳定。
- warmup_momentum=0.8:预热阶段使用的动量值,预热结束后将变为momentum参数设定的值。
- 损失函数权重
这三个参数用于调整总损失函数中不同组成部分的权重,以平衡各项优化目标:
- box=7.5:边界框回归损失的权重。负责优化预测框的位置和大小。
- cls=0.5:分类损失的权重。负责优化模型对物体类别的预测。
- dfl=1.5:分布焦点损失的权重。这是YOLOv8/v11中用于改进边界框预测精度的一种损失。
6.1.1 参数调整指南:
| 参数 | 推荐值 | 说明 |
|---|---|---|
| batch | 4-16 | 根据显存调整,越大训练越快 |
| workers | 2-8 | 根据CPU核心数调整 |
| imgsz | 640 | 图像尺寸,越大精度越高但越慢 |
| epochs | 100-500 | 根据数据集大小调整 |
6.1.2 常见问题解决:
- 显存不足(OOM错误):减小 batch和 imgsz
- 训练速度慢:增加 workers,使用更小的模型
- 过拟合:减少 epochs,增加数据增强
6.1.3 官网预训练模型下载
YOLOv11针对不同的场景和应用提供了YOLOv11n、YOLOv11s等不同大小的模型,具体看官网提供的,按需要下载https://docs.ultralytics.com/zh/models/yolo11/#citations-and-acknowledgments
7. 模型评估与测试
创建一个evaluate.py文件,封装验证函数。
7.1 使用验证集评估
# evaluate_val.py - 使用验证集评估模型
from ultralytics import YOLO
if __name__ == "__main__":
# 🎯 修改为你的训练结果模型路径
# 路径格式:runs/detect/trainX/weights/best.pt
# 其中X是训练序号,根据实际训练结果修改
model_path = r"runs\detect\train2\weights\best.pt" # 修改为你的模型路径
# 加载训练好的模型
model = YOLO(model_path)
# 在验证集上评估
results = model.val(
data="data.yaml", # 数据配置文件
split="valid" # 使用验证集评估
)
# 打印评估结果
print("评估结果:")
print(f"mAP50: {results.box.map50:.3f}")
print(f"mAP50-95: {results.box.map:.3f}")
7.2 在测试集上进行预测
# evaluate_predict.py - 在测试集上进行预测
from ultralytics import YOLO
if __name__ == "__main__":
# 🎯 修改为你的训练结果模型路径
model_path = r"runs\detect\train7\weights\best.pt" # 修改为你的模型路径
# 🎯 修改为测试集图片路径
test_images_path = r"dataset\test\images" # 修改为你的测试集路径
# 加载训练好的模型
model = YOLO(model_path)
# 进行预测并保存结果
results = model.predict(
source=test_images_path,
save=True, # 保存预测结果图像
conf=0.25, # 置信度阈值
iou=0.45, # IOU阈值
show_labels=True, # 显示标签
show_conf=True, # 显示置信度
imgsz=640 # 推理尺寸
)
print("预测完成!结果保存在 runs/detect/predict 目录")
7.3 训练结果评估
在训练YOLOv11模型时,我们主要通过观察三类损失曲线(box_loss, cls_loss, dfl_loss)的下降趋势来监控学习过程。训练完成后,所有输出成果均会系统保存在runs/目录下。如图所示,该目录不仅包含最终的模型权重(weights/)和训练配置(args.yaml),还自动生成了评估图表(如F1曲线、混淆矩阵)以及直观的训练批次(train_batch*)和验证批次(val_batch*)样本图像,便于全面复盘模型性能与训练状态。

F1-置信度曲线:展示了模型综合性能(F1分数)随置信度阈值变化的趋势。其峰值(如图中0.74)对应的置信度常被选为最佳阈值,用以平衡精确率与召回率。精确率-置信度曲线:反映了模型预测结果的可靠性。曲线越高,代表在该置信度阈值下,模型判断为“缺陷”的预测越准确。当曲线接近1时,表明预测结果几乎无误。精确率-召回率曲线:揭示了模型精确率与召回率之间的整体权衡关系。曲线越靠近右上方,性能越好;其下方的面积(mAP)是衡量模型平均精度的核心指标。召回率-置信度曲线:体现了模型发现所有真实缺陷的能力。阈值越低,召回率通常越高(如图中最高达0.89)。此曲线帮助确定在确保尽可能不漏检时所需的阈值上限。
7.3.1 损失函数(Loss Curves)和性能指标(Performance Metrics)函数

- 这张图是判断模型训练是否正常、收敛是否良好、以及最终性能优劣的直接依据。理想的图表表现为所有损失曲线平滑收敛,而所有精度/召回率/mAP曲线则稳步上升至一个较高的水平。
7.4 结果展示

结语
至此,我们完成了基于YOLOv11的“钢材表面缺陷检测为例“从数据到部署的全流程实践。整个过程不仅涵盖了模型训练、损失监控与性能评估的核心技术环节,更展现了AI为传统工业质检带来的精准与效率提升。
【获取源码包方式】
关注我的CSDN博客,在本文评论区留言,或私信我,我会将GitHub仓库链接或网盘链接发送给你。
更多推荐


所有评论(0)