在 PyTorch 中使用 YOLOv5

YOLO是“你只看一次”的首字母缩写,是一种开源软件工具,用于实时检测给定图像中的物体的有效功能。YOLO 算法使用卷积神经网络 (CNN) 模型来检测图像中的对象。 

该算法只需要通过给定神经网络进行一次前向传播即可检测图像中的所有对象。这使得 YOLO 算法在速度上比其他算法更具优势,使其成为迄今为止最著名的检测算法之一。

什么是 YOLO 对象检测?

对象检测算法是一种能够检测给定帧中某些对象或形状的算法。例如,简单的检测算法可能能够检测和识别图像中的形状,例如圆形或正方形,而更高级的检测算法可以检测更复杂的物体,例如人、自行车、汽车等。

YOLO 算法不仅通过其单前向传播功能提供高检测速度和性能,而且还以极高的准确度和精度检测它们。

在本教程中,我们将重点介绍 YOLOv5,它是 YOLO 软件的第五个也是最新版本。它最初于 2020 年 5 月 18 日发布。YOLO开源代码可以在 GitHub上找到。我们将YOLO与著名的PyTorch库一起使用。 

PyTorch 是一个深度学习开源包,基于著名的 Torch 库。它也是一个基于 Python 的库,更常用于自然语言处理和计算机视觉。

YOLO 算法如何工作?

第 1 步:残余块(将图像分成更小的网格状框)

在此步骤中,整个(整个)框架被分成较小的框或网格。

所有网格都绘制在原始图像上,共享确切的形状和大小。这些划分背后的想法是,每个网格框将检测其中的不同对象。

Residual Box Image

步骤 2:边界框回归(标识边界框内的对象)

在图像中检测到给定对象后,在其周围绘制一个边界框。边界框具有 中心点、高度、宽度和类(检测到的对象类型)等参数。

Detection of Car Inside a Bounding Box Image

IOU并集相交的缩写,用于计算模型的准确性。这是通过量化两个框的交集度来实现的:实值框(图像中的红色框)和从结果返回的框(图像中的蓝色框)。 

在本文的教程部分,我们将 IOU 值确定为 40%,这意味着如果两个框的交点低于 40%,则不应考虑此预测。这样做是为了帮助我们计算预测的准确性。

下图显示了 YOLO 检测算法的完整过程

3 Steps Working Together

有关 YOLO 算法工作原理的其他信息,请查看 YOLO 算法简介。 

我们试图通过我们的模型实现什么?

本教程中示例的主要目标是使用 YOLO 算法检测给定图像中的胸部疾病列表。与任何机器学习模型一样,我们将使用数千张胸部扫描图像来运行我们的模型。目标是让 YOLO 算法成功检测给定图像中的所有病变。 

数据集

本教程中使用的 VinBigData 512 图像数据集 可以在 Kaggle 上找到。数据集分为两部分:训练数据集和测试数据集。训练数据集包含 15,000 张图像,而测试数据集包含 3,000 张图像。训练和测试之间的这种数据划分在某种程度上是最佳的,因为训练数据集通常是测试数据集大小的 4 到 5 倍contentstack.io/v3/assets/blt71da4c740e00faaa/blt34437cddedeb95eb/6359ac9fe63a425d5dc5b4b0/EXX-Blog-pytorch-yolo5-tutorial-6.png“ src=”http://www.cheeli.com.cn/wp-content/uploads/2022/12/EXX-Blog-pytorch-yolo5-tutorial-6.png“ style=”width: 687px;”/>

数据集的另一部分包含所有图像的标签。在这个数据集中,每个图像都标有类名(发现的胸部疾病),以及类ID,图像的宽度和高度等。检查下图以查看所有可用的列。 

Example Image of Textual Data Set

YOLOv5 教程

注意:您可以在 Kaggle 上查看 此示例中使用的原始代码 。

步骤 1:导入必要的库

首先,我们将在代码的最开头导入所需的库和包。首先,让我们解释一下我们刚刚导入的一些更常见的库。NumPy是一个开源的数字Python库,允许用户创建矩阵并对其执行许多数学运算。

 

import pandas as pd
import os
import numpy as np
import shutil
import ast
from sklearn import model_selection
from tqdm import tqdm
import wandb
from sklearn.model_selection import GroupKFold\
from IPython.display import Image, clear_output  # to display images
from os import listdir
from os.path import isfile
from glob import glob
import yaml
# clear_output()

第 2 步:定义我们的路径

为了使我们的生活更轻松,我们将首先定义训练和测试数据集的标签和图像的直接路径。 

 
TRAIN_LABELS_PATH = './vinbigdata/labels/train' VAL_LABELS_PATH = './vinbigdata/labels/val' TRAIN_IMAGES_PATH = './vinbigdata/images/train' #12000 VAL_IMAGES_PATH = './vinbigdata/images/val' #3000 External_DIR = '../input/vinbigdata-512-image-dataset/vinbigdata/train' # 15000 os.makedirs(TRAIN_LABELS_PATH, exist_ok = True) os.makedirs(VAL_LABELS_PATH, exist_ok = True) os.makedirs(TRAIN_IMAGES_PATH, exist_ok = True) os.makedirs(VAL_IMAGES_PATH, exist_ok = True) size = 51

步骤 3:导入和读取文本数据集

在这里,我们将导入并读取文本数据集。此数据存储为 CSV 文件格式的行和列。

 

df = pd.read_csv('../input/vinbigdata-512-image-dataset/vinbigdata/train.csv')
df.head()

注意:df.head() 函数打印给定数据集的前 5 行。 

步骤 4:筛选和清理数据集

由于没有数据集是完美的,大多数时候,过滤过程是优化数据集所必需的,从而优化我们模型的性能。在此步骤中,我们将删除类 id 等于 14 的任何行。 

此类 ID 代表在疾病类别中没有发现。我们放弃这个类的原因是它可能会混淆我们的模型。此外,它会减慢速度,因为我们的数据集会稍微大一些。

 
df = df[df.class_id!=14].reset_index(drop = True)

步骤 5:计算 YOLO 边界框的坐标

如前面的 “YOLO 算法如何工作”部分 (特别是步骤 1 和 2)中所述,YOLO 算法希望数据集采用特定格式。在这里,我们将遍历数据帧并应用一些转换。 

以下代码的最终目标是计算每个数据点的新 x-mid、y-mid、宽度和高度维度apply(lambda 行:(row.x_min)/行.width,轴 = 1)*浮点(大小)
df[‘y_min’] = df.apply(lambda row: (row.y_min)/row.height, axis = 1)*float(size)
df[‘x_max’] = df.apply(lambda row: (row.x_max)/row.width, axis =1)*float(size)
df[‘y_max’] = df.apply(lambda row: (row.y_max)/row.height, axis =1)*float(size)

df[‘x_mid’] = df.apply(lambda row: (row.x_max+row.x_min)/2, axis =1)
df[‘y_mid’] = df.apply(lambda row: (row.y_max+row.y_min)/2, axis =1)

df[‘w’] = df.apply(lambda row: (row.x_max-row.x_min), axis =1)
df[‘h’] = df.apply(lambda row: (row.y_max-row.y_min), axis =1)

df[‘x_mid’] /= float(size)
df[‘y_mid’] /= float(size)

df[‘w’] /= float(size)
df[‘h’] /= float(size)“ data-lang=”“>

df['x_min'] = df.apply(lambda row: (row.x_min)/row.width, axis = 1)*float(size)
df['y_min'] = df.apply(lambda row: (row.y_min)/row.height, axis = 1)*float(size)
df['x_max'] = df.apply(lambda row: (row.x_max)/row.width, axis =1)*float(size)
df['y_max'] = df.apply(lambda row: (row.y_max)/row.height, axis =1)*float(size)

df['x_mid'] = df.apply(lambda row: (row.x_max+row.x_min)/2, axis =1)
df['y_mid'] = df.apply(lambda row: (row.y_max+row.y_min)/2, axis =1)

df['w'] = df.apply(lambda row: (row.x_max-row.x_min), axis =1)
df['h'] = df.apply(lambda row: (row.y_max-row.y_min), axis =1)

df['x_mid'] /= float(size)
df['y_mid'] /= float(size)

df['w'] /= float(size)
df['h'] /= float(size)

步骤 6:更改提供的数据格式

在代码的这一部分中,我们将数据集中所有行的给定数据格式更改为以下列;<类> <x_center> <y_center> <宽度> <高度>。这是必要的,因为 YOLOv5 算法只能读取此特定格式的数据。 

 

# <class> <x_center> <y_center> <width> <height>
def preproccess_data(df, labels_path, images_path):
    for column, row in tqdm(df


        属性 = np.array(属性)
        np.savetxt(os.path.join(labels_path, f“{row[‘image_id’]}.txt”),
                   [属性], fmt = [‘%d’, ‘%f’, ‘%f’, ‘%f’, ‘%f’])
        shutil.copy(os.path.join(’/kaggle/input/vinbigdata-512-image-dataset/vinbigdata/train’, f“{row[‘image_id’]}.png”),images_path)

然后,我们将运行 preproccess_data 函数两次,一次使用训练数据集及其图像,第二次使用测试数据集及其图像。

 

preproccess_data(df, TRAIN_LABELS_PATH, TRAIN_IMAGES_PATH)
preproccess_data(val_df, VAL_LABELS_PATH, VAL_IMAGES_PATH)

使用下面的行,我们将 YOLOv5 算法克隆到我们的模型中。

 
!git clone https://github.com/ultralytics/yolov5.git

步骤 7:定义模型的类

在这里,我们将模型中可用的 14 种胸部疾病定义为类。这些是可以在数据集图像中识别的实际疾病。

 
classes = [ 'Aortic enlargement',             'Atelectasis',             'Calcification',             'Cardiomegaly',             'Consolidation',             'ILD',             'Infiltration',             'Lung Opacity',             'Nodule/Mass',             'Other lesion',             'Pleural effusion',             'Pleural thickening',             'Pneumothorax',             'Pulmonary fibrosis'] data = dict(     train =  '../vinbigdata/images/train',     val   =  '../vinbigdata/images/val',     nc    = 14,     names = classes     ) with open('./yolov5/vinbigdata.yaml', 'w') as outfile:     yaml.dump(data, outfile, default_flow_style=False) f = open('./yolov5/vinbigdata.yaml', 'r') print('\nyaml:') print(f.read())

步骤 8:训练模型

首先,我们将打开 YOLOv5 目录。然后我们将使用 pip 来安装编写在需求文件中的所有库。 

需求文件包含代码库工作所需的所有必需库。我们还将安装其他库,如pycotools,seaborn和pandas。 

 

%cd ./yolov5
!pip install -U -r requirements.txt
!pip install pycocotools>=2.0 seaborn>=0.11.0 pandas thop
clear_output()

Wandb是权重和偏差的缩写,允许我们监控给定的神经网络模型login()“ data-lang=”“>

# b39dd18eed49a73a53fccd7b684ea7ecaed75b08
wandb.login()

现在我们将在提供 100 个 epoch 的 vinbigdata 集上训练 YOLOv5。我们还将传递一些其他标志,例如 –img 512,它告诉模型我们的图像大小为 512 像素,–batch 16 将允许我们的模型每批拍摄 16 张图像。使用 –data ./vinbigdata.yaml 标志,我们将传递我们的数据集,即 vinbigdata.yaml 数据集。

 
!python train.py --img 512 --batch 16 --epochs 100 --data ./vinbigdata.yaml --cfg models/yolov5x.yaml --weights yolov5x.pt --cache --name vin

步骤 9:评估模型

首先,我们将确定测试数据集目录以及权重目录。

 

test_dir = f'/kaggle/input/vinbigdata-{size}-image-dataset/vinbigdata/test'
weights_dir = './runs/train/vin3/weights/best.pt'
os.listdir('./runs/train/vin3/weights')

在这一部分中,我们将使用 detect.py 作为我们的推断来检查预测的准确性。我们还将传递一些标志,例如 –conf 0.15\,这是模型的置信阈值。如果检测到的对象的置信率低于 15%,请将其从我们的输出中删除。–iou 0.4\ 标志通知我们的模型,如果两个盒子并集的交点低于 40%,则应将其删除。

 

!python detect.py --weights $weights_dir\
--img 512\
--conf 0.15\
--iou 0.4\
--source $test_dir\
--save-txt --save-conf --exist-ok

关于在 PyTorch 中使用 YOLOv5 的最终想法

在本文中,我们解释了什么是 YOLOv5 以及基本的 YOLO 算法是如何工作的。接下来,我们继续简要解释 PyTorch 

最后,我们向您介绍了一个机器学习模型,该模型能够在 X 射线图像中检测胸部疾病。在本例中,我们使用 YOLO 作为主要检测算法来查找和定位胸部病变。然后,我们将每个病变分类为给定的类别或疾病。

如果您对机器学习和构建自己的模型感兴趣,尤其是需要检测给定图像或视频表示中的多个对象的模型,那么 YOLOv5 绝对值得一试。

Comments are closed.