kemeas算法继续优化——elkan kmeas算法

题记:又是凌晨3点的夜*
kemeas算法继续优化——elkan kmeas算法_第1张图片

elkan kmeans算法

在我的上一篇博客《kmeans算法性能改进_kmeans++算法+kmeans++优化算法+距离计算优化》中,在一般kmeans算法的基础上,添加了对于初始条件和距离计算更上的一些优化技巧。这篇博客聊一聊elkan算法,其实也是对于kmeans运行速度的优化算法。主要作用与kmeans的距离计算过程。
原理
kemeas算法继续优化——elkan kmeas算法_第2张图片
假如我们已经知道任意两个样本之间的距离,再假设我们已经知道了样本1与聚类中心1之间的距离,根据三角性两边之和大于第三边,c+d>a,所以如果c

elkan kmean算法实现

在我前面两篇文章的基础上,添加一个计算两条样本间欧氏距离的函数:

def distTwoSample(x,y):
    tol=x-y
    return np.sqrt(np.einsum("i,i->",tol,tol))

elkan kmeas完整代码如下(其实就是在我前两章博客的基础上添加了12行代码,性能我就不展示了),总体感觉哪里还可以优化,不是我认为的最好代码(就是有这种直觉,以后灵光乍现再来完善):

import pandas as pd
import numpy as np
import copy
from core.myviews.views import viewResult
from core.cluster.caculationDistance import euclideanDistance,\
                                          squaredNornal,relativeDist,distTwoSample
#自己写kmeans
if __name__ == '__main__':

    """
    在kMeansRow.py的基础上增加初始位置选取策略
    kmeans算法的实施过程
    -----------------
    1、确定初始位置
        1.1用最简单的随机生成的方法
        1.2用kMeans++改进初始位置的产生(本文的重点)
            http://ilpubs.stanford.edu:8090/778/1/2006-13.pdf
            算法过程:
            1.2.1随机的产生一个点
            1.2.2首先计算每个样本与已有聚类中心的最短距离(即离得最近的那个样本的距离);接着计算每个样本被选为
                下一个聚类中心的概率(D(X)^2/SUM(D(X)^2))。
                分析:可以思考一下为什么要选用欧式距离的平方?其实可以看一下我们计算欧式距离的过程
                    其实取欧式距离的平方是可以起到降低计算量的目的的,少了开方的过程
            1.2.3对1.2.2中的点根据概率采用轮盘赌法进行选择直到采样完成
    2、进行若干次的循环:
        2.1将剩下的样本根据距离划入相应的簇中
        2.2计算新的簇中心
        2.3如果新簇与老簇达到了结束条件,就提前退出
    3、输出结果
    """
    n_cluster=3
    maxItem=300
    tol=1e-8#停止条件,即center的改变的误差平方和(f范数)

    matrix_data=np.asarray(pd.read_csv("../../state/rawData/CompleteOrder.csv",header=None))
    n_samples,n_feature=matrix_data.shape
    # seed=np.random.permutation(n_samples)[:n_cluster]
    # center=matrix_data[seed]
    center=np.zeros((n_cluster,n_feature))
    center[0]=matrix_data[np.random.randint(n_samples)]
    #初始化
    for i in range(1,n_cluster):
        #计算每个样本点到已有中心点的距离
        distance_to_centers=euclideanDistance(matrix_data,center[[i for i in range(i)]],square=True)
        #选取据距离最小值
        closed_distance=np.min(distance_to_centers,axis=1)
        #轮盘赌
        denominator=closed_distance.sum()
        point=np.random.rand()*denominator#轮盘赌的指针
        be_choosed=np.searchsorted(np.cumsum(closed_distance),point)
        be_choosed=min(be_choosed,n_samples-1)#避免选的是最后一个而造成下标越界
        center[i]=matrix_data[be_choosed]

    for i in range(maxItem):
        #可以发现kmeans算法的后续操作都是基于labels的,ralative_distance也是只为
        #labels服务的,所以如果说距离计算上能够优化就更完美了
        # relative_distance=relativeDist(matrix_data,center)
        # labels=np.argmin(relative_distance,axis=1)

        # elkan过程
        # 计算各个cluster center 之间的距离
        dist_center_half = euclideanDistance(center, center) / 2
        labels=np.zeros(n_samples,dtype=int)
        for i in range(n_samples):
            min_dist = distTwoSample(matrix_data[i],center[0])
            minLabel=0
            for j in range(1,n_cluster):
                if min_dist>dist_center_half[minLabel,j]:
                    thisDist=distTwoSample(matrix_data[i],center[j])
                    if thisDist<min_dist:
                        min_dist=thisDist
                        minLabel=j
            labels[i]=minLabel

        #计算聚类中心
        new_center=np.zeros((n_cluster,n_feature))
        num_center=np.zeros(n_cluster)
        for r,v in enumerate(labels):
            new_center[v]+=matrix_data[r]
            num_center[v]+=1
        #out不开辟新的临时变量
        np.maximum(num_center,1,out=num_center)#防止除0
        np.reciprocal(num_center,dtype=float,out=num_center)
        np.einsum("ij,i->ij",new_center,num_center.T,out=new_center)
        # 用f范数评价
        center_shift_total=squaredNornal(center-new_center)
        if squaredNornal(center_shift_total<tol):
            break
        center=copy.deepcopy(new_center)
    print("迭代次数%s,聚类中心最小偏移平方和%s"%(i,center_shift_total))
    print("-----下面打印统计指标------")
    viewResult(matrix_data,labels,center,"elkanKmeans")

后记:其实我还是喜欢飞翔的

你可能感兴趣的:(算法,数学,算法,聚类,python,机器学习,elkan,kmeans)