提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
一、yolo模型和kmeans算法
yolo模型是啥我这里就不多做介绍了,搜索能有一堆大佬解释的很仔细。
kmeans算法是如何与yolo模型结合,又是如何实现模型优化的呢?
解释:
yolo系列的模型在做boundingbox预测的时候,使用了anchor boxes锚框。
.cfg文件内配置如下:
[yolo]
mask = 3,4,5
anchors = 10,14, 23,27, 37,58, 81,82, 135,169, 344,319
主要是用来表示最有可能的object的w和h,所以当模型对一个像素单元进行预测时,会预测出无数个object的框,但是并不能随便预测,主要是要参考anchor box大小,即从已标注的数据中统计到最有可能的object形状。
那这个时候,如果anchor box能够更好的被算出来,那么这个模型就能够更快、更好的框出物品。
在用自己的数据做训练的时候,要先修改anchors,匹配我们⾃⼰的数据,anchors大小通过kmeans聚类得到。
二、优化实现(附代码)
1.kmeans实现
一般来说,计算样本点到质点的距离时,直接算的是两点的距离,然后将样本点划归为距离最小的那个质心。在yolo系列模型中样本点的数据是有具体的业务上的含义,我们其实最终目的是想要知道最有可能的object对应的bounding box的形状。
所以在kmeans算法中,样本点到质点的距离被替换成两个box的iou,即2个box的相似度。d=1-iou(box1,box_cluster),这样d越小,box1与box_cluster越类似,将box划归为box_cluster。
2.读入数据
注:
yolo模型有自己的标注格式: <x_center> <y_center>
普通labelme标注生成的json文件,在输入数据之前要转换成对应的标注格式哦。
f = open(args.filelist)
lines = [line.rstrip('\n') for line in f.readlines()]
annotation_dims = []
size = np.zeros((1,1,3))
for line in lines:
#line = line.replace('images','labels')
#line = line.replace('img1','labels')
line = line.replace('JPEGImages','labels')
line = line.replace('.jpg','.txt')
#line = line.replace('.png','.txt')
print(line)
f2 = open(line)
for line in f2.readlines():
line = line.rstrip('\n')
w,h = line.split(' ')[3:]
#print(w,h)
annotation_dims.append(tuple(map(float,(w,h))))
annotation_dims = np.array(annotation_dim)
感觉好像有一堆,但实际上主要是这一句:
w,h = line.split(' ')[3:]
annotation_dims.append(tuple(map(float,(w,h))
3.功能函数实现
1.IOU计算
需要定义样本点到质⼼点的距离。
计算样本x代表的box和k个质心box_cluster的IOU。(即⽐较box之间的形状相似程度)。IOU:即交并集⽐例,交叉⾯积/总⾯积。
def IOU(x,centroids):
similarities = []
k = len(centroids)
for centroid in centroids:
c_w,c_h = centroid
w,h = x
if c_w>=w and c_h>=h: #box(c_w,c_h)完全包含box(w,h)
similarity = w*h/(c_w*c_h)
elif c_w>=w and c_h<=h: #box(c_w,c_h)宽⽽扁平
similarity = w*c_h/(w*h + (c_w-w)*c_h)
elif c_w<=w and c_h>=h:
similarity = c_w*h/(w*h + c_w*(c_h-h))
else: #means both w,h are bigger than c_w and c_h respectively
similarity = (c_w*c_h)/(w*h)
similarities.append(similarity) # will become (k,) shape
return np.array(similarities)
2.kmeans实现
def kmeans(X,centroids,eps,anchor_file):
N = X.shape[0]
iterations = 0
k,dim = centroids.shape
prev_assignments = np.ones(N)*(-1)
iter = 0
old_D = np.zeros((N,k)) #距离矩阵 N个点,每个点到k个质⼼共计N*K个距离
while True:
D = []
iter+=1
for i in range(N):
d = 1 - IOU(X[i],centroids) #d是⼀个k维的
D.append(d)
D = np.array(D) # D.shape = (N,k)
print("iter {}: dists = {}".format(iter,np.sum(np.abs(old_D-D))))
#assign samples to centroids
assignments = np.argmin(D,axis=1) #返回每⼀⾏的最⼩值的下标.即当前样本应该归为k个质⼼中的哪⼀个质⼼.
if (assignments == prev_assignments).all() : #质⼼已经不再变化
print("Centroids = ",centroids)
write_anchors_to_file(centroids,X,anchor_file)
return
#calculate new centroids
centroid_sums=np.zeros((k,dim),np.float) #(k,2)
for i in range(N):
centroid_sums[assignments[i]]+=X[i] #将每⼀个样本划分到对应质⼼
for j in range(k):
centroids[j] = centroid_sums[j]/(np.sum(assignments==j)) #更新质⼼
prev_assignments = assignments.copy()
old_D = D.copy()
计算每个样本点到每⼀个cluster质心的距离 d = 1- IOU(X[i],centroids)表⽰样本点到每个cluster质心的距离。
np.argmin(D,axis=1)得到每⼀个样本点离哪个cluster质心最近
argmin函数⽤法参考:https://docs.scipy.org/doc/numpy/reference/generated/numpy.argmin.html
计算每⼀个cluster中的样本点总和,取平均,更新cluster质⼼。
for i in range(N):
centroid_sums[assignments[i]]+=X[i] #将每⼀个样本划分到对应质⼼
for j in range(k):
centroids[j] = centroid_sums[j]/(np.sum(assignments==j)) #更新质⼼
不断重复上述过程,直到质心不再变化聚类完成。
保存聚类得到的anchor box大小。
KMeans优化YOLO模型:理解与代码实践
本文探讨了KMeans算法如何用于优化YOLO模型中的anchor boxes,通过计算box之间的IOU来确定最优形状。文中提供了一个详细的优化实现过程,包括KMeans的IOU距离计算和数据处理步骤,旨在提升模型对物体检测的效率和准确性。
2万+

被折叠的 条评论
为什么被折叠?



