kmeans客户分类_机器学习 | KMeans聚类分析详解

论坛 期权论坛 期权     
选择匿名的用户   2021-5-28 00:27   7939   0

be02faf3a436106744d57ebdfe52726a.png

大量数据中具有"相似"特征的数据点或样本划分为一个类别。聚类分析提供了样本集在非监督模式下的类别划分。聚类的基本思想是"物以类聚、人以群分",将大量数据集中相似的数据样本区分出来,并发现不同类的特征。

聚类模型可以建立在无类标记的数据上,是一种非监督的学习算法。尽管全球每日新增数据量以PB或EB级别增长,但是大部分数据属于无标注甚至非结构化。所以相对于监督学习,不需要标注的无监督学习蕴含了巨大的潜力与价值。聚类根据数据自身的距离或相似度将他们划分为若干组,划分原则是组内样本最小化而组间距离最大化。

  • 常用于数据探索或挖掘前期
  • 没有先验经验做探索性分析
  • 样本量较大时做预处理
  • 解决问题
    • 数据集可以分几类
    • 每个类别有多少样本量
    • 不同类别中各个变量的强弱关系如何
    • 不同类型的典型特征是什么
  • 应用场景
    • 群类别间的差异性特征分析
    • 群类别内的关键特征提取
    • 图像压缩、分割、图像理解
    • 异常检测
    • 数据离散化
  • 缺点
  • 无法提供明确的行动指向
  • 数据异常对结果有影响

本文将从算法原理、优化目标、sklearn聚类算法、算法优缺点、算法优化、算法重要参数、衡量指标以及案例等方面详细介绍KMeans算法。

KMeans

K 均值(KMeans)是聚类中最常用的方法之一,基于点与点之间的距离的相似度来计算最佳类别归属。

KMeans算法通过试着将样本分离到

equation?tex=n个方差相等的组中来对数据进行聚类,从而最小化目标函数 (见下文)。该算法要求指定集群的数量。它可以很好地扩展到大量的样本,并且已经在许多不同领域的广泛应用领域中使用。

被分在同一个簇中的数据是有相似性的,而不同簇中的数据是不同的,当聚类完毕之后,我们就要分别去研究每个簇中的样本都有什么样的性质,从而根据业务需求制定不同的商业或者科技策略。常用于客户分群、用户画像、精确营销、基于聚类的推荐系统。

算法原理

  • equation?tex=n个样本数据中随机选取
    equation?tex=k个质心作为初始的聚类中心。质心记为
    equation?tex=%5Cmu_1%5E%7B%280%29%7D%2C%5Cmu_2%5E%7B%280%29%7D%2C%5Ccdots%2C%5Cmu_k%5E%7B%280%29%7D%2C+%5C%5C
  • 定义优化目标
    equation?tex=J%28c%2C%5Cmu%29%3D%5Cmin%5Csum_%7Bi%3D1%7D%5EM%7C%7Cx_i-%5Cmu_%7Bc_i%7D%7C%7C%5E2+%5C%5C
  • 开始循环,计算每个样本点到那个质心到距离,样本离哪个近就将该样本分配到哪个质心,得到 K 个簇
    equation?tex=c_i%5Et%3C-arg%5C%2C%5Cmin_k%7C%7Cx_i-%5Cmu_%7Bk%7D%5Et%7C%7C%5E2+%5C%5C
  • 对于每个簇,计算所有被分到该簇的样本点的平均距离作为新的质心
    equation?tex=%5Cmu_%7Bk%7D%5E%7B%28t%2B1%29%7D%3C-arg%5C%2C%5Cmin_u%5Csum%5Eb_%7Bi%3Ac_i%5Et%3Dk%7D%7C%7Cx_i-%5Cmu%7C%7C%5E2+%5C%5C
  • 直到
    equation?tex=J收敛,即所有簇不再发生变化。

ad762e5a281201fc0c3ed083a23d1dda.png

KMeans迭代示意图

优化目标

KMeans 在进行类别划分过程及最终结果,始终追求"簇内差异小,簇间差异大",其中差异由样本点到其所在簇的质心的距离衡量。在 KNN 算法学习中,我们学习到多种常见的距离 ---- 欧几里得距离、曼哈段距离、余弦距离。

在 sklearn 中的KMeans使用欧几里得距离:

equation?tex=d%28x%2C%5Cmu%29%3D%5Csqrt%7B%5Csum_%7Bi%3D1%7D%5E%7Bn%7D%28x_i-%5Cmu_i%29%5E2%7D+%5C%5C

则一个簇中所有样本点到质心的距离的平方和为:

equation?tex=Cluster%5C%2CSum%5C%2Cof%5C%2CSquare%28CSS%29%3D%5Csum_%7Bj%3D0%7D%5E%7Bm%7D%5Csum_%7Bi%3D1%7D%5E%7Bn%7D%28x_i-%5Cmu_i%29%5E2%5C%5C+Total%5C%2CCluster%5C%2CSum%5C%2Cof%5C%2CSquare%3D%5Csum_%7Bl%7D%5E%7Bk%7DCSS_l+%5C%5C

其中,

equation?tex=m为一个簇中样本的个数,
equation?tex=j是每个样本的编号。这个公式被称为簇内平方和
(cluster Sum of Square), 又叫做 Inertia

而将一个数据集中的所有簇的簇内平方和相加,就得到了整体平方和(Total Cluster Sum of Square),又叫做Total Inertia。Total Inertia 越小,代表着每个簇内样本越相似,聚类的效果就越好。因此 KMeans 追求的是,求解能够让Inertia最小化的质心。

K-means 有损失函数吗?
损失函数本质是用来衡量模型的拟合效果的,只有有着求解参数需求的算法,才会有损失函数。Kmeans 不求解什么参数,它的模型本质也没有在拟合数据,而是在对数据进行一 种探索。
另外,在决策树中有衡量分类效果的指标准确度 accuracy,准确度所对应的损失叫做泛化误差,但不能通过最小化泛化误差来求解某个模型中需要的信息,我们只是希望模型的效果上表现出来的泛化误差 很小。因此决策树,KNN 等算法,是绝对没有损失函数的。

虽然在 sklearn 中只能被动选用欧式距离,但其他距离度量方式同样可以用来衡量簇内外差异。不同距离所对应的质心选择方法和Inertia如下表所示, 在K-means中,只要使用了正确的质心和距离组合,无论使用什么样的距离,都可以达到不错的聚类效果。

距离度量质心Inertia
欧几里得距离均值最小化每个样本点到质心的欧式距离之和
曼哈顿距离中位数最小化每个样本点到质心的曼哈顿距离之和
余弦距离均值最小化每个样本点到质心的余弦距离之和

sklearn.cluster.KMeans

语法:

sklearn.cluster.KMeans(n_clusters=8, init='k-means++', n_init=10, max_iter=300, tol=0.0001, precompute_distances='auto', verbose=0, random_state=None, copy_x=True, n_jobs=None, algorithm='auto')
参数与接口见文末原文

例:

>>> from sklearn.cluster import KMeans
>>> import numpy as np
>>> X = np.array([[1, 2], [1, 4], [1, 0],
...               [10, 2], [10, 4], [10, 0]])
>>> kmeans = KMeans(n_clusters=2, random_state=0).fit(X)
>>> kmeans.labels_
array([1, 1, 1, 0, 0, 0], dtype=int32)
>>> kmeans.predict([[0, 0], [12, 3]])
array([1, 0], dtype=int32)
>>> kmeans.cluster_centers_
array([[10.,  2.],
       [ 1.,  2.]])

k-means++聚类算法

KMeans算法原来可知,KMeans在聚类之前首先需要初始化

equation?tex=k个簇中心,因此
KMeans 算法对初值敏感,对于不同的初始值,可能会导致不同的聚类结果。若初始化是个随机过程,很有可能
equation?tex=k个簇中心都在同一个簇中,这种情况
KMeans 聚类算法很大程度上都不会收敛到全局最小。

为了优化选择初始质心的方法,2007 年 Arthur, David, and Sergei Vassilvitskii 三人发表了论文“k-means++: The advantages of careful seedinghttp://ilpubs.stanford.edu:8090/778/1/2006-13.pdf,sklearn.cluster.KMeans 中默认参数为 init='k-means++' ,其算法原理为在初始化簇中心时,逐个选取

equation?tex=k个簇中心,且离其他簇中心越远的样本越有可能被选为下个簇中心。

算法步骤:

  • 从数据即
    equation?tex=%5Cchi中随机(均匀分布)选取一个样本点作为第一个初始聚类中心
    equation?tex=c_1
  • 计算每个样本与当前已有聚类中心之间的最短距离
    equation?tex=D%28x%29;再计算每个样本点被选为下个聚类中心的概率
    equation?tex=P%28x%29,最后选择最大概率值所对应的样本点作为下一个簇中心
    equation?tex=P%28X%29%3D%5Cfrac%7BD%28x%29%5E2%7D%7B%5Csum_%7Bx%5Cin%5Cchi%7DD%28x%29%5E2%7D+%5C%5C
  • 重复上步骤,直到选择
    equation?tex=k个聚类中心

k-means++算法初始化的簇中心彼此相距都十分的远,从而不可能再发生初始簇中心在同一个簇中的情况。

code:

def InitialCentroid(x, K):
    c1_idx = int(np.random.uniform(0, len(x))) # Draw samples from a uniform distribution.
    centroid = x[c1_idx].reshape(1, -1)  # choice the first center for cluster.
    k = 1
    n = x.shape[0] # number of samples
    while k < K:
        d2 = []
        for i in range(n):
            subs = centroid - x[i, :]  # D(x) = (x_1, y_1) - (x, y)
            dimension2 = np.power(subs, 2) # D(x)^2
            dimension_s = np.sum(dimension2, axis=1)  # sum of each row
            d2.append(np.min(dimension_s))
        new_c_idx = np.argmax(d2)
        centroid = np.vstack([centroid, x[new_c_idx]])
        k += 1
    return centroid

重要参数

1、初始质心

KMeans 算法的第一步"随机"在样本中抽取k 个样本作为初始质心,因此并不符合"稳定且更快"的需求。因此可通过random_state参数来指定随机数种子,以控制每次生成的初始质心都在相同位置。

一个random_state对应一个质心随机初始化的随机数种子。如果不指定随机数种子,则 sklearn中的KMeans并不会只选择一个随机模式扔出结果,而会在每个随机数种子下运行多次,并使用结果最好的一个随机数种子来作为初始质心。我们可以使用参数n_init来选择,每个随机数种子下运行的次数。

而以上两种方法仍然避免不了基于随机性选取 k 个质心的本质。在sklearn中,我们使用参数init ='k-means ++'来选择使用k-means ++作为质心初始化的方案。

init: 可输入"k-means++""random"或者一个n维数组。这是初始化质心的方法,默认"k-means++"。输入"k- means++":一种为 K 均值聚类选择初始聚类中心的聪明的办法,以加速收敛。如果输入了n维数组,数组的形状应该是(n_clusters,n_features)并给出初始质心。

random_state: 控制每次质心随机初始化的随机数种子。

n_init: 整数,默认 10,使用不同的质心随机初始化的种子来运行KMeans算法的次数。最终结果会是基于Inertia来计算的n_init次连续运行后的最佳输出。

2、迭代停止

max_iter: 整数,默认 300,单次运行的KMeans算法的最大迭代次数。

tol: 浮点数,默认1e-4,两次迭代间Inertia下降的量,如果两次迭代之间Inertia下降的值小于tol所设定的值,迭代就会停下。

衡量指标

聚类模型的结果不是某种标签输出,并且聚类的结果是不确定的,其优劣由业务需求或者算法需求来决定,并且没有永远的正确答案。那么如何衡量聚类的效果呢?

衡量簇内差异来衡量聚类的效果

簇内平方和:Total_Inertia

「肘部法(手肘法)认为图上的拐点就是 K 的最佳值」

# 应用肘部法则确定 kmeans方法中的k
from scipy.spatial.distance import cdist # 计算两个输入集合的每对之间的距离。
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from sklearn.datasets import make_blobs
plt.style.use('seaborn')
plt.rcParams['font.sans-serif']=['Simhei'] #显示中文
plt.rcParams['axes.unicode_minus']=False #显示负号
X, y = make_blobs(n_samples=5000, centers=4, cluster_std = 2.5, n_features=2,random_state=42)
K=range(1,10)

# 直接计算sse
sse_result=[]
for k in K:
    kmeans=KMeans(n_clusters=k, random_state=666)
    kmeans.fit(X)
    sse_result.append(sum(np.min(cdist(X,kmeans.cluster_centers_,'euclidean'),axis=1))/X.shape[0])
plt.figure(figsize=(16,5))
plt.subplot(1,2,1)
plt.plot(K,sse_result,'gp-')
plt.xlabel('k',fontsize=20)
plt.ylabel(u'平均畸变程度')
plt.title(u'肘部法则确定最佳的K值(1)',fontdict={'fontsize':15})

# 第二种,使用inertia_
L = []
for k in K:
    kmeans = KMeans(n_clusters=k, random_state=666)
    kmeans.fit(X)
    L.append((k, kmeans.inertia_))
a = pd.DataFrame(L)
a.columns = ['k', 'inertia']
plt.subplot(1,2,2)
plt.plot(a.k, a.inertia,'gp-')
plt.xlabel('k',fontsize=20)
plt.ylabel('inertia')
plt.title(u'肘部法则确定最佳的K值(2)',fontdict={'fontsize':15})
plt.xticks(a.k)
plt.show();

输出结果

48ea5d7f66b51e783a1e32fb9d1492ca.png

但其有很大的局限:

  • 它的计算太容易受到特征数目的影响。
  • 它不是有界的,Inertia是越小越好,但并不知道合适达到模型的极限,能否继续提高。
  • 它会受到超参数 K 的影响,随着K越大,Inertia注定会越来越小,但并不代表模型效果越来越好。
  • Inertia 对数据的分布有假设,它假设数据满足凸分布,并且它假设数据是各向同性的 (isotropic),所以使用Inertia作为评估指标,会让聚类算法在一些细长簇,环形簇,或者不规则形状的流形时表现不佳。

其他衡量指标

1、真实标签已知时

可以用聚类算法的结果和真实结果来衡量聚类的效果。但需要用到聚类分析的场景,大部分均属于无真是标签的情况,可到原文里查看模型评估指标了解即可。

2、真实标签未知时

「轮廓系数」

对没有真实标签的数据进行探索,常用轮廓系数评价聚类算法模型效果。

  • 样本与其自身所在的簇中的其他样本的相似度a,等于样本与同一簇中所有其他点之间的平均距离 。
  • 样本与其他簇中的样本的相似度b,等于样本与下一个最近的簇中的所有点之间的平均距离。

根据聚类的要求"簇内差异小,簇外差异大",我们希望b永远大于a,并且大得越多越好。

单个样本的轮廓系数计算为:

equation?tex=s+%3D+%5Cfrac%7Bb-a%7D%7Bmax%28a%2Cb%29%7D%5C%5Ca%E7%BB%84%E5%86%85%E5%B7%AE%E5%BC%82%EF%BC%8Cb%E7%BB%84%E9%97%B4%E5%B7%AE%E5%BC%82+%5C%5C

取值范围

equation?tex=%28-1%2C1%29越大越好。
  • 越接近 1 表示样本与自己所在的簇中的样本很相似,并且与其他簇中的样本不相似,当样本点与簇外的样本更相似的时候,轮廓系数就为负。
  • 当轮廓系数为 0 时,则代表两个簇中的样本相似度一致,两个簇本应该是一个簇。
from sklearn.metrics import silhouette_score
# 返回所有样本的轮廓系数的均值
from sklearn.metrics import silhouette_samples
# 返回的是数据集中每个样本自己的轮廓系数
silhouette_score(X,y_pred)
silhouette_score(X,cluster_.labels_)
silhouette_samples(X,y_pred)

例:

L = []
for i in range(2, 20):
    k = i
    kmeans = KMeans(n_clusters=i)
    kmeans.fit(X)
    L.append([i, silhouette_score(X, kmeans.labels_)])
a = pd.DataFrame(L)
a.columns = ['k', '轮廓系数']
plt.figure(figsize=(8, 5), dpi=70)
plt.plot(a.k, a.轮廓系数,'gp-')
plt.xticks(a.k)
plt.xlabel('k')
plt.ylabel('轮廓系数')
plt.title('轮廓系数确定最佳的K值',fontdict={'fontsize':15})

输出结果:

3fa4ad833891a37757cb735e5e3808f3.png

轮廓系数看出,k=3时轮廓系数最大,肘部法的拐点亦是k=3,从数据集可视化图(文末案例)中也能看出数据集可以清洗分割 3 个簇(虽然初始创建了四个簇,但上面两个簇边界并不清晰,几乎连到一起)。

轮廓系数有很多优点,它在有限空间中取值,使得我们对模型的聚类效果有一个"参考"。并且,轮廓系数对数据的分 布没有假设,因此在很多数据集上都表现良好。但它在每个簇的分割比较清洗时表现最好。

「其它评估指标」

这里简单介绍「卡林斯基-哈拉巴斯指数」,有

equation?tex=k个簇的聚类而言,
Calinski-Harabaz指数
equation?tex=S%28k%29写作如下公式:

equation?tex=S%28k%29+%3D+%5Cfrac%7BTr%28B_k%29%7D%7BTr%28W_k%29%7D%5Ctimes%5Cfrac%7BN-k%7D%7Bk-1%7D+%5C%5C

其中

equation?tex=N为数据集中的样本量,
equation?tex=k为簇的个数(即类别的个数),
equation?tex=B_k是组间离散矩阵,即不同簇之间的协方差矩阵, 是
equation?tex=W_k簇内离散矩阵,即一个簇内数据的协方差矩阵,而
equation?tex=Tr%28%29表示矩阵的迹。在线性代数中,一个
equation?tex=n%C3%97n矩阵
equation?tex=A的主对角线(从左上方至右下方的对角线)上各个元素的总和被称为矩阵 A 的迹(或迹数),一般记作
equation?tex=Tr%28A%29

数据之间的离散程度越高,协方差矩阵的迹就会越大。组内离散程度低,协方差的迹就会越小,

equation?tex=Tr%28W_k%29也就越小,同时,组间离散程度大,协方差的的迹也会越大,
equation?tex=Tr%28B_k%29就越大,因此
Calinski-harabaz指数越高越好」

虽然calinski-Harabaz指数没有界,在凸型的数据上的聚类也会表现虚高。但是比起轮廓系数,其计算非常快速。

K-Means 算法的优缺点

优点

  • k-means 算法是解决聚类问题的一种经典算法, 算法简单、快速 。
  • 算法尝试找出使平方误差函数值最小的 k 个划分。 当簇是密集的、球状或团状的,且簇与簇之间区别明显时,聚类效果较好 。

缺点

  • k-平均方法只有在簇的平均值被定义的情况下才能使用,且对有些分类属性的数据不适合。
  • 要求用户必须事先给出要生成的簇的数目 k 。
  • 对初值敏感,对于不同的初始值,可能会导致不同的聚类结果。
  • 不适合于发现非凸面形状的簇,或者大小差别很大的簇。
  • 「KMeans 本质上是一种基于欧式距离度量的数据划分方法,均值和方差大的维度将对数据的聚类结果产生决定性影响。「所以在聚类前对数据(「具体的说是每一个维度的特征」)做归一化和单位统一至关重要。此外,异常值会对均值计算产生较大影响,导致」中心偏移」,因此对于"噪声"和孤立点数据最好能提前过滤 。

原文链接

机器学习 | KMeans聚类分析详解mp.weixin.qq.com

猜你喜欢

机器学习合集mp.weixin.qq.com
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP