• 机器学习-二分KMeans


    机器学习-二分KMeans

    由于传统的KMeans算法的聚类结果容易受到初始聚类中心点选择的影响,因此在传统的KMeans算法的基础上进行算法改进,对初始中心点选取比较严格,各中心点的距离较远,这就避免了初始聚类中心会选到一个类上,一定程度上克服了算法限入局部最优状态。

    二分KMeans(Bisecting KMeans)算法的主要思想是:首先将所有点作为一个簇,然后将该簇一分为二。之后选择能最大限度降低聚类代价函数(误差平方和)的簇划分为两个簇。以此进行下去,直到簇的数目等于用户给定的数目k为止。以上隐含的一个原则是:因为聚类的误差平方和能够衡量聚类性能,该值越小表示数据点越接近于它们的质心,聚类效果就越好。所以我们需要对误差平方和最大的簇进行再一次划分,因为误差平方和越大,表示该簇聚类效果越不好,越有可能是多个簇被当成了一个簇,所以我们首先需要对这个簇进行划分。

    代码实现(其中的kmeans方法参照上一篇)

    # 二分kmeans实现
    
    from numpy import *
    import matplotlib.pyplot as plt
    
    # 数据文件转矩阵
    from sklearn.cluster import KMeans
    
    from com.machineLearning.kmeans.KmeansSelf import kMeans
    
    
    def file2matrix(filePath):
        dataSet = []
        fr = open(filePath, 'r')
        content = fr.read()
        for line in content.splitlines():
            dataSet.append([line.split('	')[0], line.split('	')[1]])
        fr.close()
        return dataSet
    
    # 欧氏距离公式
    def distEclud(vecA, vecB):
        return linalg.norm(vecA.astype(float) - vecB.astype(float))
    
    # 根据聚类中心绘制散点图,以及绘制聚类中心
    def color_cluster(dataindx, dataSet, plt, k=4):
        # print(dataindx)
        plt.scatter(dataSet[:, 0].tolist(), dataSet[:, 1].tolist(), c='blue', marker='o')
        # index = 0
        # datalen = len(dataindx)
        # for indx in range(datalen):
        #     if int(dataindx[index]) == 0:
        #         plt.scatter(dataSet[index, 0].tolist(),dataSet[index, 1].tolist(), c='blue', marker='o')
        #     elif int(dataindx[index]) == 1:
        #         plt.scatter(dataSet[index, 0].tolist(), dataSet[index, 1].tolist(), c='green', marker='o')
        #     elif int(dataindx[index]) == 2:
        #         plt.scatter(dataSet[index, 0].tolist(), dataSet[index, 1].tolist(), c='red', marker='o')
        #     elif int(dataindx[index]) == 3:
        #         plt.scatter(dataSet[index, 0].tolist(), dataSet[index, 1].tolist(), c='cyan', marker='o')
        #     index += 1
    
    # 绘制散点图
    def drawScatter(plt, mydata, size=20, color='blue', mrkr='o'):
        # print(mydata.T[0][0].tolist())
        # print(mydata.T[1][0].tolist())
        plt.scatter(mydata.T[0][0].tolist(), mydata.T[1][0].tolist(), s=size, c=color, marker=mrkr)
    
    dataMat = file2matrix("/Users/FengZhen/Desktop/accumulate/机器学习/推荐系统/kmeans聚类测试集.txt")  # 从文件构建的数据集
    dataSet = mat(dataMat).astype(float)   # 转换为矩阵形式
    k = 4   # 分类数
    m = dataSet.shape[0]    # 行数
    # axis 不设置值,对 m*n 个数求均值,返回一个实数
    # axis = 0:压缩行,对各列求均值,返回 1* n 矩阵
    # axis =1 :压缩列,对各行求均值,返回 m *1 矩阵
    centroid0 = mean(dataSet, axis=0)[0]   # 初始化第一个聚类中心:每一列的均值
    centList = [centroid0]  # 把均值聚类中心加入中心表中
    ClustDist = mat(zeros((m, 2)))  # 初始化聚类距离表,距离方差,每组数据到中心点的距离
    for j in range(m):
        ClustDist[j, 1] = distEclud(centroid0, dataSet[j, :])**2
    
    
    while(len(centList) < k):
        lowestSSE = inf    # 初始化最小误差平方和。核心参数,这个值越小说明聚类的效果越好
        for i in range(len(centList)):
            print(i)
            ptsInCurrCluster = dataSet[nonzero(ClustDist[:, 0].A == i)[0], :]   # .A为转换数组
            # centroidMat:中心点, splitClustAss:所属分类,距离
            centroidMat, splitClustAss = kMeans(ptsInCurrCluster, 2)
            # 计算所有距离和
            sseSplit = sum(splitClustAss[:, 1])     # 计算splitClustAss的距离平方和
            sseNotSplit = sum(ClustDist[nonzero(ClustDist[:, 0].A != i)[0], 1]) # 计算ClustDist第一列不等于i的距离平方和
            if(sseSplit + sseNotSplit) < lowestSSE:
                bestCentToSplit = i     # 确定聚类中心的最优分隔点
                bestNewCents = centroidMat  # 用新的聚类中心更新最优聚类中心
                bestClustAss = splitClustAss.copy() # 用深拷贝聚类距离表为最优聚类距离表
                lowestSSE = sseSplit + sseNotSplit  # 更新lowestSSE
        # bestClustAss 赋值为聚类中心的索引
        # 第一部分:bestClustAss[bIndx0,0]赋值为聚类中心的索引
        bestClustAss[nonzero(bestClustAss[:, 0].A == 1)[0], 0] = len(centList)
        # 用最优分隔点的指定聚类中心索引
        bestClustAss[nonzero(bestClustAss[:, 0].A == 0)[0], 0] = bestCentToSplit
    
        # 覆盖:bestNewCents[0, :].tolist()[0]附加到原有聚类中心的bestCentToSplit位置
        centList[bestCentToSplit] = bestNewCents[0, :].tolist()[0]
        # 增加:聚类中心增加一个新的bestNewCents[1, :].tolist()[0]向量
        centList.append(bestNewCents[1, :].tolist()[0])
        ClustDist[nonzero(ClustDist[:, 0].A == bestCentToSplit)[0], :] = bestClustAss
    
    color_cluster(ClustDist[:, 0:1], dataSet, plt)
    # print("centList:", mat(centList))
    drawScatter(plt, mat(centList), size=60, color='red', mrkr='D')
    plt.show()

    效果如下

  • 相关阅读:
    lvs实现故障转移(backup)
    shell计算
    CEGUI 聊天对话框
    SetRenderState 设置渲染状态【转】
    MFC 弹出对话框
    DrawIndexedPrimitive函数的详细解释【转】
    IDirect3DDevice9::Clear 【转】
    manifest 文件错误
    D3DXMatrixLookAtLH 【转】
    D3D中的网格(Mesh)
  • 原文地址:https://www.cnblogs.com/EnzoDin/p/12528003.html
Copyright © 2020-2023  润新知