日本无码免费高清在线|成人日本在线观看高清|A级片免费视频操逼欧美|全裸美女搞黄色大片网站|免费成人a片视频|久久无码福利成人激情久久|国产视频一二国产在线v|av女主播在线观看|五月激情影音先锋|亚洲一区天堂av

  • 手機(jī)站
  • 小程序

    汽車測(cè)試網(wǎng)

  • 公眾號(hào)
    • 汽車測(cè)試網(wǎng)

    • 在線課堂

    • 電車測(cè)試

使用YOLO V5訓(xùn)練自動(dòng)駕駛目標(biāo)檢測(cè)網(wǎng)絡(luò)

2020-07-29 23:41:20·  來源:智車科技  作者:william  
 
本文會(huì)詳細(xì)介紹YOLO V5的網(wǎng)絡(luò)結(jié)構(gòu)及組成模塊,并使用YOLO V5s在BDD100K自動(dòng)駕駛數(shù)據(jù)集上進(jìn)行遷移學(xué)習(xí),搭建屬于自己的自動(dòng)駕駛交通物體對(duì)象識(shí)別網(wǎng)絡(luò)。本文來源:
本文會(huì)詳細(xì)介紹YOLO V5的網(wǎng)絡(luò)結(jié)構(gòu)及組成模塊,并使用YOLO V5s在BDD100K自動(dòng)駕駛數(shù)據(jù)集上進(jìn)行遷移學(xué)習(xí),搭建屬于自己的自動(dòng)駕駛交通物體對(duì)象識(shí)別網(wǎng)絡(luò)。
本文來源:知乎-自動(dòng)駕駛?cè)珬9こ處?br />  
YOLO V5 網(wǎng)絡(luò)結(jié)構(gòu)分析及遷移學(xué)習(xí)應(yīng)用
 
前言:本文會(huì)詳細(xì)介紹YOLO V5的網(wǎng)絡(luò)結(jié)構(gòu)及組成模塊,并使用YOLO V5s在BDD100K自動(dòng)駕駛數(shù)據(jù)集上進(jìn)行遷移學(xué)習(xí),搭建屬于自己的自動(dòng)駕駛交通物體對(duì)象識(shí)別網(wǎng)絡(luò)。
YOLO 是一種快速緊湊的開源對(duì)象檢測(cè)模型,與其它網(wǎng)絡(luò)相比,同等尺寸下性能更強(qiáng),并且具有很不錯(cuò)的穩(wěn)定性,是第一個(gè)可以預(yù)測(cè)對(duì)象的類別和邊界框的端對(duì)端神經(jīng)網(wǎng)絡(luò)。YOLO 家族一直有著旺盛的生命力,從YOLO V1一直到”V5“,如今已經(jīng)延續(xù)五代,憑借著不斷的創(chuàng)新和完善,一直被計(jì)算機(jī)視覺工程師作為對(duì)象檢測(cè)的首選框架之一。
Ultralytics于5月27日發(fā)布了YOLOv5 的第一個(gè)正式版本,其性能與YOLO V4不相伯仲,是現(xiàn)今最先進(jìn)的對(duì)象檢測(cè)技術(shù)之一,并在推理速度上是目前最強(qiáng)。
我在前一篇文章:一文讀懂YOLO V5 與 YOLO V4介紹了YOLO V5和YOLO V4的原理,相似點(diǎn)及區(qū)別。
 
在本文章中,我會(huì)詳細(xì)介紹YOLO V5的網(wǎng)絡(luò)結(jié)構(gòu)及組成模塊,并使用YOLO V5s對(duì)BDD100K自動(dòng)駕駛數(shù)據(jù)集進(jìn)行遷移學(xué)習(xí),使得訓(xùn)練出的模型能夠識(shí)別包括交通燈顏色在內(nèi)的所有交通對(duì)象。
本文分成兩塊:模型結(jié)構(gòu)及遷移學(xué)習(xí)。
  • Model architecture
  • Overview
  • Focus
  • BottleneckCSP
  • SPP
  • PANET
  • Transfer learning
  • Data prepration
  • Setup enviorment
  • Configuration
  • Modify model architecture
  • Transfer learning theory
  • Inference
Model architecture
YOLO網(wǎng)絡(luò)由三個(gè)主要組件組成:
1)Backbone:在不同圖像細(xì)粒度上聚合并形成圖像特征的卷積神經(jīng)網(wǎng)絡(luò)。
2)Neck:一系列混合和組合圖像特征的網(wǎng)絡(luò)層,并將圖像特征傳遞到預(yù)測(cè)層。
3)Head:對(duì)圖像特征進(jìn)行預(yù)測(cè),生成邊界框和并預(yù)測(cè)類別。
本文主要采用YOLO V5 1.0結(jié)構(gòu),7月23日作者更新了2.0版本代碼,對(duì)于模型定義做了些改變,我會(huì)后續(xù)進(jìn)行更新。
YOLO V5 1.0中用到的重要的模塊包括Focus,BottleneckCSP,SPP,PANET。模型的上采樣Upsample是采用nearst兩倍上采樣插值。值得注意的是YOLO V5 1.0最初為COCO數(shù)據(jù)集訓(xùn)練的Pretrained_model 使用的是FPN作為Neck,在6月22日后,Ultralytics已經(jīng)更新模型的Neck為PANET。網(wǎng)上很多的YOLO V5網(wǎng)絡(luò)結(jié)構(gòu)介紹都是基于FPN-NECK,本文的模型訓(xùn)練是基于PANET-NECK,下文中只介紹PANET-NECK。
對(duì)于YOLO V5,無論是V5s,V5m,V5l還是V5x其Backbone,Neck和Head一致。唯一的區(qū)別在與模型的深度和寬度設(shè)置,只需要修改這兩個(gè)參數(shù)就可以調(diào)整模型的網(wǎng)絡(luò)結(jié)構(gòu)。V5l 的參數(shù)是默認(rèn)參數(shù)。
  • depth multiple是用來控制模型的深度,例如V5s的深度是0.33,而V5l的深度是1,也就是說V5l的Bottleneck個(gè)數(shù)是V5s的3倍。
  • width_multiple是用來控制卷積核的個(gè)數(shù),V5s的寬度是0.5,而V5l的寬度是1,表示V5s的卷積核數(shù)量是默認(rèn)設(shè)置的一半,當(dāng)然你也可以設(shè)置到1.25倍,即V5x。例如下面YOLO V5的yaml文件中的backbone的第一層是 [[-1, 1, Focus, [64, 3]],而V5s的寬度是0.5,因此這一層實(shí)際上是[[-1, 1, Focus, [32, 3]]。
  • from列參數(shù):-1 代表是從上一層獲得的輸入,-2表示從上兩層獲得的輸入(head同理)。
  • number列參數(shù):1表示只有一個(gè),3表示有三個(gè)相同的模塊。
下圖為YOLO V5 1.0的網(wǎng)絡(luò)結(jié)構(gòu)圖(默認(rèn)對(duì)應(yīng)YOLO V5l),引用自Laughing-q。
下圖中存在三種括號(hào),其中 In_channel:輸入通道,out_channel:輸出通道,Kernel_size:卷積核大小,Stride:步長(zhǎng),x N代表此模塊的疊加次數(shù),方框外數(shù)字:depth x weight x height,默認(rèn)輸入為寬高為640x640的三通道圖像。
 
下文我將詳細(xì)講述Focus,BottleneckCSP,SPP,PANET這幾個(gè)重要模塊,由于本項(xiàng)目使用YOLO V5s網(wǎng)絡(luò)結(jié)構(gòu)訓(xùn)練模型,因此下文中的網(wǎng)絡(luò)圖及實(shí)例都基于YOLO V5s,并且輸入圖像為3x640x640。YOLO V5s默認(rèn)depth_multiple=0.33, width_multiple=0.50。即BottleneckCSP中Bottleneck的數(shù)量為默認(rèn)的1/3,而所有卷積操作的卷積核個(gè)數(shù)均為默認(rèn)的1/2。
Focus
下圖為YOLO V5s的Focus 隔行采樣拼接結(jié)構(gòu)。
 
YOLO V5默認(rèn)3x640x640的輸入,復(fù)制四份,然后通過切片操作將這個(gè)四個(gè)圖片切成了四個(gè)3x320x320的切片,接下來使用concat從深度上連接這四個(gè)切片,輸出為12x320x320,之后再通過卷積核數(shù)為32的卷積層,生成32x320x320的輸出,最后經(jīng)過batch_borm 和leaky_relu將結(jié)果輸入到下一個(gè)卷積層。
Focus的代碼分析如下:
class Focus(nn.Module):
# Focus wh information into c-space
def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True): # ch_in, ch_out, kernel, stride, padding, groups
super(Focus, self).__init__()
self.conv = Conv(c1 * 4, c2, k, s, p, g, act)
def forward(self, x): # x(b,c,w,h) -> y(b,4c,w/2,h/2)
return self.conv(torch.cat([x[..., ::2, ::2], x[..., 1::2, ::2], x[..., ::2, 1::2], x[..., 1::2, 1::2]], 1))
 
 
我們拿上圖舉例,F(xiàn)ocus是步長(zhǎng)為2的隔行采樣。
上圖第一張圖為原圖,第二張圖為Focus的特征圖,第三張圖為4x4的tensor代碼測(cè)試。
核心為這段代碼self.conv(torch.cat([x[..., ::2, ::2], x[..., 1::2, ::2], x[..., ::2, 1::2], x[..., 1::2, 1::2]], 1)) 。x[..., ::2, ::2]是黃色部分,x[..., 1::2, ::2],是紅色部分,以此類推。對(duì)于x[..., ::2, ::2]其中第一個(gè)參數(shù)“..."代表深度,也就是說三個(gè)通道都要切,第二個(gè)和第三個(gè)代表不論是寬和高都是每隔一個(gè)采樣。對(duì)于x[..., 1::2, ::2],1::2代表從列位置1開始,也就是每序號(hào)奇數(shù)列采樣。藍(lán)色,綠色的生成方式以此類推。最后用cat連接這些隔行采樣圖,生成通道數(shù)為12的特征圖。
BottlenneckCSP
下圖為YOLO V5s的第一個(gè)BottlenneckCSP結(jié)構(gòu)。
 
BottlenneckCSP分為兩部分,Bottlenneck以及CSP。
  • Bottlenneck
Bottlenneck其實(shí)就是經(jīng)典的殘差結(jié)構(gòu),先是1x1的卷積層(conv+batch_norm+leaky relu),然后再是3x3的卷積層,最后通過殘差結(jié)構(gòu)與初始輸入相加。
 
值得注意的是YOLO V5通過depth multiple控制模型的深度,例如V5s的深度是0.33,而V5l的深度是1,也就是說V5x的BottlenneckCSP中Bottleneck個(gè)數(shù)是V5s的3倍,模型中第一個(gè)BottlenneckCSP默認(rèn)Bottleneck個(gè)數(shù)x3,對(duì)于V5s只有上圖中的一個(gè)Bottleneck。
作者的代碼如下,值得注意的是e就是width_multiple,表示當(dāng)前操作卷積核個(gè)數(shù)占默認(rèn)個(gè)數(shù)的比例:
class Bottleneck(nn.Module):
# Standard bottleneck
def __init__(self, c1, c2, shortcut=True, g=1, e=0.5): # ch_in, ch_out, shortcut, groups, expansion
super(Bottleneck, self).__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 BottleneckCSP(nn.Module):
# CSP Bottleneck https://github.com/WongKinYiu/CrossStagePartialNetworks
def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion
super(BottleneckCSP, self).__init__()
c_ = int(c2 * e) # hidden channels
self.cv1 = Conv(c1, c_, 1, 1)
self.cv2 = nn.Conv2d(c1, c_, 1, 1, bias=False)
self.cv3 = nn.Conv2d(c_, c_, 1, 1, bias=False)
self.cv4 = Conv(2 * c_, c2, 1, 1)
self.bn = nn.BatchNorm2d(2 * c_) # applied to cat(cv2, cv3)
self.act = nn.LeakyReLU(0.1, inplace=True)
self.m = nn.Sequential(*[Bottleneck(c_, c_, shortcut, g, e=1.0) for _ in range(n)])
def forward(self, x):
y1 = self.cv3(self.m(self.cv1(x)))
y2 = self.cv2(x)
return self.cv4(self.act(self.bn(torch.cat((y1, y2), dim=1))))
  • CSP
下圖為YOLO V5s的CSP結(jié)構(gòu),也就是說將原輸入分成兩個(gè)分支,分別進(jìn)行卷積操作使得通道數(shù)減半,然后分支一進(jìn)行Bottlenneck x N操作,隨后concat分支一和分支二,從而使得BottlenneckCSP的輸入與輸出是一樣的大小,目的是為了讓模型學(xué)習(xí)到更多的特征。
 
很多人都對(duì)yaml文件中[[-1, 3, BottleneckCSP, [1024, False]]False的作用不太理解,其實(shí)這就是關(guān)閉了shortcut的選項(xiàng)。
def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5)
下圖是YOLO V5s 中BottlenneckCSP有無False選項(xiàng)的結(jié)構(gòu)對(duì)比:
 
SPP
下圖為YOLO V5s的SPP結(jié)構(gòu)。
 
SPP的輸入是512x20x20,經(jīng)過1x1的卷積層后輸出256x20x20,然后經(jīng)過并列的三個(gè)Maxpool進(jìn)行下采樣,將結(jié)果與其初始特征相加,輸出1024x20x20,最后用512的卷積核將其恢復(fù)到512x20x20。
作者代碼如下,重點(diǎn)是Maxpool操作:
class SPP(nn.Module):
# Spatial pyramid pooling layer used in YOLOv3-SPP
def __init__(self, c1, c2, k=(5, 9, 13)):
super(SPP, self).__init__()
c_ = c1 // 2 # hidden channels
self.cv1 = Conv(c1, c_, 1, 1)
self.cv2 = Conv(c_ * (len(k) + 1), c2, 1, 1)
self.m = nn.ModuleList([nn.MaxPool2d(kernel_size=x, stride=1, padding=x // 2) for x in k])
def forward(self, x):
x = self.cv1(x)
return self.cv2(torch.cat([x] + [m(x) for m in self.m], 1))
PANET
YOLO V5 1.0最初一版模型使用FPN作為NECK,后續(xù)在6月22號(hào)已經(jīng)全面更新為PANET。PANET基于 Mask R-CNN 和 FPN 框架,加強(qiáng)了信息傳播,具有準(zhǔn)確保留空間信息的能力,這有助于對(duì)像素進(jìn)行適當(dāng)?shù)亩ㄎ灰孕纬裳谀!?/div>
下圖中pi 代表 CSP 主干網(wǎng)絡(luò)中的一個(gè)特征層
 
該網(wǎng)絡(luò)的特征提取器采用了一種新的增強(qiáng)自下向上路徑的 FPN 結(jié)構(gòu),改善了低層特征的傳播(a部分)。第三條通路的每個(gè)階段都將前一階段的特征映射作為輸入,并用3x3卷積層處理它們。輸出通過橫向連接被添加到自上而下通路的同一階段特征圖中,這些特征圖為下一階段提供信息(b部分)。橫向連接,有助于縮短路徑,被稱為shortcut連接。同時(shí)使用自適應(yīng)特征池化(Adaptive feature pooling)恢復(fù)每個(gè)候選區(qū)域和所有特征層次之間被破壞的信息路徑,聚合每個(gè)特征層次上的每個(gè)候選區(qū)域,避免被任意分配(c部分)。對(duì)于 Mask-RCNN(e部分),F(xiàn)CN可以保留空間信息并減少網(wǎng)絡(luò)中的參數(shù)數(shù)量,但是由于參數(shù)是為所有空間位置共享的,因此該網(wǎng)路實(shí)際上并未學(xué)習(xí)如何使用像素位置進(jìn)行預(yù)測(cè)。而FC對(duì)位置敏感,可以適應(yīng)不同的空間位置。因此PANet使用來自Fully Convolutional Network (FCN)和Fully-connected layers(FC)的信息提供更準(zhǔn)確的掩碼預(yù)測(cè)。
YOLO V5借鑒了YOLO V4的修改版PANET結(jié)構(gòu)。
PANET通常使用自適應(yīng)特征池將相鄰層加在一起,以進(jìn)行掩模預(yù)測(cè)。但是,當(dāng)在YOLOv4中使用PANET時(shí),此方法略麻煩,因此,YOLO V4的作者沒有使用自適應(yīng)特征池添加相鄰層,而是對(duì)其進(jìn)行Concat操作,從而提高了預(yù)測(cè)的準(zhǔn)確性。
 
YOLO V5同樣采用了級(jí)聯(lián)操作。詳情可以參看模型大圖及Netron網(wǎng)絡(luò)圖中對(duì)應(yīng)的Concat操作。
 
Transfer learning
在自定義數(shù)據(jù)集上訓(xùn)練YOLO V5,包括以下幾個(gè)步驟:
  1. 準(zhǔn)備數(shù)據(jù)集
  2. 環(huán)境設(shè)定
  3. 配置/修改文件和目錄結(jié)構(gòu)
  4. 訓(xùn)練
  5. 推理
  6. 結(jié)果
Data Prepration
在準(zhǔn)備數(shù)據(jù)集方面,最重要的是明白YOLO家族獨(dú)特的標(biāo)簽數(shù)據(jù)集格式。
每個(gè)圖片文件.jpg,都有同一命名的標(biāo)簽文件.txt。
標(biāo)簽文件中每個(gè)對(duì)象獨(dú)占一行,格式為 。
其中:
  • -表示對(duì)象的類別序號(hào):從0 到 (classes-1)
  •  -參照?qǐng)D片寬度和高度的相對(duì)比例(浮點(diǎn)數(shù)值),從0.0到1.0
  • 例如: = / = /
  • 注意: 是矩形的中心,而不是左上角位置。
如下圖所示:
 
接下來我們要清楚YOLO V5的訓(xùn)練文件結(jié)構(gòu)是什么。
YOLO V5的標(biāo)簽文件夾和圖像文件夾應(yīng)位于同一目錄下。
其次自定義數(shù)據(jù)集應(yīng)該分成Train,Valid, Test三個(gè)部分,比例可以按照7:2:1分配。由于BDD100k數(shù)據(jù)集已經(jīng)為我們分好了Train,Valid, Test三部分,因此我們不需要自己分割數(shù)據(jù)集。
下圖為YOLO V5的訓(xùn)練文件結(jié)構(gòu):
 
讓我們來看看BDD100K數(shù)據(jù)集的概覽。
BDD100K是最大的開放式駕駛視頻數(shù)據(jù)集之一,其中包含10萬個(gè)視頻和10個(gè)任務(wù),目的是方便評(píng)估自動(dòng)駕駛圖像識(shí)別算法的的進(jìn)展。每個(gè)高分辨率視頻一共40秒。該數(shù)據(jù)集包括超過1000個(gè)小時(shí)的駕駛數(shù)據(jù),總共超過1億幀。這些視頻帶有GPU / IMU數(shù)據(jù)以獲取軌跡信息。該數(shù)據(jù)集具有地理,環(huán)境和天氣多樣性,從而能讓模型能夠識(shí)別多種場(chǎng)景,具備更多的泛化能力。這些豐富的戶外場(chǎng)景和復(fù)雜的車輛運(yùn)動(dòng)使感知任務(wù)更具挑戰(zhàn)性。該數(shù)據(jù)集上的任務(wù)包括圖像標(biāo)記,車道檢測(cè),可駕駛區(qū)域分割,道路對(duì)象檢測(cè),語(yǔ)義分割,實(shí)例分割,多對(duì)象檢測(cè)跟蹤,多對(duì)象分割跟蹤,領(lǐng)域自適應(yīng)和模仿學(xué)習(xí)。我們可以在BDD100K數(shù)據(jù)網(wǎng)站上下載數(shù)據(jù)。
 
Bdd100k的標(biāo)簽是由Scalabel生成的JSON格式。
- labels [ ]:
- id: int32
- category: string (classification)
- manualShape: boolean (whether the shape of the label is created or modified manually)
- manualAttributes: boolean (whether the attribute of the label is created or modified manually)
- score: float (the confidence or some other ways of measuring the quality of the label.)
- attributes:
- occluded: boolean
- truncated: boolean
- trafficLightColor: "red|green|yellow|none"
- areaType: "direct | alternative" (for driving area)
- laneDirection: "parallel|vertical" (for lanes)
- laneStyle: "solid | dashed" (for lanes)
- laneTypes: (for lanes)
- box2d:
- x1: float
- y1: float
- x2: float
- y2: float
道路對(duì)象類別包括以下幾類:
[
"bike",
"bus",
"car",
"motor",
"person",
"rider",
"traffic light",
"traffic sign",
"train",
"truck"
]
我們實(shí)際關(guān)注的只有- labels [ ]欄目下的內(nèi)容。
現(xiàn)在我們可以開始轉(zhuǎn)換Bdd100k的標(biāo)簽為YOLO 格式了。
Berkerley 提供了Bdd100k數(shù)據(jù)集的標(biāo)簽查看及標(biāo)簽格式轉(zhuǎn)化工具。由于沒有直接從bdd100k轉(zhuǎn)換成YOLO的工具,因此我們首先得使用將bdd100k的標(biāo)簽轉(zhuǎn)換為coco格式,然后再將coco格式轉(zhuǎn)換為yolo格式。
  • bdd to coco
我的目的是識(shí)別包括不同顏色交通燈在內(nèi)的所有交通對(duì)象,因此我們需要對(duì)原版的bdd2coco.py進(jìn)行一些修改,以獲取交通燈顏色并產(chǎn)生新的類別。
這是修改完的核心代碼:
for label in i['labels']:
annotation = dict()
category=label['category']
if (category == "traffic light"):
color = label['attributes']['trafficLightColor']
category = "tl_" + color
if category in id_dict.keys():
empty_image = False
annotation["iscrowd"] = 0
annotation["image_id"] = image['id']
x1 = label['box2d']['x1']
y1 = label['box2d']['y1']
x2 = label['box2d']['x2']
y2 = label['box2d']['y2']
annotation['bbox'] = [x1, y1, x2-x1, y2-y1]
annotation['area'] = float((x2 - x1) * (y2 - y1))
annotation['category_id'] = id_dict[category]
annotation['ignore'] = 0
annotation['id'] = label['id']
annotation['segmentation'] = [[x1, y1, x1, y2, x2, y2, x2, y1]]
annotations.append(annotation)
在完成bdd100k格式到y(tǒng)olo格式的轉(zhuǎn)換后,會(huì)獲得bdd100k_labels_images_det_coco_train.json和bdd100k_labels_images_det_coco_val.json兩個(gè)文件。
  • Coco to yolo
在完成先前的轉(zhuǎn)換之后,我們需要將訓(xùn)練集和驗(yàn)證集的coco格式標(biāo)簽轉(zhuǎn)換為yolo格式。注意需要分別指定訓(xùn)練集和驗(yàn)證集圖片位置,對(duì)應(yīng)的coco標(biāo)簽文件位置,及生成yolo標(biāo)簽的目標(biāo)位置。
config_train ={
"datasets": "COCO",
"img_path": "bdd100k_images/bdd100k/images/100k/train",
"label": "labels/bdd100k_labels_images_det_coco_train.json",
"img_type": ".jpg",
"manipast_path": "./",
"output_path": "labels/trains/",
"cls_list": "bdd100k.names",
}
config_valid ={
"datasets": "COCO",
"img_path": "bdd100k_images/bdd100k/images/100k/val",
"label": "labels/bdd100k_labels_images_det_coco_val.json",
"img_type": ".jpg",
"manipast_path": "./",
"output_path": "labels/valids/",
"cls_list": "bdd100k.names",
}
除此之外,我們還得將所有的類別寫入bdd100k.names文件。
person
rider
car
bus
truck
bike
motor
tl_green
tl_red
tl_yellow
tl_none
traffic sign
train
tl_green
運(yùn)行Bdd_preprocessing中的完整代碼可以完成Bdd100k格式標(biāo)簽到Y(jié)OLO標(biāo)簽格式的轉(zhuǎn)換。
Bdd2coco以及coco2yolo的詳細(xì)說明可以參看bdd100k代碼庫(kù)和convert2Yolo代碼庫(kù)。
為了方便將重心放在YOLO V5模型訓(xùn)練上,我為大家提供了預(yù)處理過后的Bdd100k數(shù)據(jù)集(1drv.ms/u/s!An7G4eYRvZz),該預(yù)處理過后的數(shù)據(jù)集可以直接用來訓(xùn)練YOLO V5對(duì)象檢測(cè)網(wǎng)絡(luò)。
Setup environment
運(yùn)行YOLO V5的第一步是克隆YOLO V5的官方代碼庫(kù)。
YOLO V5 需要的Pytorch版本>=1.5, Python版本3.7, CUDA版本10.2。
Ultralytics提供了requirement.txt文件來方便新環(huán)境配置。
通過在shell中運(yùn)行pip install -r requirement.txt 命令,可以自動(dòng)安裝所有依賴項(xiàng)。
numpy==1.17
scipy==1.4.1
cudatoolkit==10.2.89
opencv-python
torch==1.5
torchvision==0.6.0
matplotlib
pycocotools
tqdm
pillow
tensorboard
pyyaml
Configuration
YOLO V5的默認(rèn)YAML文件coco.yaml 中是coco數(shù)據(jù)集所有的類對(duì)象名稱和類數(shù)量(80)。由于我們的目的是基于bdd100k數(shù)據(jù)集來訓(xùn)練檢測(cè)少量特定交通物體的模型,我們不需要訓(xùn)練檢測(cè)80類網(wǎng)絡(luò)的模型,所有我們得重新創(chuàng)建一個(gè)uc_data.yaml文件來描述bdd100k數(shù)據(jù)集的數(shù)據(jù)特性。由于我們模型的輸出不是coco數(shù)據(jù)集的80個(gè)類,而是13類,因此我們得修改此處的輸出類別數(shù)量為13。
# here you need to specify the files train, test and validation txt
train: bdd100k/images/train
val: bdd100k/images/valid
test: bdd100k/images/test
nc: 13
names: ['person','rider','car','bus','truck','bike','motor','tl_green','tl_red','tl_yellow','tl_none','t_sign','train']
之后我們會(huì)用到上述YAML文件來訓(xùn)練模型。
Modify Model arichtecture
YOLO V5通過models文件家中的cfg文件*.yaml來調(diào)整訓(xùn)練模型的結(jié)構(gòu)。
由于我們模型的輸出不是coco數(shù)據(jù)集的80個(gè)類,而是13類,因此我們需要修改模型的對(duì)象預(yù)測(cè)層輸出類別數(shù)量為13。
# parameters
nc: 13 # number of classes
我們可以直接修改YAML文件下各個(gè)組件的細(xì)節(jié)(如數(shù)字),來重新定義自己的模型架構(gòu)。
# YOLO V5s
# parameters
nc: 13 # number of classes
depth_multiple: 0.33 # model depth multiple
width_multiple: 0.50 # layer channel multiple
# anchors
anchors:
- [116,90, 156,198, 373,326] # P5/32
- [30,61, 62,45, 59,119] # P4/16
- [10,13, 16,30, 33,23] # P3/8
# YOLOv5 backbone
backbone:
# [from, number, module, args]
[[-1, 1, Focus, [64, 3]], # 0-P1/2
[-1, 1, Conv, [128, 3, 2]], # 1-P2/4
[-1, 3, BottleneckCSP, [128]],
[-1, 1, Conv, [256, 3, 2]], # 3-P3/8
[-1, 9, BottleneckCSP, [256]],
[-1, 1, Conv, [512, 3, 2]], # 5-P4/16
[-1, 9, BottleneckCSP, [512]],
[-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
[-1, 1, SPP, [1024, [5, 9, 13]]],
]
# YOLOv5 head
head:
[[-1, 3, BottleneckCSP, [1024, False]], # 9
[-1, 1, Conv, [512, 1, 1]],
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
[[-1, 6], 1, Concat, [1]], # cat backbone P4
[-1, 3, BottleneckCSP, [512, False]], # 13
[-1, 1, Conv, [256, 1, 1]],
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
[[-1, 4], 1, Concat, [1]], # cat backbone P3
[-1, 3, BottleneckCSP, [256, False]],
[-1, 1, nn.Conv2d, [na * (nc + 5), 1, 1]], # 18 (P3/8-small)
[-2, 1, Conv, [256, 3, 2]],
[[-1, 14], 1, Concat, [1]], # cat head P4
[-1, 3, BottleneckCSP, [512, False]],
[-1, 1, nn.Conv2d, [na * (nc + 5), 1, 1]], # 22 (P4/16-medium)
[-2, 1, Conv, [512, 3, 2]],
[[-1, 10], 1, Concat, [1]], # cat head P5
[-1, 3, BottleneckCSP, [1024, False]],
[-1, 1, nn.Conv2d, [na * (nc + 5), 1, 1]], # 26 (P5/32-large)
[[], 1, Detect, [nc, anchors]], # Detect(P5, P4, P3)
]
為了更清楚的了解YOLO V5的模型結(jié)構(gòu),我們使用netron來實(shí)現(xiàn)模型可視化,值得注意的是,如果想獲得清晰的網(wǎng)絡(luò)圖,需要將pt文件轉(zhuǎn)化為torchscipt格式。
 
由于Bdd100k數(shù)據(jù)集與COCO數(shù)據(jù)的數(shù)據(jù)量級(jí),場(chǎng)景及部分對(duì)象類別相近,因此我并沒有修改模型結(jié)構(gòu)。如果將YOLO V5運(yùn)用在一些小數(shù)據(jù)場(chǎng)景或者對(duì)象類別相差較大的場(chǎng)景如醫(yī)學(xué)視覺,則可以根據(jù)實(shí)際情況增減模型。
Transfer learning theory
現(xiàn)在讓我們來了解下本文的重點(diǎn)遷移學(xué)習(xí)。
什么是遷移學(xué)習(xí)?遷移學(xué)習(xí)(Transfer learning) 顧名思義就是就是把已學(xué)訓(xùn)練好的模型參數(shù)遷移到新的模型來幫助新模型訓(xùn)練??紤]到大部分?jǐn)?shù)據(jù)或任務(wù)是存在相關(guān)性的,所以通過遷移學(xué)習(xí)我們可以將已經(jīng)學(xué)到的模型參數(shù)(也可理解為模型學(xué)到的知識(shí))通過某種方式來分享給新模型從而加快并優(yōu)化模型的學(xué)習(xí)效率不用像大多數(shù)網(wǎng)絡(luò)那樣從零學(xué)習(xí)(starting from scratch,tabula rasa)。
https://www.zhihu.com/question/41979241/answer/123545914
再來看看我們面臨的問題,我們已經(jīng)有了YOLO V5模型框架,有了針對(duì)COCO數(shù)據(jù)集預(yù)訓(xùn)練的權(quán)重文件*.pt,Bdd100k的訓(xùn)練數(shù)據(jù)很龐大,而我們需要額外提取紅綠燈的顏色作為新的類別,那怎么樣才能把YOLO V5已經(jīng)學(xué)習(xí)的模型參數(shù)通過某種方式分享給新模型從而加快并優(yōu)化模型的學(xué)習(xí)效率?
下圖為針對(duì)不同場(chǎng)景的遷移學(xué)習(xí)指南。
 
  • 如果訓(xùn)練集小,訓(xùn)練數(shù)據(jù)與預(yù)訓(xùn)練數(shù)據(jù)相似,那么我們可以凍住卷積層,直接訓(xùn)練全連接層。
  • 如果訓(xùn)練集小,訓(xùn)練數(shù)據(jù)與預(yù)訓(xùn)練數(shù)據(jù)不相似,那么必須從頭訓(xùn)練卷積層及全連接層。
  • 如果訓(xùn)練集大,訓(xùn)練數(shù)據(jù)與預(yù)訓(xùn)練數(shù)據(jù)相似,那么我們可以使用預(yù)訓(xùn)練的權(quán)重參數(shù)初始化網(wǎng)絡(luò),然后從頭開始訓(xùn)練。
  • 如果訓(xùn)練集大,訓(xùn)練數(shù)據(jù)與預(yù)訓(xùn)練數(shù)據(jù)不相似,那么我們可以使用預(yù)訓(xùn)練的權(quán)重參數(shù)初始化網(wǎng)絡(luò),然后從頭開始訓(xùn)練或者完全不使用預(yù)訓(xùn)練權(quán)重,重新開始從頭訓(xùn)練。
  • 值得注意的是,對(duì)于大數(shù)據(jù)集,不推薦凍住卷積層,直接訓(xùn)練全連接層的方式,這可能會(huì)對(duì)性能造成很大影響。
我們的情況,符合上述第三種,通常只需要使用預(yù)訓(xùn)練的權(quán)重初始化網(wǎng)絡(luò),然后直接從頭開始訓(xùn)練,從而更快的使模型有效收斂。但是由于之前沒有人公開過對(duì)于Bdd100k數(shù)據(jù)集使用YOLO V5預(yù)訓(xùn)練權(quán)重和不使用其訓(xùn)練權(quán)重的對(duì)比,甚至你也可以說COCO數(shù)據(jù)集80類,而Bdd100k數(shù)據(jù)集13類,兩者大部分類是不相似的。我并不能百分百確定哪個(gè)方案更適合本項(xiàng)目。于是我分別使用YOLO V5s預(yù)訓(xùn)練權(quán)重和不使用其訓(xùn)練權(quán)重來訓(xùn)練基于Bdd100k數(shù)據(jù)集的對(duì)象識(shí)別網(wǎng)絡(luò),并對(duì)比它們的效果。
Ultralytics一共提供了四個(gè)版本的YOLO V5模型。
下圖是它們的比較:
 
YOLO V5x是非常巨型的網(wǎng)絡(luò),同樣也是訓(xùn)練精度最好的網(wǎng)絡(luò),關(guān)于YOLO V5x與YOLO V4的性能對(duì)比尚未有百分百定論,根據(jù)WongKinYiu的6月22日的Benchmarks結(jié)論,YOLO V4仍然稍微優(yōu)于YOLO V5x,但是根據(jù)最近很多kaggle比賽的同學(xué)反映,YOLO V5的比賽結(jié)果普遍由于YOLO V4,當(dāng)然不排除這是tensorflow和pytorch等版本的YOLO V4優(yōu)化不夠。我覺得YOLO V5最驚艷的是它的速度和尺寸。因此我在本文中只使用YOLO V5s來訓(xùn)練基于Bdd100k自動(dòng)駕駛數(shù)據(jù)集的對(duì)象檢測(cè)深度網(wǎng)絡(luò)。另外一個(gè)影響因素是,Bdd100k的數(shù)據(jù)集龐大,YOLO V5s在 Intel Xeon W-2145 ,64 GB RAM,NVIDIA RTX 2080Ti,batch_size 32, Use RAM cache的情況下訓(xùn)練300 epochs 需要66小時(shí),YOLO V5x是它的三倍。還是等我有時(shí)間再訓(xùn)練下YOLO V5x吧~
Traininig
在我們完成所有的準(zhǔn)備工作之后,我們可以開始訓(xùn)練了!
準(zhǔn)備文件:
  • YOLO v5代碼庫(kù)
  • 預(yù)處理后的bdd100k數(shù)據(jù)集:將JSON標(biāo)簽轉(zhuǎn)換為YOLO格式,并按照YOLO V5的訓(xùn)練文件結(jié)構(gòu)要求布置
  • custom_yolov5s.yaml:修改后的模型文件
  • uc_data.yaml: 包含訓(xùn)練,驗(yàn)證集的位置,類別數(shù)目及名稱
訓(xùn)練配置:
  • Intel Xeon W-2145 ,64 GB RAM,NVIDIA RTX 2080Ti。
訓(xùn)練參數(shù)(基于bdd100k數(shù)據(jù)集進(jìn)行分析):
  • — img: 輸入圖像的大小,建議使用640,因?yàn)閷?duì)于交通場(chǎng)景,輸入圖片尺寸過小時(shí),會(huì)導(dǎo)致部分對(duì)象寬高小于3像素,可能會(huì)影響訓(xùn)練精度
  • — batch-size: 批次大小,對(duì)于2080Ti-11GB 或者P100-16GB,輸入img-size 640,batch-size 32為上限
  • — epochs: 訓(xùn)練迭代數(shù),作者建議訓(xùn)練300個(gè)epochs起
  • — data: 創(chuàng)建的 YAML 文件uc_data.yaml
  • — cfg: 模型文件Custom_yolov5s.yaml,需要自己至少修改類別數(shù)量及類別種類
  • — weights: 對(duì)于本項(xiàng)目不使用預(yù)訓(xùn)練權(quán)重,如果需要預(yù)訓(xùn)練權(quán)重,可以訪問此地址
  • — cache-images: 將預(yù)處理后的訓(xùn)練數(shù)據(jù)全部存儲(chǔ)在RAM中,能夠加快訓(xùn)練速度
  • — hyp: 這個(gè)參數(shù)是自定義的hyp.yaml地址,對(duì)于小尺寸數(shù)據(jù),可以更改hyp中optimizer為Adam,并修改配套參數(shù)為作者預(yù)設(shè)的Adam參數(shù)
  • — rect:輸入這個(gè)參數(shù),會(huì)關(guān)閉Mosaic數(shù)據(jù)增強(qiáng)
  • — resume:從上次訓(xùn)練的結(jié)束last.pt繼續(xù)訓(xùn)練
  • — nosave:輸入這個(gè)參數(shù)將存儲(chǔ)最后的checkpoint,可以加快整體訓(xùn)練速度,但是建議關(guān)閉這個(gè)參數(shù),這樣能保留best.pt
  • — notest:只測(cè)試最后一個(gè)epoch,能加快整體訓(xùn)練速度
  • — noautoanchor:關(guān)閉自適應(yīng)自適應(yīng)錨定框,YOLO V5會(huì)自動(dòng)分析當(dāng)前錨定框的 Best Possible Recall (BPR) ,對(duì)于img-size 640,最佳BPR為0.9900,隨著img-size降低,BPR也隨之變差
  • — multi-scale:輸入圖像多尺度訓(xùn)練,在訓(xùn)練過程中,輸入圖像會(huì)自動(dòng)resize至 img-size +/- 50%,能一定程度上防止模型過擬合,但是對(duì)于GPU顯存要求很高,對(duì)于640的img-size至少使用16GB顯存,才能保證運(yùn)行不出錯(cuò)
  • — single-cls:模型的輸出為單一類別,比如我只需要識(shí)別Trunk
  • — device: 選擇使用CUDA或者CPU
YOLO V5的作者建議至少訓(xùn)練300個(gè)回合,每次訓(xùn)練完成后所有的結(jié)果及權(quán)重會(huì)儲(chǔ)存在runs文件夾下。
訓(xùn)練過程:
  • Train from pre-weight(橘黃色)
!python train.py --img 640 --batch 32 --epochs 300 --data './models/uc_data.yaml' --cfg ./models/custom_yolov5s.yaml --weights "./weights/yolov5s.pt" --name yolov5s_bdd_prew --cache
  • Train from scatch(藍(lán)色)
!python train.py --img 640 --batch 32 --epochs 300 --data './models/uc_data.yaml' --cfg ./models/custom_yolov5s.yaml --weights "" --name yolov5s_bdd --cache
訓(xùn)練結(jié)果:
  • Metrics
 
  • Train loss
 
  • Valid loss
 
結(jié)果分析:
  • Train from pre-weight和Train from scatch的最高mAP_0.5均能達(dá)到46.5%。
  • Train from pre-weight比Train from scatch能更快收斂,但是在250epochs左右兩者已經(jīng)達(dá)到一致。
  • Train from pre-weight和Train from scatch的模型大小均為14.8M,值得注意的是YOLO V5在訓(xùn)練結(jié)束后會(huì)自動(dòng)給模型剪枝,訓(xùn)練過程中的last.pt有58.6M,作者考慮的非常周到。
  • 總的來說Train from pre-weight比Train from scatch能更快收斂,能一定程度上減少訓(xùn)練時(shí)間開銷,對(duì)于和COCO數(shù)據(jù)集相近的數(shù)據(jù)集,可以采用Train from pre-weight,如果時(shí)間充裕,Train from scatch更為妥當(dāng)。
Inference
現(xiàn)在我們已經(jīng)完成了模型訓(xùn)練了,讓我們?cè)谝恍﹫D像上測(cè)試它的性能吧。
檢測(cè)參數(shù):
  • — weights: 訓(xùn)練權(quán)重的路徑
  • — source:推理目標(biāo)的路徑,可以是圖片,視頻,網(wǎng)絡(luò)攝像頭等
  • — source:推理結(jié)果的輸出路徑
  • — img-size:推理圖片的大小
  • — conf-thres:對(duì)象置信閾值,默認(rèn)0.4
  • — iou-thres:NMS的IOU閾值,可以根據(jù)實(shí)際對(duì)象的重疊度調(diào)節(jié),默認(rèn)0.5
  • — device: 選擇使用CUDA或者CPU
  • — view-img:顯示所有推理結(jié)果
  • — save-txt:將每一幀的推理結(jié)果及邊界框的位置,存入*.txt文件
  • — classes:類別過濾,意思是只推理目標(biāo)類別
  • — agnostic-nms:使用agnostic-nms NMS
!python detect.py --weights runs/exp0_yolov5s_bdd_prew/weights/best_yolov5s_bdd_prew.pt --source bdd100k/images/test --save-txt
 
 
 
 
為了測(cè)試YOLO V5s的實(shí)時(shí)視頻處理性能,我測(cè)試了一個(gè)4K 道路場(chǎng)景錄制視頻,
推理速度高達(dá)7ms/幀。
 
 
更多完整視頻,請(qǐng)用瀏覽器訪問下面鏈接:
https://www.bilibili.com/video/BV1sz4y1Q7wi?from=search&seid=17636832624273422
 
Summary
至此我們已經(jīng)了解了YOLO V5的網(wǎng)絡(luò)結(jié)構(gòu),并且基于Bdd100k數(shù)據(jù)集訓(xùn)練了屬于自己的自動(dòng)駕駛對(duì)象檢測(cè)模型。YOLO V5是個(gè)非常棒的開源對(duì)象檢測(cè)網(wǎng)絡(luò),代碼庫(kù)的更新速度非???,不管它現(xiàn)階段配不配的上V5的名稱,它都是一個(gè)快速而且強(qiáng)大的對(duì)象檢測(cè)器。YOLO V5值得你去嘗試!
作者:William
Github: https://github.com/williamhyin/yolov5s_bdd100k
Email: williamhyin@outlook.com
知乎專欄: 自動(dòng)駕駛?cè)珬9こ處?nbsp;https://zhuanlan.zhihu.com/williamhyin
 
分享到:
 
反對(duì) 0 舉報(bào) 0 收藏 0 評(píng)論 0
滬ICP備11026917號(hào)-25