K-Means聚类算法

作者: longsan0918 | 来源:发表于2019-01-20 15:14 被阅读3次

    聚类

    聚类 是一种无监督学习,它将相似对象归到一个簇中。
    簇中的对象越相似,聚类的效果越好。
    聚类跟分类的区别,分类事先知道分类的种类,聚类则预先未定义 ,聚类属于无监督分类

    K-means(K-均值)算法

    之所以称k-均值,是因为它将数据分为k个簇,且每个簇的中心是采用所包含对象的均值计算出来的....
    给定一个有M个对象的数据集,构建一个具有k个簇的模型,其中k<=M。满足以下条件:
    1、每个簇至少包含一个对象;
    2、每个对象属于且仅属于一个簇;
    3、将满足上述条件的k个簇成为一个合理的聚类划分;
    基本思想:对于给定的类别数目k,首先给定初始划分,通过迭代改变样本和簇的隶属关系,使的每次处理后得到的划分方式比上一次的好(簇内数据集距离变小)

    构建过程 image.png

    终止条件: 迭代次数, 最小平方误差MSE, 簇中心变化率

    K-means算法的思考
    K-means算法在迭代的过程中使用簇类中所有对象的均值作为新的质心,如果簇中存在异常点,会导致均值误差较大
    eg: 簇中有 2, 4, 6, 8,100 K-means使用的新质点为24,显然误差较大,优化使用K-Mediods聚类(K中值聚类),采用中位数 6

    k-means优缺点
    缺点
    1 k值是用户给定的,需要数据分析经验,不同的k值,分类的结果不一样
    2 对初始簇中心点敏感
    3 不适合发现非凸形状的簇或者大小差别较大的簇

    image.png
    4 异常值对模型影响较大

    优点
    1 当簇近似高斯分布时,效果较好
    2 处理大数据集时,该算法可以保证较好的伸缩性和高效率
    3 易理解 聚类效果不错

    高斯分布数据生成(make_blobs的使用)

    # -*- coding: utf-8 -*-
    # @Time    : 2019/1/11 10:39 AM
    # @Author  : scl
    # @Email   : 1163820757@qq.com
    # @File    : 高斯分布数据.py
    # @Software: PyCharm
    
    import matplotlib
    matplotlib.use("TkAgg")
    import matplotlib.pyplot as plt
    
    from sklearn.datasets import make_blobs
    
    '''
    make_blobs: 产生一个服从给定均值和标准差的高斯分布
    最终返回数据样本组成的x特征矩阵 以及样本对应的类别(当前数据属于哪个均值哪个标准差的数据分布)
    '''
    x,y = make_blobs(n_samples=50,n_features=2,centers=3)
    # 50个样本 2个特征 3个簇中心
    
    
    print(x)
    print(y)
    print(x.shape)
    print(y.shape)
    # (50, 2)
    # (50,)
    
    # s表示点的半径大小
    plt.scatter(x[:, 0], x[:, 1], c=y, s=3)
    plt.show()
    
    

    模拟数据使用kmeans预测

    # -*- coding: utf-8 -*-
    # @Time    : 2019/1/14 9:50 AM
    # @Author  : scl
    # @Email   : 1163820757@qq.com
    # @File    : 模拟数据使用kmeans算法.py
    # @Software: PyCharm
    
    import matplotlib
    matplotlib.use("TkAgg")
    import matplotlib.pyplot as plt
    from sklearn.datasets import make_blobs
    from sklearn.cluster import KMeans
    from sklearn.model_selection import GridSearchCV
    
    N = 1000
    n_centers = 4
    X,Y = make_blobs(n_samples=N,n_features=2,centers=n_centers,random_state=12)
    
    
    # 1# 模型构建
    # algo = KMeans(n_clusters=n_centers)
    # algo.fit(X)
    
    
    # 2 模型构建使用网格交叉验证
    '''
    定义: 将原始数据集划分为两部分 一部分分为训练集 训练模型 另一部分分为测试集合验证模型效果
    交叉验证的目的是为了验证训练模型的拟合程度
    
    网格交叉验证(网格搜索) GridSearchCV 对估计器的指定参数值穷举搜索  通过给定不同参数值的组合 验证选取一组最优的参数parameters
    '''
    parameters = {
        'n_clusters':[2,3,4,5,6],
        'random_state':[0,14,28]
    }
    model = KMeans(n_clusters=n_centers)
    algo = GridSearchCV(estimator=model,param_grid=parameters,cv=5)
    algo.fit(X)
    
    
    # 数据预测
    x_test =[
        [-4, 8],
        [-3, 7],
        [0, 5],
        [0, -5],
        [8, -8],
        [7, -9]
    ]
    # 预测值:[2 2 3 3 1 1]
    print('预测值:{}'.format(algo.predict(x_test)))
    
    # print("中心点坐标{}".format(algo.cluster_centers_))
    # print("目标函数的损失函数:(所有样本到簇中心点的距离平方和)")
    #
    # print(algo.inertia_)
    # print(algo.inertia_/N)
    
    ## 交叉验证
    print("最优模型参数{}".format(algo.best_params_))
    print('中心点坐标{}'.format(algo.best_estimator_.cluster_centers_))
    print("目标函数损失值{}".format(algo.best_estimator_.inertia_))
    print(algo.best_estimator_.inertia_/N)
    
    plt.scatter(X[:,0],X[:,1],c = Y,s=30)
    plt.show()
    

    公式

    1.Jaccard(杰卡德相似系数)

    image.png

    如果J(A,B) 越趋近于1,表示A和B集合完全重合。如果J(A,B) 趋近于0,表示A和B集合几乎没有相交。

    即J(A,B) 越接近于1,越相似。距离和相似程度反比,距离越小,相似程度越大。所以用 1-J(A,B) 来表示度量函数时,值越大,相似度越大。

    1. Pearson相关系数(皮尔森相关系数)
    定义为两个变量间的协方差与标准差的商

    41269A50-436E-4B69-9589-473F81015E63.png
    一般情况下:
    若:|PXY|<0.3 则:X和Y不相关;
    若:0.3<|PXY|<0.7 则: X和Y弱相关
    若:0.7<|PXY|<1 则:X和Y强相关;
    若:PXY>0 则:正相关;
    若:PXY<0 则:负相关;

    K-Means算法案例

    # -*- coding: utf-8 -*-
    # @Time    : 2019/1/14 11:23 AM
    # @Author  : scl
    # @Email   : 1163820757@qq.com
    # @File    : K-Means算法.py
    # @Software: PyCharm
    import matplotlib
    matplotlib.use("TkAgg")
    import numpy as  np
    import matplotlib.pyplot as plt
    import matplotlib as mpl
    import sklearn.datasets as ds
    import matplotlib.colors
    from sklearn.cluster import KMeans #引入kmeans
    
    ## 设置属性防止中文乱码
    mpl.rcParams['font.sans-serif'] = [u'SimHei']
    mpl.rcParams['axes.unicode_minus'] = False
    
    
    # 1 生成模拟数据
    N = 1500
    centers = 4
    
    # 产生等方差的数据集(中心点随机)
    data1,y1 = ds.make_blobs(N,n_features=2,centers=centers,random_state=12)
    # 产生指定中心点和方差的数据集
    data2,y2 = ds.make_blobs(N,n_features=2,centers= [(-10,-8), (-5,8), (5,2), (8,-7)],cluster_std=[1.5, 2.5, 1.9, 1],random_state=12)
    # 产生方差相同 样本数量不同的数据集
    data3 = np.vstack((data1[y1 == 0][:200],
                       data1[y1 == 1][:100],
                       data1[y1 == 2][:10],
                       data1[y1 == 3][:50]))
    
    y3 = np.array([0] * 200 + [1] * 100 + [2] * 10 + [3] * 50)
    
    # 2 模型构建
    km = KMeans(n_clusters=centers,init='random',random_state=12)
    km.fit(data1)
    
    
    # 模型预测
    y_hat = km.predict(data1)
    print('所有样本距离簇中心点的总距离和:',km.inertia_)
    print('距离聚簇中的平均距离',(km.inertia_/N))
    cluster_centers = km.cluster_centers_
    print('聚簇中心点\n',cluster_centers)
    
    y_hat2 = km.fit_predict(data2)
    y_hat3 = km.fit_predict(data3)
    
    def expandBorder(a,b):
        d = (b - a) * 0.1
        return  a-d,b+d
    
    # 绘图
    cm = mpl.colors.ListedColormap(list('rgbmyc'))
    plt.figure(figsize=(15, 9), facecolor='w')
    
    plt.subplot(241)
    plt.scatter(data1[:, 0], data1[:, 1], c=y1, s=30, cmap=cm, edgecolors='none')
    x1_min, x2_min = np.min(data1, axis=0)
    x1_max, x2_max = np.max(data1, axis=0)
    x1_min, x1_max = expandBorder(x1_min, x1_max)
    x2_min, x2_max = expandBorder(x2_min, x2_max)
    plt.xlim((x1_min, x1_max))
    plt.ylim((x2_min, x2_max))
    plt.title(u'原始数据')
    plt.grid(True)
    
    plt.subplot(242)
    plt.scatter(data1[:, 0], data1[:, 1], c = y_hat, s=30, cmap=cm, edgecolors='none')
    plt.xlim((x1_min, x1_max))
    plt.ylim((x2_min, x2_max))
    plt.title(u'K-Means算法聚类结果')
    plt.grid(True)
    
    
    # 对数据做一个旋转
    m = np.array(((1, -5), (0.5, 5)))
    data_r = data1.dot(m)
    y_r_hat = km.fit_predict(data_r)
    
    plt.subplot(243)
    plt.scatter(data_r[:, 0], data_r[:, 1], c=y1, s=30, cmap=cm, edgecolors='none')
    x1_min, x2_min = np.min(data_r, axis=0)
    x1_max, x2_max = np.max(data_r, axis=0)
    x1_min, x1_max = expandBorder(x1_min, x1_max)
    x2_min, x2_max = expandBorder(x2_min, x2_max)
    plt.xlim((x1_min, x1_max))
    plt.ylim((x2_min, x2_max))
    plt.title(u'数据旋转后原始数据图')
    plt.grid(True)
    
    plt.subplot(244)
    plt.scatter(data_r[:, 0], data_r[:, 1], c=y_r_hat, s=30, cmap=cm, edgecolors='none')
    plt.xlim((x1_min, x1_max))
    plt.ylim((x2_min, x2_max))
    plt.title(u'数据旋转后预测图')
    plt.grid(True)
    
    plt.subplot(245)
    plt.scatter(data2[:, 0], data2[:, 1], c=y2, s=30, cmap=cm, edgecolors='none')
    x1_min, x2_min = np.min(data2, axis=0)
    x1_max, x2_max = np.max(data2, axis=0)
    x1_min, x1_max = expandBorder(x1_min, x1_max)
    x2_min, x2_max = expandBorder(x2_min, x2_max)
    plt.xlim((x1_min, x1_max))
    plt.ylim((x2_min, x2_max))
    plt.title(u'不同方差的原始数据')
    plt.grid(True)
    
    plt.subplot(246)
    plt.scatter(data2[:, 0], data2[:, 1], c=y_hat2, s=30, cmap=cm, edgecolors='none')
    plt.xlim((x1_min, x1_max))
    plt.ylim((x2_min, x2_max))
    plt.title(u'不同方差簇数据的K-Means算法聚类结果')
    plt.grid(True)
    
    plt.subplot(247)
    plt.scatter(data3[:, 0], data3[:, 1], c=y3, s=30, cmap=cm, edgecolors='none')
    x1_min, x2_min = np.min(data3, axis=0)
    x1_max, x2_max = np.max(data3, axis=0)
    x1_min, x1_max = expandBorder(x1_min, x1_max)
    x2_min, x2_max = expandBorder(x2_min, x2_max)
    plt.xlim((x1_min, x1_max))
    plt.ylim((x2_min, x2_max))
    plt.title(u'不同簇样本数量原始数据图')
    plt.grid(True)
    
    plt.subplot(248)
    plt.scatter(data3[:, 0], data3[:, 1], c=y_hat3, s=30, cmap=cm, edgecolors='none')
    plt.xlim((x1_min, x1_max))
    plt.ylim((x2_min, x2_max))
    plt.title(u'不同簇样本数量的K-Means算法聚类结果')
    plt.grid(True)
    
    plt.tight_layout(2, rect=(0, 0, 1, 0.97))
    plt.suptitle(u'数据分布对KMeans聚类的影响', fontsize=18)
    
    plt.show()
    
    Figure_1.png

    相关文章

      网友评论

        本文标题:K-Means聚类算法

        本文链接:https://www.haomeiwen.com/subject/lggarqtx.html