Pytorch入门实战 P09-YOLOv5里面的Backbone模块搭建网络

news2024/11/24 17:52:37

目录

1、YOLOv5的模型图。

2、BackBone简单介绍。

3、YOLOv5的Backbone文件。

4、YOLOv5Backbone的code部分

5、完整的code部分

6、结果展示

(1)Adam优化器

(2)SGD优化器


  • 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
  • 🍖 原作者:K同学啊 | 接辅导、项目定制

这周的这篇博客,主要是使用YOLOv5里面的Backbone模块,搭建网络。

我们先来看下YOLOv5的Backbone部分。

1、YOLOv5的模型图。

(图片来源于网络)

上图中,最左侧的事YOLOv5里面的BackBone,上篇博文,主要讲的是YOLOv5里面的BackBone里面的C3模块。

这篇文章,我们主要看YOLOv5里面的BackBone部分,即:YOLOv5的骨干网络。

2、BackBone简单介绍。

YOLOv5 模型主要由 Backbone、Neck 和Head 三部分组成,网络模型(如上图所示)。

①Backbone 主要负责对输入图像进行特征提取
②Neck 负责对特征图进行多尺度特征融合,并把这些特征传递给预测层。
③Head 进行最终的回归预测

YOLOv5的骨干网络(Backbone)是其整体架构中至关重要的部分,主要负责从输入图像中提取丰富的特征信息。以下是关于YOLOv5骨干网络的详细说明:

骨干网络采用自下而上的路径从原始图像中提取特征。输入图像经过一系列的卷积、批量归一化和激活函数处理后,得到不同尺度的特征图。这些特征图不仅包含了丰富的细节信息,还具备了一定的语义信息,为后续的目标检测任务提供了有力的支持。

YOLOv5的骨干网络采用了BottleNeckCSP结构,这是一种特殊设计的残差网络结构

(1)该结构由Focus结构、三组CBL+CSP1_x 和 CBL+SPP串行搭建而成。(如下图)

(2)其中,(如下图)。CBL(Convolutional Block)由卷积(Conv)、批量归一化(BN)和激活函数(Leaky ReLU)组成。(也可叫CBS,因为S的话取得是Silu激活函数,L的话,直接取激活函数Leaky,这俩都是可以的,)


(3)(如下图)CSP1_x则借鉴了CSPNet网络结构,由CBL/CBS模块、Res unit模块以及卷积层Concat组成,其中x表示有x个CSP1模块。

(4)随着网络层数的加深,特征图的分辨率逐渐降低。浅层特征图感受野比较小,尺寸比较大,包含更多的细节和位置信息;而深层特征图尺寸比较小,感受野比较大,反映了图像的全局和抽象特征,包含更丰富的语义信息。

3、YOLOv5的Backbone文件。

4、YOLOv5Backbone的code部分

class YOLOv5_backbone(nn.Module):
    def __init__(self):
        super(YOLOv5_backbone, self).__init__()

        self.Conv_1 = Conv(3, 64, 3, 2, 2)
        self.Conv_2 = Conv(64, 128, 3, 2)
        self.C3_3 = C3(128, 128)
        self.Conv_4 = Conv(128, 256, 3, 2)
        self.C3_5 = C3(256, 256)
        self.Conv_6 = Conv(256, 512, 3, 2)
        self.C3_7 = C3(512, 512)
        self.Conv_8 = Conv(512, 1024, 3, 2)
        self.C3_9 = C3(1024, 1024)
        self.SPPF = SPPF(1024, 1024, 5)

        # 全连接网络层,用于分类
        self.classifier = nn.Sequential(
            nn.Linear(in_features=65536, out_features=100),
            nn.ReLU(),
            nn.Linear(in_features=100, out_features=4)
        )

    def forward(self, x):
        x = self.Conv_1(x)
        x = self.Conv_2(x)
        x = self.C3_3(x)
        x = self.Conv_4(x)
        x = self.C3_5(x)
        x = self.Conv_6(x)
        x = self.C3_7(x)
        x = self.Conv_8(x)
        x = self.C3_9(x)
        x = self.SPPF(x)

        x = torch.flatten(x, start_dim=1)
        x = self.classifier(x)

        return x
def autopad(k, p=None):
    if p is None:
        p = k // 2 if isinstance(k, int) else [x // 2 for x in k]
    return p
class Conv(nn.Module):
    def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True):
        super().__init__()
        self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False)
        self.bn = nn.BatchNorm2d(c2)
        self.act = nn.SiLU() if act is True else (act if isinstance(act, nn.Module) else nn.Identity())

    def forward(self, x):
        return self.act(self.bn(self.conv(x)))
class Bottleneck(nn.Module):
    def __init__(self, c1, c2, shortcut=True, g=1, e=0.5):
        super().__init__()
        c_ = int(c2 * e)
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c_, c2, 3, 1, g=g)
        self.add = shortcut and c1 == c2

    def forward(self, x):
        return x + self.cv2(self.cv1(x)) if self.add else self.cv2(self.cv1(x))
class C3(nn.Module):
    def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):  # ch_in, ch_out, number, shortcut, groups, expansion
        super().__init__()
        c_ = int(c2 * e)  # hidden channels
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c1, c_, 1, 1)
        self.cv3 = Conv(2 * c_, c2, 1)  # act=FReLU(c2)
        self.m = nn.Sequential(*(Bottleneck(c_, c_, shortcut, g, e=1.0) for _ in range(n)))

    def forward(self, x):
        return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), dim=1))
class SPPF(nn.Module):
    # Spatial Pyramid Pooling - Fast (SPPF) layer for YOLOv5 by Glenn Jocher
    def __init__(self, c1, c2, k=5):  # equivalent to SPP(k=(5, 9, 13))
        super().__init__()
        c_ = c1 // 2  # hidden channels
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c_ * 4, c2, 1, 1)
        self.m = nn.MaxPool2d(kernel_size=k, stride=1, padding=k // 2)

    def forward(self, x):
        x = self.cv1(x)
        with warnings.catch_warnings():
            warnings.simplefilter('ignore')  # suppress torch 1.9.0 max_pool2d() warning
            y1 = self.m(x)
            y2 = self.m(y1)
            return self.cv2(torch.cat([x, y1, y2, self.m(y2)], 1))

 

5、完整的code部分

import copy
import pathlib
import warnings

import matplotlib.pyplot as plt
import torch
from torch import nn
from torchvision import datasets
from torchvision.transforms import transforms
import matplotlib as mpl
mpl.use('Agg')  # 在服务器上运行的时候,打开注释

'''

    实现YOLOv5的 Backbone模块
'''
# 设置准备
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(device)

# 导入数据
data_dir = './weather_photos'
data_dir = pathlib.Path(data_dir)

data_paths = list(data_dir.glob('*'))
classNames = [str(path).split('/')[1] for path in data_paths]
print(classNames)

# 图像预处理
train_transforms = transforms.Compose([
    transforms.Resize([224, 224]),
    transforms.ToTensor(),
    transforms.Normalize(
        mean=[0.485, 0.456, 0.406],
        std=[0.229, 0.224, 0.225]
    )
])

test_transforms = transforms.Compose([
    transforms.Resize([224, 224]),
    transforms.ToTensor(),
    transforms.Normalize(
        mean=[0.485, 0.456, 0.406],
        std=[0.229, 0.224, 0.225]
    )
])
total_data = datasets.ImageFolder('./weather_photos', transform=train_transforms)

# 划分数据集
train_size = int(0.8*len(total_data))
test_size = len(total_data) - train_size
train_dataset, test_dataset = torch.utils.data.random_split(total_data, [train_size,test_size])
print(train_size, test_size)  # 900 225

# 加载数据集
batch_size = 4
train_dl = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_dl = torch.utils.data.DataLoader(test_dataset, batch_size=batch_size, shuffle=True)
for X, y in test_dl:
    print('Shape of X[N, C, H, W]', X.shape)  # torch.Size([4, 3, 224, 224])
    print('Shape of y', y.shape, y.dtype)  # torch.Size([4]) torch.int64
    break

# 搭建网络模型 (包含Backbone模块的模型)
def autopad(k, p=None):
    if p is None:
        p = k // 2 if isinstance(k, int) else [x // 2 for x in k]
    return p


class Conv(nn.Module):
    def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True):
        super().__init__()
        self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False)
        self.bn = nn.BatchNorm2d(c2)
        self.act = nn.SiLU() if act is True else (act if isinstance(act, nn.Module) else nn.Identity())

    def forward(self, x):
        return self.act(self.bn(self.conv(x)))


class Bottleneck(nn.Module):
    def __init__(self, c1, c2, shortcut=True, g=1, e=0.5):
        super().__init__()
        c_ = int(c2 * e)
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c_, c2, 3, 1, g=g)
        self.add = shortcut and c1 == c2

    def forward(self, x):
        return x + self.cv2(self.cv1(x)) if self.add else self.cv2(self.cv1(x))


class C3(nn.Module):
    def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):  # ch_in, ch_out, number, shortcut, groups, expansion
        super().__init__()
        c_ = int(c2 * e)  # hidden channels
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c1, c_, 1, 1)
        self.cv3 = Conv(2 * c_, c2, 1)  # act=FReLU(c2)
        self.m = nn.Sequential(*(Bottleneck(c_, c_, shortcut, g, e=1.0) for _ in range(n)))

    def forward(self, x):
        return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), dim=1))


class SPPF(nn.Module):
    # Spatial Pyramid Pooling - Fast (SPPF) layer for YOLOv5 by Glenn Jocher
    def __init__(self, c1, c2, k=5):  # equivalent to SPP(k=(5, 9, 13))
        super().__init__()
        c_ = c1 // 2  # hidden channels
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c_ * 4, c2, 1, 1)
        self.m = nn.MaxPool2d(kernel_size=k, stride=1, padding=k // 2)

    def forward(self, x):
        x = self.cv1(x)
        with warnings.catch_warnings():
            warnings.simplefilter('ignore')  # suppress torch 1.9.0 max_pool2d() warning
            y1 = self.m(x)
            y2 = self.m(y1)
            return self.cv2(torch.cat([x, y1, y2, self.m(y2)], 1))


class YOLOv5_backbone(nn.Module):
    def __init__(self):
        super(YOLOv5_backbone, self).__init__()

        self.Conv_1 = Conv(3, 64, 3, 2, 2)
        self.Conv_2 = Conv(64, 128, 3, 2)
        self.C3_3 = C3(128, 128)
        self.Conv_4 = Conv(128, 256, 3, 2)
        self.C3_5 = C3(256, 256)
        self.Conv_6 = Conv(256, 512, 3, 2)
        self.C3_7 = C3(512, 512)
        self.Conv_8 = Conv(512, 1024, 3, 2)
        self.C3_9 = C3(1024, 1024)
        self.SPPF = SPPF(1024, 1024, 5)

        # 全连接网络层,用于分类
        self.classifier = nn.Sequential(
            nn.Linear(in_features=65536, out_features=100),
            nn.ReLU(),
            nn.Linear(in_features=100, out_features=4)
        )

    def forward(self, x):
        x = self.Conv_1(x)
        x = self.Conv_2(x)
        x = self.C3_3(x)
        x = self.Conv_4(x)
        x = self.C3_5(x)
        x = self.Conv_6(x)
        x = self.C3_7(x)
        x = self.Conv_8(x)
        x = self.C3_9(x)
        x = self.SPPF(x)

        x = torch.flatten(x, start_dim=1)
        x = self.classifier(x)

        return x


model = YOLOv5_backbone().to(device)
print(model)


# 编写训练函数
def train(dataloader, model, loss_fn, optimizer):
    size = len(dataloader.dataset)  # 训练集大小
    num_batches = len(dataloader)  # 批次数目,size/batch_size 向上取整
    train_loss, train_acc = 0, 0

    for X, y in dataloader:
        X, y = X.to(device), y.to(device)

        # 计算预测误差
        pred = model(X)
        loss = loss_fn(pred, y)

        # 反向传播
        optimizer.zero_grad()  # grad属性归零
        loss.backward()    # 反向传播
        optimizer.step()    # 每一步自动更新

        # 记录acc与loss
        train_acc += (pred.argmax(1) == y).type(torch.float).sum().item()
        train_loss += loss.item()

    train_acc /= size
    train_loss /= num_batches
    return train_acc, train_loss


# 编写测试函数
def test(dataloader, model, loss_fn):
    size = len(dataloader.dataset)
    num_batches = len(dataloader)
    test_loss, test_acc = 0, 0

    # 当不进行训练时,停止梯度更新,节省计算内存消耗
    with torch.no_grad():
        for imgs, target in dataloader:
            imgs, target = imgs.to(device), target.to(device)

            # 计算loss
            target_pred = model(imgs)
            loss = loss_fn(target_pred, target)

            test_loss += loss.item()
            test_acc += (target_pred.argmax(1) == target).type(torch.float).sum().item()
    test_acc /= size
    test_loss /= num_batches

    return test_acc, test_loss



# 正式训练
optimizer = torch.optim.Adam(model.parameters(), lr=1e-4)
loss_fn = nn.CrossEntropyLoss()   # 创建损失函数
epochs = 60
train_loss = []
train_acc = []
test_loss = []
test_acc = []
best_acc = 0  # 设置一个最佳准确率,作为最佳模型的判别指标

for epoch in range(epochs):
    model.train()
    epoch_train_acc, epoch_train_loss = train(train_dl, model, loss_fn, optimizer)

    model.eval()
    epoch_test_acc, epoch_test_loss = test(test_dl, model, loss_fn)

    # 保存最佳模型到best_model
    if epoch_test_acc > best_acc:
        best_acc = epoch_test_acc
        best_model = copy.deepcopy(model)

    train_acc.append(epoch_train_acc)
    train_loss.append(epoch_train_loss)
    test_acc.append(epoch_test_acc)
    test_loss.append(epoch_test_loss)

    # 获得当前学习率
    lr = optimizer.state_dict()['param_groups'][0]['lr']

    template = 'Epoch:{:2d}, Train_acc:{:.1f}%, Train_loss:{:.3f} ,===,Test_acc:{:.1f}%, Test_loss:{:.3f}, Lr:{:.2E}'
    print(template.format(epoch + 1, epoch_train_acc*100, epoch_train_loss, epoch_test_acc*100, epoch_test_loss, lr))

# 保存最佳模型到文件中
PATH = './best_model.pth'
torch.save(best_model.state_dict(), PATH)
print('Done!!')


# 结果可视化
warnings.filterwarnings('ignore')
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
plt.rcParams['figure.dpi'] = 100  # 分辨率
epochs_range = range(epochs)

plt.figure(figsize=(12, 3))

plt.subplot(1,2,1)
plt.plot(epochs_range, train_acc, label="Train Accuracy")
plt.plot(epochs_range, test_acc, label='Test Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Acc')

plt.subplot(1,2,2)
plt.plot(epochs_range, train_loss, label="Train Loss")
plt.plot(epochs_range, test_loss, label='Test Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')

plt.savefig("/data/jupyter/deep_demo/p09_v5_backbone/resultImg.jpg")  # 保存图片在服务器的位置
plt.show()



# 模型评估
best_model.load_state_dict(torch.load(PATH, map_location=device))
epoch_test_acc, epoch_test_loss = test(test_dl, best_model, loss_fn)

print(f'epoch_test_acc:{epoch_test_acc}, epoch_test_loss:{epoch_test_loss}')

6、结果展示

(1)Adam优化器

(2)SGD优化器

7、总结

 使用不同优化器,对于模型的精确度也是不一样的。

看YOLOv5源码的时候,可以先看.yaml文件,看下Backbone部分→Head部分。

看下总体的模型提,再去细看里面的代码。

收获还是很多的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1647699.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

羊大师解析,鲜为人知的羊奶冷知识

羊大师解析,鲜为人知的羊奶冷知识 羊奶的脂肪球更小:相较于牛奶,羊奶中的脂肪球直径更小,这有助于其更快地被人体消化和吸收。 羊奶含有更多的中链脂肪酸:羊奶中含有较多的中链脂肪酸(MCT)&am…

WiFine通信与Wi-sun通信对比

调制速率 WiFine通信:(G)FSK 50Kbps~500Kbps ;LoRa 5Kbps~37.5Kbps Wi-Sun通信:(G)FSK 50Kbps~300Kbps ;QPSK/OFDM 计划中… 2、协议简介 WiFine通信:为低成本、低功耗、移动设备倾力打造 的轻量级、分布式无线移动…

Stateflow基础知识笔记

01--Simulink/Stateflow概述 Stateflow是集成于Simulink中的图形化设计与开发工具,主要 用于针对控制系统中的复杂控制逻辑进行建模与仿真,或者说, Stateflow适用于针对事件响应系统进行建模与仿真。 Stateflow必须与Simulink联合使用&#…

阿赵UE引擎C++编程学习笔记——HelloWorld

大家好,我是阿赵。   从这一篇开始学习虚幻引擎的C编程。   学习所有编程好像都应该从HelloWorld开始,所以我这里也不例外。不过为了能打印出HelloWorld,需要做的事情还不少。不过到了能打印出HelloWorld的时候,我感觉学习的过…

使用DxTex.exe工具处理DDS图片

一.DxTex.exe DDS文件:基于Direct3D引擎的纹理图片格式。 DxTex.exe:基于Direct3D引擎开发的DDS文件处理工具,文件分辨率修改,文件minmap修改。 DxTex.exe路径:Utilities\bin\x64\DxTex.exe 二.修改分辨率 Format-Resize Texture 三.修改mipmap Format-Change Surface Format

专业的保密网文件导入导出系统,让文件流转行为更可控安全

军工单位因其涉及国防安全和军事机密,对保密工作有极高的要求,通常会采取严格的网络隔离措施来保护敏感信息和提高网络安全性。常见的方式是通过物理隔离将网络彻底分隔开来,比如保密网和非保密网。网络隔离后,仍有数据交换的需求…

VALSE 2024年度进展评述内容分享-世界模型增强下的自动驾驶

2024年视觉与学习青年学者研讨会(VALSE 2024)于5月5日到7日在重庆悦来国际会议中心举行。本公众号将全方位地对会议的热点进行报道,方便广大读者跟踪和了解人工智能的前沿理论和技术。欢迎广大读者对文章进行关注、阅读和转发。文章是对报告人…

【kali换源之后签名无效,报错处理】

#一、问题:报错信息# 错误:1 http://mirrors.ustc.edu.cn/kali kali-rolling InRelease 错误:2 http://mirrors.tuna.tsinghua.edu.cn/kali kali-rolling InRelease 错误:3 http://dl.google.com/linux/chrome/deb stable InRelease 错误:4 http://mirrors.aliyu…

LeetCode509:斐波那契数(使用动态规划)

题目描述 斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是: F(0) 0,F(1) 1 F(n) F(n - 1) F(n - 2),其中 n > 1…

Web3 ETF软件系统的主要功能

下面是Web3 ETF系统软件的主要功能,这些功能共同构成了Web3 ETF系统软件的核心,使其能够有效地为投资者提供Web3技术相关的投资机会,同时确保合规性、安全性和透明度。北京木奇移动软件有限公司,专业的软件外包开发公司&#xff0…

Java性能优化(一):ArrayList还是LinkedList?

引言 集合作为一种存储数据的容器,是我们日常开发中使用最频繁的对象类型之一。JDK为开发者提供了一系列的集合类型,这些集合类型使用不同的数据结构来实现。因此,不同的集合类型,使用场景也不同。 很多同学在面试的时候&#x…

3个电脑录制视频技巧,新手也能轻松上手

在当今信息化时代,电脑录制视频已经成为人们日常工作和学习中的一项重要技能。无论是录制在线会议、教程讲解还是游戏直播,一款合适的录屏软件都至关重要。本文将介绍三种常见的电脑录制视频方法,为广大用户提供详细的操作步骤,满…

Python中的分布式爬虫系统Scrapy与分布式任务队列的结合

随着互联网的不断发展,网络爬虫在数据采集和信息挖掘中发挥着重要作用。然而,单机爬虫往往难以应对大规模数据抓取的需求,因此,构建分布式爬虫系统成为了一种必然选择。本文将介绍如何利用 Python 中的 Scrapy 框架和分布式任务队…

VALSE 2024主旨报告内容解析:以深度学习框架为牵引促进自主AI生态发展

2024年视觉与学习青年学者研讨会(VALSE 2024)于5月5日到7日在重庆悦来国际会议中心举行。本公众号将全方位地对会议的热点进行报道,方便广大读者跟踪和了解人工智能的前沿理论和技术。欢迎广大读者对文章进行关注、阅读和转发。文章是对报告人…

AngusTester安装Mock服务

一、介绍 Mock服务(AngusMockService) 提供了一个虚拟环境,让您能够模拟不同的接口响应、状态码和数据,快速生成并模拟您所依赖的API,使开发和测试先行,以实现更快的开发和更全面的测试,更早地交付稳定的产品或应用。…

Amazon Bedrock 托管 Llama 3 8B70B

Amazon Bedrock 托管 Llama 3 8B&70B,先来体验:(*实验环境账号有效期为1天,到期自动关停,请注意重要数据保护) https://dev.amazoncloud.cn/experience/cloudlab?id65fd86c7ca2a0d291be26068&visi…

AI烟雾监测识别摄像机:智能化安全防范的新利器

随着现代社会的不断发展,人们对于安全问题的关注日益增加,尤其是在日常生活和工作中,对火灾等意外事件的预防成为了一项重要任务。为了更好地应对火灾风险,近年来,AI烟雾监测识别摄像机应运而生,成为智能化…

[笔试训练](十四)

目录 040:乒乓球框 041:组队竞赛 042:删除最大数字的相邻分数 040:乒乓球框 乒乓球筐__牛客网 (nowcoder.com) 题目&#xff1a; 题解&#xff1a; 哈希简单查询 #include <iostream> #include <string> using namespace std; int main() {string s1, s2;w…

【rar技巧】如何制作rar分卷压缩?

一个rar压缩包体积太大了&#xff0c;想要将压缩包分为三个&#xff0c;该如何做到&#xff1f;其实很简单&#xff0c;方法就在我们经常使用的WinRAR当中。 我们先将压缩包内的文件解压出来&#xff0c;然后查看一下&#xff0c;然后打开WinRAR软件&#xff0c;找到文件&…

拼多多标准推广怎么玩

拼多多标准推广的玩法主要包括以下方面&#xff1a; 拼多多推广可以使用3an推客。3an推客&#xff08;CPS模式&#xff09;给商家提供的营销工具&#xff0c;由商家自主设置佣金比例&#xff0c;激励推广者去帮助商家推广商品链接&#xff0c;按最终有效交易金额支付佣金&…