在YOLOV5优化算法当中,根据不同的数据信息,通常会事先设定固定Anchor,接下来本文关键为大家介绍了有关yolov5中anchors设定的资料,原文中根据案例编码推荐的十分详尽,必须的小伙伴可以借鉴一下
yolov5中增强了响应式导向框(AutoLearningBoundingBoxAnchors),但是其他yolo系类是不存在的。
一、默认设置导向框
Yolov5中默认设置保留了某些对于coco数据信息的预置导向框,在yolov5的环境变量*.yaml里已经预置了640×640图像尺寸下导向框的规格(以yolov5s.yaml为例子):
#anchors anchors: -[10,13,16,30,33,23]#P3/8 -[30,61,62,45,59,119]#P4/16 -[116,90,156,198,373,326]#P5/32
anchors主要参数一共有四行,每排9个标值;且每一行意味着运用不同类型的特征图;
1、首行要在最大的一个特点图中锚框
2、下一页是在正中间的的特点图中锚框
3、第三行要在最小特点图中锚框;
在物体检测任务时,一般希望能在大一点的特征图上来检验个人目标,但大特征图才带有大量个人目标信息内容,因而大特点图中anchor标值一般设为小标值,而大特点图中标值设定为大标值检验大总体目标。
二、自定导向框
1、训练的时候快速计算导向框
yolov5中并不只是应用默认设置导向框,在进行练习之前都会对模型集中标注信息内容进行核实,估算此数据信息标明信息内容对于默认设置导向框的最好均方误差,当最好均方误差大于等于0.98,一般不必须升级导向框;假如最好均方误差低于0.98,就需要重算合乎此数据信息的导向框。
审查导向框适合不适合标准的函数公式在/utils/autoanchor.py报告中:
defcheck_anchors(dataset,model,thr=4.0,imgsz=640):
在其中thr就是指数据信息集中标注框高宽较大阀值,默认设置是采用超参文档hyp.scratch.yaml里的“anchor_t”变量值。
审查关键编码如下所示:
defmetric(k):#computemetric r=wh[:,None]/k[None] x=torch.min(r,1./r).min(2)[0]#ratiometric best=x.max(1)[0]#best_x aat=(x>1./thr).float().sum(1).mean()#anchorsabovethreshold bpr=(best>1./thr).float().mean()#bestpossiblerecall returnbpr,aat bpr,aat=metric(m.anchor_grid.clone().cpu().view(-1,2)) 在其中2个指标值必须说明一下(bpr和aat): bpr(bestpossiblerecall) aat(anchorsabovethreshold)
其中bpr主要参数就是说确定是否必须重算导向框的根据(是不是低于0.98)。
重算合乎此数据信息标明框的导向框,是运用kmean聚类方法达到的,编码在/utils/autoanchor.py文件中:
def kmean_anchors(path='./data/coco128.yaml',n=9,img_size=640,thr=4.0,gen=1000,verbose=True):
"""Creates kmeans-evolved anchors from training dataset
Arguments:
path:path to dataset*.yaml,or a loaded dataset
n:number of anchors
img_size:image size used for training
thr:anchor-label wh ratio threshold hyperparameter hyp['anchor_t']used for training,default=4.0
gen:generations to evolve anchors using genetic algorithm
verbose:print all results
Return:
k:kmeans evolved anchors
Usage:
from utils.autoanchor import*;_=kmean_anchors()
"""
thr=1./thr
prefix=colorstr('autoanchor:')
def metric(k,wh):#compute metrics
r=wh[:,None]/k[None]
x=torch.min(r,1./r).min(2)[0]#ratio metric
#x=wh_iou(wh,torch.tensor(k))#iou metric
return x,x.max(1)[0]#x,best_x
def anchor_fitness(k):#mutation fitness
_,best=metric(torch.tensor(k,dtype=torch.float32),wh)
return(best*(best>thr).float()).mean()#fitness
def print_results(k):
k=k[np.argsort(k.prod(1))]#sort small to large
x,best=metric(k,wh0)
bpr,aat=(best>thr).float().mean(),(x>thr).float().mean()*n#best possible recall,anch>thr
print(f'{prefix}thr={thr:.2f}:{bpr:.4f}best possible recall,{aat:.2f}anchors past thr')
print(f'{prefix}n={n},img_size={img_size},metric_all={x.mean():.3f}/{best.mean():.3f}-mean/best,'
f'past_thr={x[x>thr].mean():.3f}-mean:',end='')
for i,x in enumerate(k):
print('%i,%i'%(round(x[0]),round(x[1])),end=','if i<len(k)-1 else'n')#use in*.cfg
return k
if isinstance(path,str):#*.yaml file
with open(path)as f:
data_dict=yaml.load(f,Loader=yaml.SafeLoader)#model dict
from utils.datasets import LoadImagesAndLabels
dataset=LoadImagesAndLabels(data_dict['train'],augment=True,rect=True)
else:
dataset=path#dataset
#Get label wh
shapes=img_size*dataset.shapes/dataset.shapes.max(1,keepdims=True)
wh0=np.concatenate([l[:,3:5]*s for s,l in zip(shapes,dataset.labels)])#wh
#Filter
i=(wh0<3.0).any(1).sum()
if i:
print(f'{prefix}WARNING:Extremely small objects found.{i}of{len(wh0)}labels are<3 pixels in size.')
wh=wh0[(wh0>=2.0).any(1)]#filter>2 pixels
#wh=wh*(np.random.rand(wh.shape[0],1)*0.9+0.1)#multiply by random scale 0-1
#Kmeans calculation
print(f'{prefix}Running kmeans for{n}anchors on{len(wh)}points...')
s=wh.std(0)#sigmas for whitening
k,dist=kmeans(wh/s,n,iter=30)#points,mean distance
k*=s
wh=torch.tensor(wh,dtype=torch.float32)#filtered
wh0=torch.tensor(wh0,dtype=torch.float32)#unfiltered
k=print_results(k)
#Plot
#k,d=[None]*20,[None]*20
#for i in tqdm(range(1,21)):
#k[i-1],d[i-1]=kmeans(wh/s,i)#points,mean distance
#fig,ax=plt.subplots(1,2,figsize=(14,7),tight_layout=True)
#ax=ax.ravel()
#ax[0].plot(np.arange(1,21),np.array(d)**2,marker='.')
#fig,ax=plt.subplots(1,2,figsize=(14,7))#plot wh
#ax[0].hist(wh[wh[:,0]<100,0],400)
#ax[1].hist(wh[wh[:,1]<100,1],400)
#fig.savefig('wh.png',dpi=200)
#Evolve
npr=np.random
f,sh,mp,s=anchor_fitness(k),k.shape,0.9,0.1#fitness,generations,mutation prob,sigma
pbar=tqdm(range(gen),desc=f'{prefix}Evolving anchors with Genetic Algorithm:')#progress bar
for _ in pbar:
v=np.ones(sh)
while(v==1).all():#mutate until a change occurs(prevent duplicates)
v=((npr.random(sh)<mp)*npr.random()*npr.randn(*sh)*s+1).clip(0.3,3.0)
kg=(k.copy()*v).clip(min=2.0)
fg=anchor_fitness(kg)
if fg>f:
f,k=fg,kg.copy()
pbar.desc=f'{prefix}Evolving anchors with Genetic Algorithm:fitness={f:.4f}'
if verbose:
print_results(k)
return print_results(k)对kmean_anchors()函数中的主要参数做个简单的解释(编码中有了英语注解):
path:包括数据信息目标文件夹等信息的yaml文档(例如coco128.yaml),或是数据信息偏微分(yolov5快速计算导向框时就是通过的这种方法,先将数据信息标签信息载入再加工)
n:导向框的总数,既有几个;初始值是9
img_size:图像尺寸。估算数据信息样版标签框的高宽时,也是需要缩放进img_size尺寸之后再计算出来的;初始值是640
thr:数据信息集中标注框高宽较大阀值,默认设置是采用超参文档hyp.scratch.yaml里的“anchor_t”变量值;初始值是4.0;快速计算时,就会自动根据自己所采用的数据信息,进行计算适宜的阀值。
gen:kmean聚类算法迭代次数,初始值是1000
verbose:是不是打印全部数值,初始值是true
如果不想快速计算导向框,还可以在train.py中设定主要参数就可以:
parser.add_argument('--noautoanchor',action='store_true',help='disableautoanchorcheck')2、练习前手动式估算导向框
如果采用yolov5运动效果并不好(清除其他问题,只关心“预置导向框”这些因素),yolov5在审查默认设置导向框是不是符合标准时,计算出来的最好均方误差超过0.98,并没有快速计算导向框;这时也可以自己手动式估算导向框。【就算自己的信息集中化总体目标高宽最高值低于4,默认设置导向框不一定是最理想的】
最先可以自己编写一个程序,统计一下你所能锻炼的数据信息全部标签框高宽,看看高宽关键遍布在哪些范畴、较大高宽多少钱?例如:你应用的信息集中化总体目标高宽较大达到5:1(乃至10:1),那还是需要重算导向框了,对于coco数据信息的主要高宽是4:1。
随后在yolov5系统中构建一个新的python文件test.py,手动式估算导向框:
import utils.autoanchor as autoAC
#对数据集重新计算anchors
new_anchors=autoAC.kmean_anchors('./data/mydata.yaml',9,640,5.0,1000,True)
print(new_anchors)
输入信息如下(只截取了部分):
autoanchor:Evolving anchors with Genetic Algorithm:fitness=0.6604:87%|████████▋|866/1000[00:00<00:00,2124.00it/s]autoanchor:thr=0.25:0.9839 best possible recall,3.84 anchors past thr
autoanchor:n=9,img_size=640,metric_all=0.267/0.662-mean/best,past_thr=0.476-mean:15,20,38,25,55,65,131,87,97,174,139,291,256,242,368,382,565,422
autoanchor:thr=0.25:0.9849 best possible recall,3.84 anchors past thr
autoanchor:n=9,img_size=640,metric_all=0.267/0.663-mean/best,past_thr=0.476-mean:15,20,39,26,54,64,127,87,97,176,142,286,257,245,374,379,582,424
autoanchor:thr=0.25:0.9849 best possible recall,3.84 anchors past thr
autoanchor:n=9,img_size=640,metric_all=0.267/0.663-mean/best,past_thr=0.476-mean:15,20,39,26,54,63,126,86,97,176,143,285,258,241,369,381,583,424
autoanchor:thr=0.25:0.9849 best possible recall,3.84 anchors past thr
autoanchor:n=9,img_size=640,metric_all=0.267/0.663-mean/best,past_thr=0.476-mean:15,20,39,26,54,63,127,86,97,176,143,285,258,241,369,380,583,424
autoanchor:thr=0.25:0.9849 best possible recall,3.84 anchors past thr
autoanchor:n=9,img_size=640,metric_all=0.267/0.663-mean/best,past_thr=0.476-mean:15,20,39,26,53,63,127,86,97,175,143,284,257,243,369,381,582,422
autoanchor:thr=0.25:0.9849 best possible recall,3.84 anchors past thr
autoanchor:n=9,img_size=640,metric_all=0.267/0.663-mean/best,past_thr=0.476-mean:15,20,40,26,53,62,129,85,96,175,143,287,256,240,370,378,582,419
autoanchor:Evolving anchors with Genetic Algorithm:fitness=0.6605:100%|██████████|1000/1000[00:00<00:00,2170.29it/s]
Scanning'..coco128labelstrain2017.cache'for images and labels...128 found,0 missing,2 empty,0 corrupted:100%|██████████|128/128[00:00<?,?it/s]
autoanchor:thr=0.25:0.9849 best possible recall,3.84 anchors past thr
autoanchor:n=9,img_size=640,metric_all=0.267/0.663-mean/best,past_thr=0.476-mean:15,20,40,26,53,62,129,85,96,175,143,287,256,240,370,378,582,419
[[14.931 20.439]
[39.648 25.53]
[53.371 62.35]
[129.07 84.774]
[95.719 175.08]
[142.69 286.95]
[256.46 239.83]
[369.9 378.3]
[581.87 418.56]]
Process finished with exit code 0输出的9组新的锚定框即是根据自己的数据集来计算的,可以按照顺序替换到你所使用的配置文件*.yaml中(比如yolov5s.yaml)。就可以重新训练了。
参考的博文(表示感谢!):
https://github.com/ultralytics/yolov5
https://blog.csdn.net/flyfish1986/article/details/117594265
https://zhuanlan.zhihu.com/p/183838757
https://blog.csdn.net/aabbcccffffd01/article/details/109578614
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/130263.html
如今yolov5的neck用的都是PANet,在efficient文章中给出了BiFPN结构,也有更为很不错的特性,接下来本文关键为大家介绍了对于如何将yolov5里的PANet层改成BiFPN的资料,需用的小伙伴可以借鉴一下 一、Add 1.在common.py后放入如下所示编码 #融合BiFPN设定可学习培训主要参数学习培训不一样支系的权重值 #2个支系add实际操作 cl...
如今yolov5的neck用的都是PANet,在efficient文章中给出了BiFPN结构,也有更为很不错的特性,接下来本文关键为大家介绍了对于如何将yolov5里的PANet层改成BiFPN的资料,必须的小伙伴可以借鉴一下 一、Add 1.在common.py后放入如下所示编码 #融合BiFPN设定可学习培训主要参数学习培训差异支系的权重值 #2个支系add实际操作 clas...
摘要:结论正确检测小物体确实是一个挑战。下载视觉实战项目讲在小白学视觉公众号后台回复视觉实战项目,即可下载包括图像分割口罩检测车道线检测车辆计数添加眼线车牌识别字符识别情绪检测文本内容提取面部识别等个视觉实战项目,助力快速学校计算机视觉。 点击上方小白学视觉,选择加星标或置顶 重磅干货,第一时...
阅读 1230·2023-01-14 11:38
阅读 1252·2023-01-14 11:04
阅读 1042·2023-01-14 10:48
阅读 2728·2023-01-14 10:34
阅读 1347·2023-01-14 10:24
阅读 1223·2023-01-14 10:18
阅读 779·2023-01-14 10:09
阅读 895·2023-01-14 10:02