K-means 计算 anchor boxes

k-means原理

K-means算法是很典型的基于距离的聚类算法,采用距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度就越大。该算法认为簇是由距离靠近的对象组成的,因此把得到紧凑且独立的簇作为最终目标。

问题

K-Means算法主要解决的问题如下图所示。我们可以看到,在图的左边有一些点,我们用肉眼可以看出来有四个点群,K-Means算法被用来找出这几个点群。
这里写图片描述

算法概要

这里写图片描述

从上图中,我们可以看到,A, B, C, D, E 是五个在图中点。而灰色的点是我们的种子点,也就是我们用来找点群的点。有两个种子点,所以K=2。

然后,K-Means的算法如下:

随机在图中取K(这里K=2)个种子点。
然后对图中的所有点求到这K个种子点的距离,假如点Pi离种子点Si最近,那么Pi属于Si点群。(上图中,我们可以看到A,B属于上面的种子点,C,D,E属于下面中部的种子点)
接下来,我们要移动种子点到属于他的“点群”的中心。(见图上的第三步)
然后重复第2)和第3)步,直到,种子点没有移动(我们可以看到图中的第四步上面的种子点聚合了A,B,C,下面的种子点聚合了D,E)。

k-means算法缺点

1、需要提前指定k
2、k-means算法对种子点的初始化非常敏感

k-means++算法

k-means++是选择初始种子点的一种算法,其基本思想是:初始的聚类中心之间的相互距离要尽可能的远。

方法如下:
1.从输入的数据点集合中随机选择一个点作为第一个聚类中心
2.对于数据集中的每一个点x,计算它与最近聚类中心(指已选择的聚类中心)的距离D(x)
3.选择一个新的数据点作为新的聚类中心,选择的原则是:D(x)较大的点,被选取作为聚类中心的概率较大
4.重复2和3直到k个聚类中心被选出来
5.利用这k个初始的聚类中心来运行标准的k-means算法

第2、3步选择新点的方法如下:
a.对于每个点,我们都计算其和最近的一个“种子点”的距离D(x)并保存在一个数组里,然后把这些距离加起来得到Sum(D(x))。
b.然后,再取一个随机值,用权重的方式来取计算下一个“种子点”。这个算法的实现是,先用Sum(D(x))乘以随机值Random得到值r,然后用currSum += D(x),直到其currSum>r,此时的点就是下一个“种子点”。原因见下图:

### 使用IOU距离进行K-means聚类以生成锚点框 为了提高目标检测模型的性能,通常会通过预定义一组锚点框来辅助边界框预测。这些锚点框应当能够很好地覆盖训练集中物体的真实尺寸分布。为此,可以采用基于交并比(Intersection over Union, IoU)的距离度量来进行k-means聚类算法。 #### K-means聚类原理概述 传统的欧氏距离用于衡量两个样本之间的相似程度,在这里不适合用来评估不同形状大小的目标框间的差异性。因此引入了IoU作为新的距离度量标准。具体来说,对于任意给定的一对真实标签框\(b_1\)和候选框\(b_2\), 它们的IoU计算方式如下: \[ \text{IoU}(b_1,b_2)=\frac{\text{Area}_{(intersection)}} {\text{Area}_{(union)}}=\frac{(b_{min}^{x}, b_{max}^{y})-(b_{max}^{x}, b_{min}^{y})}{A(b_1)+A(b_2)-A(\text{intersection})}\] 其中 \(A()\) 表示面积函数;下标 min 和 max 分别表示取最小值与最大值操作。当且仅当两矩形重叠部分不为空时该表达式才有意义[^2]。 #### 实现过程中的注意事项 考虑到实际应用中可能存在大量标注数据,直接对其进行暴力搜索效率低下。所以一般先随机选取若干初始中心点,再迭代更新直至收敛得到最终簇心集合。值得注意的是,由于图像内可能出现多个密集排列的小物件情况,这会给传统方法带来挑战[^3]。此时应适当调整参数设置或尝试其他改进策略如DenseBox等。 下面给出一段Python代码实现上述思路: ```python import numpy as np def iou(box, clusters): """ 计算单个box与其他cluster成员的最大iou值. 参数: box (array): 单个ground truth bbox [width, height]. clusters (numpy array): 所有当前clusters [[w,h],...,[wn,hn]]. 返回: float: 最大IoU分数. """ x = np.minimum(clusters[:, 0], box[0]) y = np.minimum(clusters[:, 1], box[1]) intersection = x * y area_box = box[0] * box[1] areas_clusters = clusters[:, 0] * clusters[:, 1] union = area_box + areas_clusters - intersection return intersection / union.max() def kmeans(boxes, k=9): """执行k-mean++初始化后的k-means聚类.""" num_boxes = len(boxes) distances = np.empty((num_boxes,k)) last_nearest=np.ones(num_boxes) cluster_indices=[np.random.randint(low=0, high=num_boxes)] centroids = boxes[cluster_indices].copy() for _ in range(k-1): D2=(1-iou_matrix(centroids, boxes)).sum(axis=-1)**2 probs=D2/D2.sum() cumulative_probs=np.cumsum(probs) r=np.random.rand() index=int(np.searchsorted(cumulative_probs,r)) if not index in cluster_indices: cluster_indices.append(index) centroids = boxes[cluster_indices].copy() while True: for idx in range(len(centroids)): distances[:,idx]=1-iou(boxes[idx], centroids) nearest=np.argmin(distances,axis=1) if (last_nearest==nearest).all(): break for idx in range(k): mask=(nearest==idx) if sum(mask)>0: centroids[idx]=(boxes[mask]).mean(axis=0) last_nearest=nearest.copy() return centroids if __name__=='__main__': # 假设我们有一个包含所有bounding box宽度高度信息的数据集 dataset = [...] # 这里应该加载真实的bbox宽高列表 anchors=kmeans(dataset, k=9) print('Anchor Boxes:', anchors.tolist()) ``` 此段程序实现了利用IoU距离完成k-means聚类的过程,并输出最优解——即九组最佳匹配的锚点框尺寸。需要注意的是`dataset`变量需替换为从特定任务领域收集到的实际测量数值。
评论 66
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值