K-Means

引入

聚类

  1. 是一种无监督学习,将相似的样本(对象/实例)归到同一簇(cluster)中。通常用样本的相似度或距离来衡量。eg:天空中的星星,靠得近的星星可以被归为一个星团,而星团之间的星星距离比较远。
  2. 簇内的对象越相似,聚类的效果越好。
  3. 硬聚类:一个样本只能属于一个类。
  4. 软聚类:一个样本可以以概率属于多个类。
  5. 聚类与分类的不同:分类为监督,是监督学习,目标事先已知;而聚类的“类”没有预先定义,是从数据中自动发现的,是无监督学习。也就是说,聚类问题中,给我们的样本只用xx,没有yy。
  6. k-means表示:该算法可以发现k个不同的簇,且每个簇的中心采用簇内所含值的均值计算而成。属于硬聚类。。常见的聚类算法还有:层次聚类。

K-means算法

1967年MacQueen提出

流程

  1. 选择适当的k。
  2. 初始化k个质心\mu^{(0)}=\{\mu_1^{(0)},\mu_2^{(0)},\dots,\mu_k^{(0)}\}
  3. 计算每个样本到质心的距离。
  4. 按最小距离聚类,将数据集D分配到k个子数据集D^{(1)}=\{D_1^{(1)},D_2^{(1)},\dots,D_k^{(1)}\}
  5. 迭代以下步骤直至收敛:(假设在第t步)
    1)重新计算质心:\mu^{(t)}=\{\mu_1^{(t)},\mu_2^{(t)},\dots,\mu_k^{(t)}\},求均值。
    2)重新计算每个样本到每个质心的距离(遍历样本,扫描质心,两个for循环嵌套)。
    3)按最小距离聚类,将数据集DD重新分配到kk个子数据集D^{(t)}=\{D_1^{(t)},D_2^{(t)},\dots,D_k^{(t)}\}
    4)如果迭代收敛或符合停止条件(达到最大迭代次数or所有样本分类不再变化),则输出聚类结果。否则t=t+1返回步骤5.1)迭代。

K-means缺点

  1. K的选择需要事先预定。
  2. K个初始质心的位置选择对聚类结果和运行时间都有很大影响(K-Means++/biKmeans)。
  3. 不能保证全局最优,可能是局部最优解。
  4. 对异常值敏感。(改进1:离群点监测的LOF算法,先去除离群点;改进2:该求K中值法。)

K-means改进

如何确定K?
一、手肘法思想:

随着聚类数K的增大,样本划分更加精细,那么所有样本的聚类误差(SSE)会逐渐变小:

SSE=\sum_{i=1}^k\sum_{x\in D_i}|x-\mu_i|^2

  • 当K值小于真实聚类数时,K的增加会对聚类效果产生很大影响,故SSE下降幅度很大;
  • 当K值大于真实聚类数时,K的增加不会对聚类效果产生很大影响,故SSE下降幅度将会趋于平缓;整个SSE-K图为一个手肘型。


    .png
二、轮廓系数法
  1. 思想:类中样本距离越近,类间样本距离越远,聚类效果越好。用平均轮廓系数来衡量。
  2. 类中不相似度:a_i的平均,体现凝聚度。a_i表示样本x_i到同类中其他样本的平均距离。a_i越小,表明类中样本不相似度越低,凝聚度越高,越应该聚为一类。(among)
  3. 类间不相似度:b_i的最小值,体现分离度。b_i表示样本x_i到其他类中所有样本的平均距离。b_i越大,表明内间不相似程度越高,分离度越高,越不应该聚为一个类。(between)。最近类:
    C_j=\min\limits_{D_k}\frac{1}{n}\sum_{x\in D_k}|x-x_i|^2

D_k为要找的最近类,x是最近类里的全部样本,n是最近类里的全部样本的个数。

4.某一个样本点xixi的轮廓系数:
S_i=\frac{b_i-a_i}{max(a_i,b_i)}
\begin{equation} S_i = \begin{cases} 1-\frac{a_i}{b_i}, & a_i < b_i\\\ 0, &a_i=b_i\\\ \frac{a_i}{b_i}-1, & a_i > b_i\\\ \end{cases} \end{equation}

1)S_i接近1,则说明样本x_i聚类合理;(理想状况,a_i越小越好,b_i越大越好)
2)S_i接近-1,则说明样本x_i应该分为其他的类;
3)S_i接近0,则说明样本x_i在两个类的边界上。

5.将所有点的轮廓系数求平均,就是该聚类结果的总轮廓系数。选择平均轮廓系数最大对应的K即可。

如何初始化质心

K-means++

随机初始化质心可能导致算法迭代很慢,K-means++是对K-mean随机初始化质心的一个优化,具体步骤如下:

  1. 随机选取一个点作为第一个聚类中心。
  2. 计算所有样本与第一个聚类中心的距离。
  3. 选择出上一步中距离最大的点作为第二个聚类中心。
  4. 迭代:计算所有点到与之最近的聚类中心的距离,选取最大距离的点作为新的聚类中心。
  5. 终止条件:直到选出了这k个中心。

只需要随机取第一个聚类中心即可。
然后按照最远优先原则来选新的聚类中心

K-means实例应用——Python实现

import numpy as np
def loadDataSet(fileName):
    '''
    :param fileName: 文件名字
    :return: 矩阵
    '''
    dataMat = []
    fr = open(fileName)
    for line in fr.readlines():
        curLine = line.strip().split('\t')
        fltLine = list(map(float, curLine))
        dataMat.append(fltLine)
    return dataMat
def distEclud(vecA, vecB):
    return np.sqrt(np.sum(np.power(vecA - vecB, 2)))
def randCent(dataSet, k):
    '''
    构建一个包含k个随机质心的集合(k行n列,n表示数据的维度/特征个数),
    只需要保证质心在数据边界里面就可以了
    :param dataSet: 输入数据集
    :param k: 质心个数
    :return:
    '''
    # 得到数据样本的维度
    n = np.shape(dataSet)[1]
    # 初始化为一个(k,n)的全零矩阵
    centroids = np.mat(np.zeros((k, n)))
    # 遍历数据集的每一个维度
    for j in range(n):
        # 得到该列数据的最小值,最大值
        minJ = np.min(dataSet[:, j])
        maxJ = np.max(dataSet[:, j])
        # 得到该列数据的范围(最大值-最小值)
        rangeJ = float(maxJ - minJ)
        # k个质心向量的第j维数据值随机为位于(最小值,最大值)内的某一值
        centroids[:, j] = minJ + rangeJ * np.random.rand(k, 1)  # random.rand(行,列)产生这个形状的矩阵,且每个元素in [0,1)
    # 返回初始化得到的k个质心向量
    return centroids
def kMeans(dataSet, k, distMeas=distEclud, createCent=randCent):
    '''
    :param dataSet: 输入的数据集
    :param k: 聚类的个数,可调
    :param distMeas: 计算距离的方法,可调
    :param createCent: 初始化质心的位置的方法,可调
    :return: k个类质心的位置坐标,样本所处的类&到该类质心的距离
    '''
    # 获取数据集样本数
    m = np.shape(dataSet)[0]
    # 初始化一个(m,2)全零矩阵,用来记录没一个样本所属类,距离类中心的距离
    clusterAssment = np.mat(np.zeros((m, 2)))
    # 创建初始的k个质心向量
    centroids = createCent(dataSet, k)
    # 聚类结果是否发生变化的布尔类型
    clusterChanged = True
    # 终止条件:所有数据点聚类结果不发生变化
    while clusterChanged:
        # 聚类结果变化布尔类型置为False
        clusterChanged = False
        # 遍历数据集每一个样本向量
        for i in range(m):
            # 初始化最小距离为正无穷,最小距离对应的索引为-1
            minDist = float('inf')
            minIndex = -1
            # 循环k个类的质心
            for j in range(k):
                # 计算数据点到质心的欧氏距离
                distJI = distMeas(centroids[j, :], dataSet[i, :])
                # 如果距离小于当前最小距离
                if distJI < minDist:
                    # 当前距离为最小距离,最小距离对应索引应为j(第j个类)
                    minDist = distJI
                    minIndex = j
            # 当前聚类结果中第i个样本的聚类结果发生变化:布尔值置为True,继续聚类算法
            if clusterAssment[i, 0] != minIndex:
                clusterChanged = True
            # 更新当前变化样本的聚类结果和平方误差
            clusterAssment[i, :] = minIndex, minDist**2
        # 打印k-means聚类的质心
        # print(centroids)
        # 遍历每一个质心
        for cent in range(k):
            # 将数据集中所有属于当前质心类的样本通过条件过滤筛选出来
            ptsInClust = dataSet[np.nonzero(clusterAssment[:, 0].A == cent)[0]]
            # 计算这些数据的均值(axis=0:求列均值),作为该类质心向量
            centroids[cent, :] = np.mean(ptsInClust, axis=0)
    # 返回k个聚类,聚类结果及误差
    return centroids, clusterAssment
.png
import matplotlib.pyplot as plt
def plotDataSet(filename):
    # 导入数据
    datMat = np.mat(loadDataSet(filename))
    # 进行k-means算法其中k为4
    myCentroids, clustAssing = kMeans(datMat, 4)
    clustAssing = clustAssing.tolist()
    myCentroids = myCentroids.tolist()
    xcord = [[], [], [], []]
    ycord = [[], [], [], []]
    datMat = datMat.tolist()
    m = len(clustAssing)
    for i in range(m):
        if int(clustAssing[i][0]) == 0:
            xcord[0].append(datMat[i][0])
            ycord[0].append(datMat[i][1])
        elif int(clustAssing[i][0]) == 1:
            xcord[1].append(datMat[i][0])
            ycord[1].append(datMat[i][1])
        elif int(clustAssing[i][0]) == 2:
            xcord[2].append(datMat[i][0])
            ycord[2].append(datMat[i][1])
        elif int(clustAssing[i][0]) == 3:
            xcord[3].append(datMat[i][0])
            ycord[3].append(datMat[i][1])
    fig = plt.figure()
    ax = fig.add_subplot(111)
    # 绘制样本点
    ax.scatter(xcord[0], ycord[0], s=20, c='b', marker='*', alpha=.5)
    ax.scatter(xcord[1], ycord[1], s=20, c='r', marker='D', alpha=.5)
    ax.scatter(xcord[2], ycord[2], s=20, c='c', marker='>', alpha=.5)
    ax.scatter(xcord[3], ycord[3], s=20, c='k', marker='o', alpha=.5)
    # 绘制质心
    ax.scatter(myCentroids[0][0], myCentroids[0][1], s=100, c='k', marker='+', alpha=.5)
    ax.scatter(myCentroids[1][0], myCentroids[1][1], s=100, c='k', marker='+', alpha=.5)
    ax.scatter(myCentroids[2][0], myCentroids[2][1], s=100, c='k', marker='+', alpha=.5)
    ax.scatter(myCentroids[3][0], myCentroids[3][1], s=100, c='k', marker='+', alpha=.5)
    plt.title('DataSet')
    plt.xlabel('X')
    plt.show()
.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 161,326评论 4 369
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,228评论 1 304
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,979评论 0 252
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,489评论 0 217
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,894评论 3 294
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,900评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,075评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,803评论 0 205
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,565评论 1 249
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,778评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,255评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,582评论 3 261
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,254评论 3 241
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,151评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,952评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,035评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,839评论 2 277

推荐阅读更多精彩内容

  • 算法介绍 对于同一个数据集,相同的聚簇中心,每次计算结果也可能会不一样 该算法除了要事先确定簇数K和对初始聚类中心...
    shanshan302阅读 1,474评论 0 1
  • 1.1 概述 聚类算法又叫无监督算法,其目的是将数据划分有意义或有用的组或簇,划分一般是基于业务需求或建模需求...
    诗云HSY阅读 1,331评论 0 1
  • 0x00 内容 学习内容:无监督聚类算法K-Means k-means:模型原理、收敛过程、超参数的选择 0x01...
    s0k0y阅读 609评论 0 0
  • 1项目背景 本次分析数据来源CDNow网站的用户在1997年1月1日至1998年6月30日期间内购买CD订单明细,...
    L李卓阅读 3,926评论 0 4
  • 一. 概念K-means:事先确定常数K,常数K意味着最终的聚类类别数,首先随机选定初始点为质心,并通过计算每一个...
    YCzhao阅读 2,310评论 0 0