日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

【目标检测】yolo系列:从yolov1到yolov5之YOLOv1详解及复现

發布時間:2023/11/27 生活经验 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【目标检测】yolo系列:从yolov1到yolov5之YOLOv1详解及复现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

檢測器通常能夠被分為兩類,一類是two-stage檢測器,最具代表的為faster R-CNN;另一類是one-stage檢測器,包括YOLO,SSD等。一般來說,two-stage檢測器具有高定位和識別準確性,而one-stage則有速度上的優勢。其在結構上的區別就是two-stage檢測器有一個生成region proposal的步驟,然后對其進行預測和分類;而one-stage則是直接對預測框進行回歸和分類預測。

一階段(one-stage)目標檢測算法直接將目標邊界定位問題轉化為回歸問題來處理。對圖像的多層特征圖進行均勻密集采樣,使用CNN網絡提取特征,然后直接進行分類和回歸。

YOLO系列是典型的目標檢測one-stage模型。本系列文章主要介紹從 YOLO v1發展到YOLO v5的改進和主要設計思路,并且會用教程的方式講述每一個YOLO模型。

YOLO v1(2015)

Redmon等人提出的 YOLO(You Only Look Once)算法,將目標檢測作為回歸問題解決,將候選區和檢測兩個階段合二為一。

下面講詳細說明yolo v1。

yolov1解決的需求

  1. 能夠檢測出圖中的多個大小不同的目標

通俗地講,就是用分類的算法設計了一個檢測器,YOLO的作者的思路如下:分類器輸出是一個one-hot vector,那將檢測器的輸出轉換成(c, x, y, w, h),c表示confidence置信度,把問題轉化成一個回歸問題,直接回歸出Bounding Box的位置。

主要的思路就是用一個(c,x,y,w,h)去負責image某個區域的目標。比如說圖片設置為16個區域,每個區域用1個(c,x,y,w,h)去負責,就可以一次輸出16個框,每個框是1個(c,x,y,w,h)。
所以,現在的模型是
img→cbrp16→cbrp32→cbrp64→cbrp128→...→fc256?fc[5]→c,x,y,w,himg \rightarrow cbrp16 \rightarrow cbrp32 \rightarrow cbrp64 \rightarrow cbrp128 \rightarrow ... \\ \rightarrow fc256-fc[5] \rightarrow c,x,y,w,h imgcbrp16cbrp32cbrp64cbrp128...fc256?fc[5]c,x,y,w,h

  1. 能夠檢測多類的目標

如果目標特別密集的情況下,只預測一個類別 的目標肯定不夠用,所以將預測出的輸出加上一個類別概率值,即C,則是某個目標框框出來的物體屬于其中一個類別的概率,C是一個one-hot vector,長度為類別的數目。

現在的模型是:
img→cbrp16→cbrp32→cbrp64→cbrp128→...→fc256?fc[5+C]?S?S→[c,x,y,w,h,one?hot]?S?Simg \rightarrow cbrp16 \rightarrow cbrp32 \rightarrow cbrp64 \rightarrow cbrp128 \rightarrow \\ ... \rightarrow fc256-fc[5+C]*S*S \\ \rightarrow [c,x,y,w,h,one-hot]*S*S imgcbrp16cbrp32cbrp64cbrp128...fc256?fc[5+C]?S?S[c,x,y,w,h,one?hot]?S?S

  1. 檢測小目標

小目標總是檢測不佳,所以我們專門設計神經元去擬合小目標。
對于每個區域,我們用2個五元組(c,x,y,w,h),一個負責回歸大目標,一個負責回歸小目標,同樣添加one-hot vector,one-hot就是[0,1],[1,0]這樣子,來表示目標框框出來的屬于哪一類。

yolo v1的詳細思路

總體思路

yolo v1 將一張圖片分為S × S個網格,每個網格負責預測中心點落在此網格內的目標,每個網格通過卷積,提取成一個特征向量,然后用這個特征向量去預測目標框。每個網格會預測B 個bounding box,C 個類別概率值每個bounding box預測5個值(x, y , w, h, confidence) ,如下圖所示,一張圖片的預測結果有[S×S×(5?B+C)]個值。

下圖是論文中的圖:

YOLO v1其實就是劃分成了7*7個區域,預測49個目標,分了20個類別。

網絡結構

Yolov1的整個網絡先使用卷積層進行特征提取,再通過全連接層進行分類和回歸。構思來自GoogleNet,網絡由24層卷積+2層全連接層組成。在3×3的卷積后面加上1×1卷積來降低feature map的空間大小,從而較少網絡的參數和計算量。使用PASCAL VOC 數據集來評估模型,所以網絡的最后輸出為7×7×30=1470。

模型訓練

網絡的訓練分為2部分:
(1)預訓練一個分類網絡:使用上述網絡的前20個卷積層+average-pool+全連接層在ImageNet進行訓練,網絡輸入為(224×224×3)。
(2)訓練檢測網絡:移除預訓練網絡中的后兩層,再在預訓練網絡的基礎上+4層卷積層+2層全連接層,將網絡的輸入變為(448×448×3)。

在神經網絡結構確定之后,訓練效果好壞,由Loss函數和優化器決定。Yolo v1使用普通的梯度下降法作為優化器。Yolo v1使用的Loss函數如下:


一個網格中會預測多個bbox,在訓練時,只選擇IOU最大的那個bbox來負責預測目標,其他bbox的Pr(Object)值被設為0,使得bbox的預測更加專業,提高整體的recall。

模型預測

1. 使用非極大抑制生成預測框

在預測的時候,格點與格點并不會沖突,但是在預測一些大物體或者鄰近物體時,會有多個格點預測了同一個物體。此時采用非極大抑制(NMS),一個目標可能有多個預測框,通過NMS可以過濾掉一些多余的預測框,確保一個目標只有一個預測框。NMS是通過類別置信度來篩選的。

2. 推理時將 p?cp*cp?c 作為輸出置信度

在推理時,使用物體的類別預測最大值 p 乘以 預測框的最大值 c ,作為輸出預測物體的置信度。

首先從所有的預測框中找到置信度最大的那個bbox,然后挨個計算其與剩余bbox的IOU,如果其值大于一定閾值(重合度過高),那么就將該剩余bbox剔除;然后對剩余的預測框重復上述過程,直到處理完所有的檢測框
這樣也可以過濾掉一些大部分重疊的矩形框。輸出檢測物體的置信度,同時考慮了矩形框與類別,滿足閾值的輸出更加可信。

yolo v1存在的問題

  • yolo v1每個網格只能預測一個類別,讓所有同一個網格預測出來的多個框屬于一個類別,所以對于相鄰目標的預測效果不好。(這個問題從yolo v2后就已經解決)
  • 沒有計算背景的geo_loss,只計算了前景的geo_loss,樣本不均衡問題依然存在。
  • 小目標預測效果不好

完整代碼如下:
https://github.com/abeardear/pytorch-YOLO-v1

yolov1源碼復現

數據集準備

選用voc2012+2007 數據集,可以提前下載,如需使用自己的數據集,請參考數據集格式。

  • 下載voc2012的訓練數據集
  • 下載voc2007的測試數據集
  • 將所有圖片放在一個文件夾中,
  • 對數據集進行預處理。
    (1)xml_2_txt.py 將xml標注轉換為txt文件(應該將xml_2_txt.py放在voc數據集的同一文件夾中,或者在 xml_2_txt.py 中更改標注文件的路徑)
    (2)dataset預處理數據集,txt描述文件,image_name.jpg x y w h c x y w h c 這樣就是說一張圖片中有兩個目標

依賴庫

  • pytorch
  • opencv
  • visdom
  • tqdm

模型訓練驗證

運行 train.py文件,file_root修改成自己訓練集的文件所在位置。

import os
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
import torch
import torch.nn as nn
from torch.utils.data import DataLoader
import torchvision.transforms as transforms
from torchvision import models
from torch.autograd import Variablefrom net import vgg16, vgg16_bn
from resnet_yolo import resnet50, resnet18
from yoloLoss import yoloLoss
from dataset import yoloDatasetfrom visualize import Visualizer
import numpy as npuse_gpu = torch.cuda.is_available()file_root = '/home/xzh/data/VOCdevkit/VOC2012/allimgs/'learning_rate = 0.001
num_epochs = 50
batch_size = 24
use_resnet = True
if use_resnet:net = resnet50()
else:net = vgg16_bn()
# net.classifier = nn.Sequential(
#             nn.Linear(512 * 7 * 7, 4096),
#             nn.ReLU(True),
#             nn.Dropout(),
#             #nn.Linear(4096, 4096),
#             #nn.ReLU(True),
#             #nn.Dropout(),
#             nn.Linear(4096, 1470),
#         )
#net = resnet18(pretrained=True)
#net.fc = nn.Linear(512,1470)
# initial Linear
# for m in net.modules():
#     if isinstance(m, nn.Linear):
#         m.weight.data.normal_(0, 0.01)
#         m.bias.data.zero_()
print(net)
#net.load_state_dict(torch.load('yolo.pth'))
print('load pre-trined model')
if use_resnet:resnet = models.resnet50(pretrained=True)new_state_dict = resnet.state_dict()dd = net.state_dict()for k in new_state_dict.keys():print(k)if k in dd.keys() and not k.startswith('fc'):print('yes')dd[k] = new_state_dict[k]net.load_state_dict(dd)
else:vgg = models.vgg16_bn(pretrained=True)new_state_dict = vgg.state_dict()dd = net.state_dict()for k in new_state_dict.keys():print(k)if k in dd.keys() and k.startswith('features'):print('yes')dd[k] = new_state_dict[k]net.load_state_dict(dd)
if False:net.load_state_dict(torch.load('best.pth'))
print('cuda', torch.cuda.current_device(), torch.cuda.device_count())criterion = yoloLoss(7,2,5,0.5)
if use_gpu:net.cuda()net.train()
# different learning rate
params=[]
params_dict = dict(net.named_parameters())
for key,value in params_dict.items():if key.startswith('features'):params += [{'params':[value],'lr':learning_rate*1}]else:params += [{'params':[value],'lr':learning_rate}]
optimizer = torch.optim.SGD(params, lr=learning_rate, momentum=0.9, weight_decay=5e-4)
# optimizer = torch.optim.Adam(net.parameters(),lr=learning_rate,weight_decay=1e-4)# train_dataset = yoloDataset(root=file_root,list_file=['voc12_trainval.txt','voc07_trainval.txt'],train=True,transform = [transforms.ToTensor()] )
train_dataset = yoloDataset(root=file_root,list_file=['voc2012.txt','voc2007.txt'],train=True,transform = [transforms.ToTensor()] )
train_loader = DataLoader(train_dataset,batch_size=batch_size,shuffle=True,num_workers=4)
# test_dataset = yoloDataset(root=file_root,list_file='voc07_test.txt',train=False,transform = [transforms.ToTensor()] )
test_dataset = yoloDataset(root=file_root,list_file='voc2007test.txt',train=False,transform = [transforms.ToTensor()] )
test_loader = DataLoader(test_dataset,batch_size=batch_size,shuffle=False,num_workers=4)
print('the dataset has %d images' % (len(train_dataset)))
print('the batch_size is %d' % (batch_size))
logfile = open('log.txt', 'w')num_iter = 0
vis = Visualizer(env='xiong')
best_test_loss = np.inffor epoch in range(num_epochs):net.train()# if epoch == 1:#     learning_rate = 0.0005# if epoch == 2:#     learning_rate = 0.00075# if epoch == 3:#     learning_rate = 0.001if epoch == 30:learning_rate=0.0001if epoch == 40:learning_rate=0.00001# optimizer = torch.optim.SGD(net.parameters(),lr=learning_rate*0.1,momentum=0.9,weight_decay=1e-4)for param_group in optimizer.param_groups:param_group['lr'] = learning_rateprint('\n\nStarting epoch %d / %d' % (epoch + 1, num_epochs))print('Learning Rate for this epoch: {}'.format(learning_rate))total_loss = 0.for i,(images,target) in enumerate(train_loader):images = Variable(images)target = Variable(target)if use_gpu:images,target = images.cuda(),target.cuda()pred = net(images)loss = criterion(pred,target)total_loss += loss.data[0]optimizer.zero_grad()loss.backward()optimizer.step()if (i+1) % 5 == 0:print ('Epoch [%d/%d], Iter [%d/%d] Loss: %.4f, average_loss: %.4f' %(epoch+1, num_epochs, i+1, len(train_loader), loss.data[0], total_loss / (i+1)))num_iter += 1vis.plot_train_val(loss_train=total_loss/(i+1))#validationvalidation_loss = 0.0net.eval()for i,(images,target) in enumerate(test_loader):images = Variable(images,volatile=True)target = Variable(target,volatile=True)if use_gpu:images,target = images.cuda(),target.cuda()pred = net(images)loss = criterion(pred,target)validation_loss += loss.data[0]validation_loss /= len(test_loader)vis.plot_train_val(loss_val=validation_loss)if best_test_loss > validation_loss:best_test_loss = validation_lossprint('get best test loss %.5f' % best_test_loss)torch.save(net.state_dict(),'best.pth')logfile.writelines(str(epoch) + '\t' + str(validation_loss) + '\n')  logfile.flush()      torch.save(net.state_dict(),'yolo.pth')

運行eval_voc.py 進行模型驗證,若模型表現效果不好,可以對train.py中對學習率等進行調整,也可以調整網絡結構,進行模型調優。

模型預測

運行predict.py,將訓練好并調好參數的最優模型傳入其中,進行預測。
結果如圖所示。

總結

以上是生活随笔為你收集整理的【目标检测】yolo系列:从yolov1到yolov5之YOLOv1详解及复现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。