聚类kmeans算法在yolov3中的应用

yolov3在做boundingbox预测的时候,用到了anchor boxes.这个anchors的含义即最有可能的object的width,height.事先通过聚类得到.比如某一个像素单元,我想对这个像素单元预测出一个object,围绕这个像素单元,可以预测出无数种object的形状,并不是随便预测的,要参考anchor box的大小,即从已标注的数据中通过聚类统计到的最有可能的object的形状.

.cfg文件内的配置如下:

[yolo] mask = 3,4,5 anchors = 10,14, 23,27, 37,58, 81,82, 135,169, 344,319

在用我们自己的数据做训练的时候,要先修改anchors,匹配我们自己的数据.anchors大小通过聚类得到.

通俗地说,聚类就是把挨得近的数据点划分到一起.
kmeans算法的思想很简单

随便指定k个cluster

把点划分到与之最近的一个cluster

上面得到的cluster肯定是不好的,因为一开始的cluster是乱选的嘛

更新每个cluster为当前cluster的点的均值.
这时候cluster肯定变准了,为什么呢?比如当前这个cluster里有3个点,2个点靠的很近,还有1个点离得稍微远点,那取均值的话,那相当于靠的很近的2个点有更多投票权,新算出来的cluster的中心会更加靠近这两个点.你要是非要抬杠:那万一一开始我随机指定的cluster中心点就特别准呢,重新取均值反而把中心点弄的不准了?事实上这是kmeans的一个缺陷:比较依赖初始的k个cluster的位置.选择不恰当的k值可能会导致糟糕的聚类结果。这也是为什么要进行特征检查来决定数据集的聚类数目了。

重新执行上述过程

把点划分到与之最近的一个cluster

更新每个cluster为当前cluster的点的均值

不断重复上述过程,直至cluster中心变化很小

yolov3要求的label文件格式 <object-class> <x_center> <y_center> <width> <height> Where: <object-class> - integer object number from 0 to (classes-1) <x_center> <y_center> <width> <height> - float values relative to width and height of image, it can be equal from (0.0 to 1.0] > for example: <x> = <absolute_x> / <image_width> or <height> = <absolute_height> / <image_height> atention: <x_center> <y_center> - are center of rectangle (are not top-left corner)

举例:
1 0.716797 0.395833 0.216406 0.147222
所有的值都是比例.(中心点x,中心点y,目标宽,目标高)

kmeans实现

一般来说,计算样本点到质心的距离的时候直接算的是两点之间的距离,然后将样本点划归为与之距离最近的一个质心.
在yolov3中样本点的数据是有具体的业务上的含义的,我们其实最终目的是想知道最有可能的object对应的bounding box的形状是什么样子的. 所以这个距离的计算我们并不是直接算两点之间的距离,我们计算两个box的iou,即2个box的相似程度.d=1-iou(box1,box_cluster). 这样d越小,说明box1与box_cluster越类似.将box划归为box_cluster.

数据加载 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_dims)

看着一大段,其实重点就一句

w,h = line.split(' ')[3:] annotation_dims.append(tuple(map(float,(w,h))))

这里涉及到了python的语法,map用法https://www.runoob.com/python/python-func-map.html
这样就生成了一个N*2矩阵. N代表你的样本个数.

定义样本点到质心点的距离
计算样本x代表的box和k个质心box的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) 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

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zygyws.html