zoukankan      html  css  js  c++  java
  • 二 k-means聚类算法的手动实现

    一、python实现k-means

    import numpy as np
    import pandas as pd
    import matplotlib as mpl
    import matplotlib.pyplot as plt
    %matplotlib inline
    
    #为了减少迭代次数,我们可以尽量把质心初始化在数据分布的内部
    def randCent(data, k):  #定义随机选取质心的函数
        data_min = data.iloc[:, :].min() #返回每一个特征的最小值
        data_max = data.iloc[:, :].max() #返回每一个特征的最大值
        data_cent = np.random.uniform(data_min,data_max,(k, data.shape[1]))#在最大值和最小值之间随机生成K个质心,返回k*data.shape[1]形状
        return data_cent 
    
    #将以上打包成函数,计算一个样本到所有质心的距离并且返回最小距离和对应的索引
    def one_sample_datacent_distance(one_sample, data_cent):
        one_sample_distance = np.sum(np.power((one_sample.values - data_cent), 2), axis=1)  #一个样本到所有质心的距离
        distance_min_values = one_sample_distance.min() #最小的距离的值
        distance_min_index  = np.where(one_sample_distance == distance_min_values)#距离最短的的索引
        return distance_min_values, distance_min_index
    
    
    
    def kmeans(data,k ):
        m, n = data.shape#提取出数据集的行列
        data_cent = randCent(data, k)
        
        add_3 = np.zeros((m,3))
        add_3[:,0] = np.inf
        add_3[:, 1: 3] = -1
        data_add_3 = pd.concat([data, pd.DataFrame(add_3)] , axis=1, ignore_index = True)
        
        clusterChanged = True #设定一个循环因子,用来控制循环
        while clusterChanged: 
            clusterChanged = False #先更改循环因子,防止陷入死循环
            for i in range(m): #对数据集中每一条样本进行循环
                dist_min_values, dist_min_index = one_sample_datacent_distance(data_add_3.iloc[i, :n], data_cent) #计算当前样本到k个质心的距离
                data_add_3.iloc[i, n] = dist_min_values #将距离的最小值放到容器的第一列(即第n列)
                #找到最小距离所在位置的索引即为簇的标号,将簇标号放入容器第二列(即第n+1列)
                data_add_3.iloc[i, n+1] = dist_min_index[0] 
            #判断最后两列是否相等(簇是否还会变化),不相等则进入下一次循环,相等则终止循环    
            clusterChanged = not (data_add_3.iloc[:, -1] == data_add_3.iloc[:, -2]).all()
            #重新计算当前的质心
            if clusterChanged:
                cent_df = data_add_3.groupby(n+1).mean() #对每个簇进行求均值
                data_cent = cent_df.iloc[:,:n].values  #将均值赋值给质心(确定了新质心)
                data_add_3.iloc[:, -1] = data_add_3.iloc[:, -2] #当前簇标号赋值给最后一列
                
        
        return data_cent, data_add_3

    效果如下:

    from sklearn.datasets import make_blobs #导入生成数据集的包
    
    #自己创建数据集
    X, y = make_blobs(n_samples=500,n_features=2,centers=4,random_state=1)
    
    plt.scatter(X[:, 0], X[:, 1]
                ,marker='o' #点的形状
                ,s=8 #点的大小
               );

    数据集的分布图:

    调用自己写的k-means进行聚类:

    test_cent, test_cluster = kmeans(pd.DataFrame(X), 4)
    
    #plt.scatter(testSet.iloc[:,0],testSet.iloc[:,1])
    plt.scatter(test_cluster.iloc[:,0], test_cluster.iloc[:, 1], c=test_cluster.iloc[:, -1])
    plt.scatter(test_cent[:,0],test_cent[:,1],c='r');

    效果还是非常好

  • 相关阅读:
    PC端列表数据无限下拉加载
    Oracle中的LOB数据类型分类
    jmeter系列(4)-JSON提取器
    jmeter系列(9)-常见函数__V拼接函数
    jmeter系列(3)-属性
    jmeter系列(8)-常见函数__counter
    jmeter系列(6)-查看函数用法
    jmeter系列(2)-用户参数
    jmeter系列(1)-用户自定义的变量
    b_lc_完成任务的最少工作时间段(贪心(×) / 枚举)
  • 原文地址:https://www.cnblogs.com/LUOyaXIONG/p/10732947.html
Copyright © 2011-2022 走看看