# yolov5中anchors设定案例详细说明

> 作者/来源: UCloud 运营管理员
> 发布时间: 2023-01-12T06:13:00.000Z
> 分类: 推荐奖励
> 标签: AI, Python
> 原文链接: http://117.50.162.249:3000/yun/articles/635

---

# yolov5中anchors设定案例详细说明

> 来源: https://www.ucloud.cn/yun/130263.html
> 作者: 89542767
> 发布日期: 发布于2023-01-12 14:13

在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&gt;1./thr).float().sum(1).mean()#anchorsabovethreshold
　　bpr=(best&gt;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&gt;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&gt;thr).float().mean(),(x&gt;thr).float().mean()*n#best possible recall,anch&gt;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&gt;thr].mean():.3f}-mean:',end='')
　　for i,x in enumerate(k):
　　print('%i,%i'%(round(x[0]),round(x[1])),end=','if i&lt;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&lt;3.0).any(1).sum()
　　if i:
　　print(f'{prefix}WARNING:Extremely small objects found.{i}of{len(wh0)}labels are&lt;3 pixels in size.')
　　wh=wh0[(wh0&gt;=2.0).any(1)]#filter&gt;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]&lt;100,0],400)
　　#ax[1].hist(wh[wh[:,1]&lt;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)&lt;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&gt;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&lt;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&lt;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&lt;?,?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