當前位置:
首頁 > 知識 > YOLO,一種簡易快捷的目標檢測演算法

YOLO,一種簡易快捷的目標檢測演算法

本文由兔子老大為AI 研習社撰寫的獨家供稿。有償供稿請聯繫郵箱 【konglingshuang@leiphone.com】。

YOLO全稱You Only Look Once,是一個十分容易構造目標檢測演算法,出自於CVPR2016關於目標檢測的方向的一篇優秀論文(https://arxiv.org/abs/1506.02640),本文會對YOLO的思路進行總結並給出關鍵代碼的分析,在介紹YOLO前,不妨先看看其所在的領域的發展歷程。


目標檢測

相對於傳統的分類問題,目標檢測顯然更符合現實需求,因為往往現實中不可能在某一個場景只有一個物體(業務需求也很少會只要求分辨這是什麼),但也因此目標檢測的需求變得更為複雜,不僅僅要求detector能夠檢驗出是什麼物體,還的確定這個物體在圖片哪裡。

總的來說,目標檢測先是經歷了最為簡單而又暴力的歷程,這個過程高度的符合人類的直覺。簡單點來說,既然要我要識別出目標在哪裡,那我就將圖片劃分成一個個一個個小圖片扔進detector,但detecror認為某樣物體在這個小區域 上了,OK,那我們就認為這個物體在這個小圖片上了。而這個思路,正是比較早期的目標檢測思路,比如R-CNN。

然後來的Fast R-CNN,Faster R-CNN雖有改進,比如不再是將圖片一塊塊的傳進CNN提取特徵,而是整體放進CNN提取除 featuremap 然後再做進一步處理,但依舊是整體流程分為區域提取目標分類兩部分(two-stage),這樣做的一個特點是雖然精度是保證了,但速度上不去,於是以YOLO為主要代表的這種一步到位(one-stage)即End To End的目標演算法應運而生了。

YOLO詳解

細心的讀者可能已經發現,是的,YOLO的名字You only look once正是自身特點的高度概括。

YOLO的核心思想在於將目標檢測作為回歸問題解決 ,YOLO首先將圖片劃分成SxS個區域,注意這個區域的概念不同於上文提及將圖片劃分成N個區域扔進detector這裡的區域不同。上文提及的區域是真的將圖片進行剪裁,或者說把圖片的某個局部的像素扔進detector,而這裡的劃分區域,只的是邏輯上的劃分。

為什麼是邏輯上的劃分呢?這體現再YOLO最後一層全連接層上,也就是YOLO針對每一幅圖片做出的預測。

其預測的向量是SxSx(B*5+C)長度的向量。其中S是劃分的格子數,一般S=7,B是每個格子預測的邊框數 ,一般B=2,C是跟你實際問題相關的類別數,但要注意的是這裡你應該背景當作一個類別考慮進去。

不難得出,這個預測向量包括:

SxSxC 個類別信息,表示每一個格子可能屬於什麼類別

SxSxB 個置信度,表示每一個格子的B個框的置信度,再YOLO進行預測後,一般只保留置信度為0.5以上的框。當然這個閾值也可以人工調整。

SxSxBx4 個位置信息,4個位置信息分別是xywh,其中xy為box的中心點。

說完YOLO的總體思路後,我們在看看YOLO的網路結構

該網路結構包括 24 個卷積層,最後接 2 個全連接層。文章設計的網路借鑒 GoogleNet 的思想,在每個 1x1 的 歸約層(Reduction layer,1x1的卷積 )之後再接一個 3?3 的卷積層的結構替代 Inception結構。論文中還提到了 fast 版本的 Yolo,只有 9 個卷積層,其他則保持一致。

因為最後使用了全連接層,預測圖片要和train的圖片大小一致,而其他one-stage的演算法,比如SSD,或者YOLO-V2則沒有這個問題,但這個不在本文討論範圍內。

其實網路架構總體保持一致即可,個人不建議照抄全部參數,還是需要根據你的實際任務或計算資源進行魔改,所以接下來重點會講述訓練的過程和損失函數的構建,其中也會給出MXNET版本的代碼進行解釋。文末會給出全部代碼的開源地址。

損失函數的定義

圖片來源於網路

大題來說,損失函數分別由:

預測框位置的誤差 (1)(2)

IOU誤差(3)(4)

類別誤差(5)

其中,每一個組成部分對整體的貢獻度的誤差是不同的,需要乘上一個權重進行調和。相對來說,目標檢測的任務其實更在意位置誤差,故位置誤差的權重一般為5。在此,讀者可能費解,為什麼框的寬和高取的是根號,而非直接計算?

想要了解這個問題,我們不妨來看看的圖像

這裡額外多說一句,如果有打數據挖掘比賽經驗的同學,可能會比較清楚一種數據處理的手段,當某些時候,會對某一特徵進行數據變換,比如和,取 log這些變換有一個特徵,就是數值越大,懲罰越大(變換的幅度越大,比如4和4的平方,10到10的平方)。

而在損失函數中應用這一方法,起到的作用則是使得小框產生的誤差比大框的誤差更為敏感,其目的是為了解決對小物體的檢測問題。但事實上,這樣的設定只能緩解卻沒有最終解決這個問題。

在說IOU誤差,IOU的定義為實際描框和預測框之間的交集除以兩者之間的並集。

聽上去很複雜,實際我們既然能獲得預測框坐標,只要通過簡單的換算,該比值實際能轉換成面積的計算。而同樣的,這裡也有一個問題,我們感興趣的物體,對於整體圖片來說,畢竟屬於小數。換言之,就是在SxS個格子裡面,預測出來的框大多是無效的框,這些無效框的誤差積累是會對損失函數產生影響,換句話說,我們只希望有物體的預測框有多准,而不在乎沒有物體的框預測得有多差。因此,我們也需要對這些無效框的在損失函數上得貢獻乘上一個權重,進行調整。

也就是,該值一般取0.5。

關於分類誤差,論文雖然是採用mse來衡量,但是否採用交叉熵來衡量更合理呢?對於分類問題,採用mse和交叉熵來衡量,又會產生什麼問題?這個問題留給讀者思考。


代碼實現

說完了損失函數,下面來講述如何使用MXNET來實現YOLO,同理的,YOLO的網路結構較為簡單,你可以採用任何的框架搭出,如果像我一樣只是為了演示demo,對網路結構可以修改一下,採取網路拓撲上比較簡單的模型。

同樣的,目標檢測常使用在ImageNet上預訓練(pretrain)的模型 作為特徵抽取器,同樣,因為這裡只是演示demo,同樣也省略這一部分,只是重點講損失函數的構造。

首先,雖然損失函數雖然是邏輯上分成三個部分,但我們不打算分開三個部分計算。

而是將整體式子拆分成 W x loss來計算,這樣在代碼上,實現起來要方便得多,以下時loss函數的計算過程:

可能會有童鞋好奇,為什麼坐標誤差是用預測值和label直接mse算呢,w和h不是應該要開根號嗎?是的,但我們為了數值穩定,在人工構建label時就已經將wh以開根後的形式存儲好了,這是因為,神經網路的輸出在初始時,正負值時隨機的,儘管在數學上的結果是虛數i,但在DL相關的框架,該操作會直接造成nan,造成損失函數無法優化,而且相應代碼的書寫更為複雜。而採取直接以取根號後的形式我們只要在獲取輸出時,再將wh求一個平方即可。

另外要說的一點就是IOU誤差,雖然很多文章都將這一點直接成為IOU誤差,實際上計算時時IOU誤差和置信度的結合。

置信度在label的表現形式時,這個地方有目標物體則為1,沒有則是0,這樣用mse優化後,輸出值會在0~1附近,正好可以代表某個框是否框中物體的置信度。

但為什麼不直接 對置信度用mse呢,這同樣是一個權重的調節的問題,但這裡不能說我們就不care那些沒有物體的框的值了,因為這裡的值是置信度,如果我們任由其發展,萬一沒有物體的框的置信度比有框中物體的置信度還要高,那我們使用閾值過濾時,就可能出現問題了。只能說我們希望loss中更重視有框中物體的框的誤差。

這裡補充另外一個知識點最大值抑制,簡單點來說,既然每個格子會生成B個框(一般B>1)這樣就有可能同時兩個框都框中了物體,那麼到底採用那個框作為預測結果呢?答案是採用IOU值高的那個框,而IOU值小的,就會不被重視而受到抑制。

在求出IOU後,我們求出每一個格子的框中的最大值,再使用equal操作,使得最大值為1,其餘值為0再參與後面的運算即可。


代碼地址

DEMO-github(https://github.com/MashiMaroLjc/YOLO)

代碼使用的是李沐公開課的皮卡丘數據集,用MXNET的Gluon介面實現,Enjoyit!

運行效果:

上述文章若有不正確的地方,敬請指正。

上海交通大學博士講師團隊

從演算法到實戰應用

涵蓋 CV 領域主要知識點

手把手項目演示

全程提供代碼

深度剖析 CV 研究體系

輕鬆實戰深度學習應用領域!

新人福利

關注 AI 研習社(okweiwu),回復1領取

【超過 1000G 神經網路 / AI / 大數據,教程,論文】

YOLO9000 好棒好快好強壯 閱讀筆記

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 AI研習社 的精彩文章:

拿到吳恩達 DeepLeaning 的課程證書能找到機器學習工作嗎?

TAG:AI研習社 |