有时候GMM-UBM的初始化可以采用k-means方法,k-means的原理很简单,但是也存在很多的优缺点。
K-means算法是硬聚类算法,是典型的基于原型的目标函数聚类方法的代表,它是数据点到原型的某种距离作为优化的目标函数,利用函数求极值的方法得到迭代运算的调整规则。(百度百科)
硬聚类算法就是一个点全部判定为属于哪个类或者不属于哪个类,很容易陷入局部最优导致高斯模型稳定性不好
算法的基本过程:
1.首先根据问题的规模和要求,确定要分成几类,这个K值是必须给出的。 K值的给出很关键,这里我们简单起见直接给出。当然也有比较好的初始化K值的方法,比如:与层次聚类结合, 稳定性方法, 系统演化方法, 使用canopy算法进行初始划分。
canopy算法:
Stage1、聚类最耗费计算的地方是计算对象相似性的时候,Canopy Method在第一阶段选择简单、计算代价较低的方法计算对象相似性,将相似的对象放在一个子集中,这个子集被叫做Canopy ,通过一系列计算得到若干Canopy,Canopy之间可以是重叠的,但不会存在某个对象不属于任何Canopy的情况,可以把这一阶段看做数据预处理;
Stage2、在各个Canopy 内使用传统的聚类方法(如K-means),不属于同一Canopy 的对象之间不进行相似性计算。
从这个方法起码可以看出两点好处:首先,Canopy 不要太大且Canopy 之间重叠的不要太多的话会大大减少后续需要计算相似性的对象的个数;其次,类似于K-means这样的聚类方法是需要人为指出K的值的,通过Stage1得到的Canopy 个数完全可以作为这个K值,一定程度上减少了选择K的盲目性
具体参考:http://blog.youkuaiyun.com/qll125596718/article/details/8243404/#t2
2.k个初始质心的选择。
选择适当的初始质心是基本kmeans算法的关键步骤。常见的方法是随机的选取初始质心,但是这样簇的质量常常很差。我们通常采取下面几种做法:
1),多次运行,每次使用一组不同的随机初始质心,然后选取具有最小SSE(误差的平方和)的簇集。这种策略简单,但是效果可能不好,这取决于数据集和寻找的簇的个数。
2),取一个样本,并使用层次聚类技术对它聚类。从层次聚类中提取K个簇,并用这些簇的质心作为初始质心。该方法通常很有效,但仅对下列情况有效:(1)样本相对较小,例如数百到数千(层次聚类开销较大)(2)K相对于样本大小较小
3),随机地选择第一个点,或取所有点的质心作为第一个点。然后,对于每个后继初始质心,选择离已经选取过的初始质心最远的点。使用这种方法,确保了选择的初始质心不仅是随机的,而且是散开的。(但是,这种方法可能选中离群点。此外,求离当前初始质心集最远的点开销也非常大)
4),canopy算法
3. 计算每个点到每个质心的距离(一般用欧式距离),将每一个点划分到距离最近的质心所在的类中,重新计算质心,然后重新对每个点进行划分
4. 终止条件
1),直到没有点移动
2),直到每个质心都与上一次的质心的差小于一个阈值
3),直到计算每一个类中的距离,所有类的距离之和小于某个阈值
4),直达达到某一个最大迭代次数
优点: 原理简单,实现也比较简单,聚类效果也还可以
缺点:
K不好确定
质心选择影响比较大,如果选第三种的话,容易造成离群点
算法复杂度不好控制O(NKM), N 点的个数,K 类的个数,M是迭代次数
初始点选不好可能会局部最优
结果不稳定
无法增量计算
python 代码实现:
一个开源的demo:https://github.com/kjahan/k-means
数据需要自己从网站上下载,下载csv格式的,然后main函数里