Advertisement

365天深度学习训练营-第P8周:YOLOv5-C3模块实现

阅读量:

我的环境:

  • 开发语言:Python 版本号为 3.11.x
  • 开发工具:PyCharm 社区版版本号为 2022 年第 3 季度
  • 深度学习框架版本信息:PyTorch 版本号为 2.x;OpenCV torch vision 版本号为 0.x.x.x

本次目标**:**

  • 了解C3模块

该模块在YOLOv5网络中扮演着关键角色,并主要功能在于提升网络深度并增强特征提取能力。

具体来说,在YOLOv5-C3模块中包含三个Conv层(分别是Conv1、 Conv2 和 Conv3)以及一个瓶颈层构成的整体架构上,则能够被系统地划分为四个主要组成部分。

  • Conv1:第一层卷积模块对该输入特征图执行一次卷积操作。该过程可采用任意尺寸的卷积核但根据设计建议使用1×1尺寸以实现降维或升维功能这对于特征提取至关重要。
  • Bottleneck:作为第二个核心模块该设计包含两个关键组件:首先经过一个(1×1)卷积层将特征图通道数减半;随后通过一个(3×3)卷积层将通道数增加一倍。这种结构既能显著提升网络的感受野又能有效降低计算开销。
  • Conv2 和 Conv3:其作用与第一层类似具体而言其中 Conv2 使用步长为 1 的卷积层进行操作而 Conv3 则采用步长为 2 的设计以进一步扩大感受野从而优化特征提取效果。

在每一对Conv模块之间增加了BN层并搭配了LeakyReLU激活函数,并为了增强模型的稳定性和泛化能力。

该模块主要承担多尺度特征融合技术和跨通道信息传递机制所承担的核心功能,在此基础之上显著提升了特征图的表达能力,并进一步优化了YOLOv5模型的整体性能与识别精度

一、前期准备

将数据集导入。

复制代码
 import torch

    
 import torch.nn as nn
    
 from torchvision import transforms,datasets
    
 from torchvision.models import vgg16
    
 import PIL,pathlib
    
 from torchinfo import summary
    
 import matplotlib.pyplot as plt
    
  
    
 data_path='F:\ weather\ weather_photos'
    
 data_path=pathlib.Path(data_path)
    
 data_paths = list(data_path.glob('*'))
    
 classNames = [str(path).split('\ ')[2] 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]
    
     )
    
 ])
    
  
    
 total_data =datasets.ImageFolder(data_path, transform=train_transforms)
    
 print(total_data)
    
 print(total_data.class_to_idx)
    
  
    
 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_dataset,test_dataset)
    
 print(train_size,test_size)
    
  
    
 batch_size = 32
    
 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)

二、构建C3模块

复制代码
 def autopad(k, p=None):

    
     if p is None:
    
     p = k // 2 if isinstance(k, int) else [x // 2 for x in k]  # auto-pad
    
     return p
    
  
    
  
    
 class Conv(nn.Module):
    
     def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True):  # ch_in, ch_out, kernel, stride, padding, groups
    
     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):  # ch_in, ch_out, shortcut, groups, expansion
    
     super().__init__()
    
     c_ = int(c2 * e)  # hidden channels
    
     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 model_K(nn.Module):
    
     def __init__(self):
    
     super(model_K, self).__init__()
    
  
    
     self.Conv = Conv(3, 32, 3, 2)
    
  
    
     self.C3_1 = C3(32, 64, 3, 2)
    
  
    
     self.classifier = nn.Sequential(
    
         nn.Linear(in_features=802816, out_features=100),
    
         nn.ReLU(),
    
         nn.Linear(in_features=100, out_features=4)
    
     )
    
  
    
     def forward(self, x):
    
     x = self.Conv(x)
    
     x = self.C3_1(x)
    
     x = torch.flatten(x, start_dim=1)
    
     x = self.classifier(x)
    
  
    
     return x
    
  
    
  
    
 model = model_K().to("cpu")
    
 summary(model)

构建C3组成的模块,并将其整合。

三、训练模型

**** 设置超参数。

复制代码
 loss_fn = nn.CrossEntropyLoss()

    
 learn_rate = 1e-3
    
 opt = torch.optim.SGD(model.parameters(),lr=learn_rate)

编写训练函数和测试函数。

复制代码
 def train(dataloader,model,loss_fn,optimizer):

    
     size = len(dataloader.dataset)
    
     num_batchs = len(dataloader)
    
     train_loss, train_acc = 0, 0
    
     for X,y in dataloader:
    
     pred=model(X)
    
     loss=loss_fn(pred,y)
    
  
    
     optimizer.zero_grad()
    
     loss.backward()
    
     optimizer.step()
    
  
    
     train_acc+=(pred.argmax(1)==y).type(torch.float).sum().item()
    
     train_loss+=loss.item()
    
     train_acc /= size
    
     train_loss /= num_batchs
    
  
    
     return train_acc,train_loss
    
  
    
 def test(dataloader,model,loss_fn):
    
     size=len(dataloader.dataset)
    
     num_batchs=len(dataloader)
    
     test_loss,test_acc=0,0
    
  
    
     with torch.no_grad():
    
     for imgs,target in dataloader:
    
  
    
         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_batchs
    
  
    
     return test_acc,test_loss

正式训练。

复制代码
 epochs=20

    
 train_loss=[]
    
 train_acc=[]
    
 test_loss=[]
    
 test_acc=[]
    
  
    
 for epoch in range(epochs):
    
     model.train()
    
     epoch_train_acc,epoch_train_loss= train(train_dl,model,loss_fn,opt)
    
     model.eval()
    
     epoch_test_acc,epoch_test_loss=test(test_dl,model, loss_fn)
    
     train_acc.append(epoch_train_acc)
    
     train_loss.append(epoch_train_loss)
    
     test_acc.append(epoch_test_acc)
    
     test_loss.append(epoch_test_loss)
    
  
    
     template = ('Epoch:{:2d},Train_acc:{:.1f}%,Train_loss:{:.3f},Test_acc:{:.1f}%,Test_loss:{:.3f}')
    
     print(template.format(epoch+1,epoch_train_acc,epoch_train_loss,epoch_test_acc,epoch_test_loss))
    
 print('Done')

四、结果可视化

复制代码
 epochs_range = range(epochs)

    
  
    
 plt.figure(figsize=(12,3))
    
 plt.subplot(1,2,1)
    
 plt.plot(epochs_range,train_acc,label='Training Accuracy')
    
 plt.plot(epochs_range,test_acc,label='Test Accuracy')
    
 plt.legend(loc='lower right')
    
 plt.title('Training and Validation Accuracy')
    
  
    
 plt.subplot(1,2,2)
    
 plt.plot(epochs_range,train_loss,label='Training Loss')
    
 plt.plot(epochs_range,test_loss,label='Validation Loss')
    
 plt.legend(loc='upper right')
    
 plt.title('Training and Validation Loss')
    
 plt.show()

五、指定图片进行预测

复制代码
 classes = list(total_data.class_to_idx)

    
 def predict_one_img(image_path, model, transform, classes):
    
     test_img = PIL.Image.open(image_path).convert('RGB')
    
     test_img=transform(test_img)
    
     img = test_img.to('cpu').unsqueeze(0)
    
     model.eval()
    
     output = model(img)
    
     x,pred = torch.max(output,1)
    
     pred_class=classes[pred]
    
     print(f'预测结果是{pred_class}')
    
 predict_one_img(image_path='F:\ weather_photos\ cloudy\ cloudy1.jpg',model=model,transform=train_transforms,classes=classes)

保存模型参数

复制代码
 PATH = './model.pth'

    
 torch.save(model.state_dict(),PATH)
    
  
    
 model.load_state_dict(torch.load(PATH))

全部评论 (0)

还没有任何评论哟~