在YOLOv2論文中,作者有對(duì)Dimension Cluster做一個(gè)介紹,這個(gè)cluster的目的就是尋找出anchor的先驗(yàn)(簡稱為先驗(yàn)框)。
什么是先驗(yàn)框呢,簡單來說,在YOLOv1中,作者遇到了一個(gè)問題,雖然我們通過實(shí)驗(yàn)知道要選兩個(gè)boxes是最優(yōu)的,但是如何這兩個(gè)boxes的尺寸如何決定呢?網(wǎng)絡(luò)自身可以學(xué)著不斷調(diào)節(jié)box的大小,但是我們能夠提前給定一個(gè)/多個(gè)尺寸作為備選不是更好嗎?所以作者就決定利用 k-means 聚類方法在 training set bounding boxes上來尋找先驗(yàn)框(框的尺寸)。
標(biāo)準(zhǔn)的k-means方法用的是歐氏距離,但是這樣會(huì)導(dǎo)致 larger boxes generate more error than smaller boxes. 我們想要得到的先驗(yàn)框,是能夠帶領(lǐng)我們得到更高的IOU的,如果用歐氏距離來衡量,可能會(huì)導(dǎo)致“大框優(yōu)勢”。所以作者使用了
來作為k-means中“距離”的判定。
我們期待距離越小越好(IOU越大越好),所以距離判定時(shí)候用 1 - IOU
討論內(nèi)容見(需要翻墻):https://groups.google.com/forum/#!topic/darknet/qrcGefJ6d5g
其中,兩個(gè)po主放出了他們k-means算法的代碼:
????Jumabek
????PaulChongPeng?
????WillieMaddox
PaulChongPeng的我用VOC2007+2012的training set測試了一下(4/46/2018),結(jié)果如下:
自己加了一個(gè)測avg_IOU,最后IOU還可以,但是anchor還是和作者的數(shù)據(jù)有些差距(據(jù)說作者是用VOC+COCO一起做的聚類)
還有一個(gè)po主放出了standard k-means的方法(實(shí)際是不對(duì)的),用的是歐氏距離而非“IOU距離”:
# I wrote up a couple quick scripts to help with this: gen_boxes.sh and cluster_boxes.py.
# They operate within your directory of some_image_name.txt label files.
# Usage example is shown below:
ubuntu@host:~/data/labels$ ls *.txt | head -5
00RaKqC3eqjWCHQMIPKaeNMsdivO83GL.txt
016rMzBciA5V4SjFsCAQ1do8klvl4CWt.txt
01dfRsndtBz67TK80LCH0NAseYwh7md6.txt
03hptnlIR8YB0dNUqZ4AC9gVkwtDb5DZ.txt
04HPP8cRl0wFL0tPEpNCmwrDW74kByKB.txt
ubuntu@host:~/data/labels$ head 00RaKqC3eqjWCHQMIPKaeNMsdivO83GL.txt
0 0.502333 0.549333 0.144667 0.137333
ubuntu@host:~/data/labels$ cat gen_boxes.sh
cat *.txt | cut -d' ' -f 4,5 | sed 's/\([^ ]*\) \(.*\)/\1,\2/g' > boxes.csv
ubuntu@host:~/data/labels$ bash gen_boxes.sh
ubuntu@host:~/data/labels$ cat cluster_boxes.py
from sklearn.cluster import KMeans
import numpy as np
data = np.genfromtxt('boxes.csv', delimiter=',')
print("Example of data:")
print(data[0:10])
print("")
kmeans = KMeans(n_clusters=5, random_state=0).fit(data)
print("Cluster centers:")
print(kmeans.cluster_centers_)
print("")
print("Scaled to [0, 13]:")
print(kmeans.cluster_centers_ * 13)
print("")
print("In Darknet config format:")
def coords(x):
? return "%f,%f" % (x[0], x[1])
print("anchors= %s" % " ".join([coords(center) for center in kmeans.cluster_centers_ * 13]))
ubuntu@host:~/data/labels$ python cluster_boxes.py
Example of data:
[[ 0.144667? 0.137333]
[ 0.135333? 0.240667]
[ 0.145? ? 0.146667]
[ 0.547? ? 0.306667]
[ 0.4? ? ? 0.241667]
[ 0.137? ? 0.145? ]
[ 0.643? ? 0.356667]
[ 0.147? ? 0.086667]
[ 0.123? ? 0.112? ]
[ 0.202? ? 0.265? ]]
Cluster centers:
[[ 0.1377161? 0.13268718]
[ 0.28492789? 0.18958423]
[ 0.0663724? 0.05359964]
[ 0.48530697? 0.496173? ]
[ 0.18765588? 0.27052479]]
Scaled to [0, 13]:
[[ 1.79030931? 1.72493339]
[ 3.70406262? 2.46459499]
[ 0.86284123? 0.6967953 ]
[ 6.30899063? 6.450249? ]
[ 2.43952643? 3.51682231]]
# In Darknet config format:
# anchors= 1.790309,1.724933 3.704063,2.464595 0.862841,0.696795 6.308991,6.450249 2.439526,3.516822
# You can then copy that "anchors= ..." line in place of the existing one in your yolo-whatever.cfg file.
YOLOv3也沿用了YOLOv2中的先驗(yàn)框(anchor),求法相同。
為什么YOLOv2和YOLOv3的anchor大小有明顯區(qū)別?
在YOLOv2中,作者用最后一層feature map的相對(duì)大小來定義anchor大小。也就是說,在YOLOv2中,最后一層feature map大小為13X13,相對(duì)的anchor大小范圍就在(0x0,13x13],如果一個(gè)anchor大小是9x9,那么其在原圖上的實(shí)際大小是288x288.
而在YOLOv3中,作者又改用相對(duì)于原圖的大小來定義anchor,anchor的大小為(0x0,input_w x input_h]。
所以,在兩份cfg文件中,anchor的大小有明顯的區(qū)別。如下是作者自己的解釋:
So YOLOv2 I made some design choice errors, I made the anchor box size be relative to the feature size in the last layer. Since the network was down-sampling by 32. This means it was relative to 32 pixels so an anchor of 9x9 was actually 288px x 288px.
In YOLOv3 anchor sizes are actual pixel values. this simplifies a lot of stuff and was only a little bit harder to implement
https://github.com/pjreddie/darknet/issues/555#issuecomment-376190325
---------------------
作者:Pattorio
來源:CSDN
原文:https://blog.csdn.net/Pattorio/article/details/80095511
版權(quán)聲明:本文為博主原創(chuàng)文章,轉(zhuǎn)載請(qǐng)附上博文鏈接!