天天看点

多元统计分析——聚类分析——K-均值聚类应用场景

在《多元统计分析——聚类分析——K-均值聚类(K-中值、K-众数)》当中,我们理解了K-均值聚类的原理,也简单的介绍了K-均值聚类的两个应用场景:

  • 发现异常情况:如果不对数据进行任何形式的转换,只是经过中心标准化或级差标准化就进行快速聚类,会根据数据分布特征得到聚类结果。这种聚类会将极端数据单独聚为几类。这种方法适用于统计分析之前的异常值剔除,对异常行为的挖掘,比如监控银行账户是否有洗钱行为、监控POS机是有从事套现、监控某个终端是否是电话卡养卡客户等等。

注:区别于单个维度的异常值:单个变量的异常值一般是离中心点位置超过3倍或者5倍的标准差。

  • 将个案数据做划分:出于客户细分目的的聚类分析一般希望聚类结果为大致平均的几大类(原始数据尽量服从正态分布,这样聚类出来的簇的样本点个数大致接近),因此需要将数据进行转换,比如使用原始变量的百分位秩、Turkey正态评分、对数转换等等。在这类分析中数据的具体数值并没有太多的意义,重要的是相对位置。这种方法适用场景包括客户消费行为聚类、客户积分使用行为聚类等等。

以上两种场景的大致步骤如下:

多元统计分析——聚类分析——K-均值聚类应用场景

现在我们通过案例来分析这两个场景。

案例:有一份电信用户的数据集,字段包括:

多元统计分析——聚类分析——K-均值聚类应用场景

 1、导入数据

数据样本大体如下:

%matplotlib inline
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

profile_telecom = pd.read_csv('profile_telecom.csv')
profile_telecom.head() 
           

输出:

多元统计分析——聚类分析——K-均值聚类应用场景

2、变量的相关系数矩阵

去除ID列,输出后四列的相关系数矩阵。

profile_telecom.loc[: ,'cnt_call':].corr()
           

输出:

多元统计分析——聚类分析——K-均值聚类应用场景

可以看出有些变量之间的相关系数还是比较高的。

3、检测变量分布

plt.figure(figsize=(8, 3))

for i in range(4):
    plt.subplot(220 + i + 1)
    plt.hist(profile_telecom.iloc[:, i + 1], bins=20)

plt.show()
           

输出:

多元统计分析——聚类分析——K-均值聚类应用场景

可以看出,各变量都是一个右偏的分布,在实际工作当中,遇到最多的一般就是正态分布和右偏分布。

4、场景一:检测异常情况——发现离群点

4.1、变量归一化——学生标准化

仅使用学生标准化进行预处理,不使用其它会改变数据分布形态的变换。

from sklearn.preprocessing import scale
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA

tele_scaled = scale(profile_telecom.loc[:, 'cnt_call':])  #学生标准化
tele_scaled
           

输出:

array([[-0.296453  ,  3.68086843,  0.85513907,  2.08171356],
       [-0.1905409 , -0.80292101, -0.59755491, -0.64747691],
       [-0.56879838,  0.31802635, -0.39579186, -0.08281681],
       ...,
       [ 0.24823778,  0.01231344,  3.2762957 ,  2.45815362],
       [-0.11488941,  0.01231344, -0.11332358, -0.08281681],
       [ 1.01988304, -0.80292101, -0.59755491, -0.64747691]])
           

4.2、降维——主成分分析

tele_pca = PCA(n_components=2)   #PCA降维(2维)
tele_pca_score = tele_pca.fit_transform(tele_scaled)
print('variance_ratio:', tele_pca.explained_variance_ratio_)
           

输出:

variance_ratio: [0.62510442 0.24620209]
           

前两个主成分,方差占比之和为87%, 所以降到二维是比较合适的。

 4.3、K-means聚类

k = 4
tele_kmeans = KMeans(n_clusters=k, n_init=15).fit(tele_pca_score)  #聚成四类
tele_kmeans.cluster_centers_    #输出质心
           

输出:

array([[ 5.10963437, -0.21710494],
       [ 1.30272379, -0.10395259],
       [-0.8669528 , -0.10911188],
       [-0.06943007,  4.0981177 ]])
           

 4.4、聚类特征分析

4.4.1、轮廓系数

from sklearn.metrics import silhouette_score
silhouette_score(tele_pca_score, tele_kmeans.labels_)
           

输出:

0.5081846457150366
           

4.4.2、降维之后聚类效果

plt.figure(figsize=[4, 3])

markers = 'xvo+*^dDhs|_<,.>'

k = 4

for cluster, marker in zip(range(k), markers[:k]):
    x_axis = tele_pca_score[:, 0][tele_kmeans.labels_ == cluster]
    y_axis = tele_pca_score[:, 1][tele_kmeans.labels_ == cluster]
    plt.scatter(x_axis, y_axis, marker=marker)
    
plt.show()
           

输出:

多元统计分析——聚类分析——K-均值聚类应用场景

在没有进行数据分布形态转换的情况之下,比较明显的看出红框中为疑似离群点。注意:k=4是我们随意选择的数字,k我们可以选大一些,如7、8、9...,这样异常点检测的效果越明显。聚类完成之后,可以对数据样本按聚类标签进行分组,查看每个标签下都有多少个样本,如下:

4.4.3、聚类之后各类的数量

pd.DataFrame(tele_pca_score).groupby(tele_kmeans.labels_).count()
           

输出:

多元统计分析——聚类分析——K-均值聚类应用场景

我们会发现,有某些簇的样本量较小,即疑似异常值点。

5、场景二:将个案数据做划分

5.1、变量分布转换——取对数

上面我们已经知道,原始变量都是呈右偏分布的。

#  对变量取对数(也可取rank)
log_telecom = np.log1p(profile_telecom.iloc[:, 1:]) #有很多0值,0值取对数是无意义的,所以+1之后取对数。
plt.figure(figsize=(8, 3))
for i in range(4):
    plt.subplot(220 + i + 1)
    plt.hist(log_telecom.iloc[:, i], bins=20)

plt.show()
           

输出:

多元统计分析——聚类分析——K-均值聚类应用场景

右偏分布的数据集为了让其尽量靠近正态,处理的方法一般是取对数。结合实际业务,变量中有很多是0值,我们先将其+1,因为对0取对数是没有意义的。 

5.2、变量归一化——学生标准化

log_telecom_scaled=scale(log_telecom)
log_telecom_scaled
           

输出:

array([[ 0.04174954,  1.98292009,  1.26385741,  1.60145475],
       [ 0.19291257, -1.24657303, -1.11310713, -0.63398781],
       [-0.48397217,  0.76013283,  0.06635716,  0.40350962],
       ...,
       [ 0.6609339 ,  0.50039436,  1.89829497,  1.71268561],
       [ 0.28932817,  0.50039436,  0.57532607,  0.40350962],
       [ 1.18246098, -1.24657303, -1.11310713, -0.63398781]])
           

注意,是否进行标准化,可以结合实际的业务场景,如本例题中,四个变量的量纲是一样的(单位都为“次数”) ,但是其各变量之间的方差差异是比较大的,所以需要进行标准化。否则后续的PCA效果可能不太好。

不需要标准化是有两个先决条件的:1、量纲一致;2、方差相近。

5.3、降维——主成分分析

log_pca = PCA(n_components=2, whiten=True)
log_pca_score = log_pca.fit_transform(log_telecom_scaled)
print('variance_ratio:', log_pca.explained_variance_ratio_)
           

输出:

variance_ratio: [0.71197124 0.22755356]
           

 前两个主成分方差占比超过90%,取两个主成分正好。前两个主成分(各变量的权重)如下:

components=log_pca.components_  #获得转换后的所有主成分
components
           

输出:

array([[ 0.22077367,  0.54471581,  0.5687719 ,  0.57536266],
       [ 0.97202048, -0.19050882, -0.08855497, -0.10507422]])
           

5.4、使用轮廓系数或者样本到类中心的距离和(离差平方和)确定聚类数量

plt.figure(figsize=[8, 2])
Ks = range(2, 10)
rssds = []; silhs = []
for k in Ks:
    model = KMeans(n_clusters=k, n_init=15)
    model.fit(log_pca_score)
    rssds.append(model.inertia_)
    silhs.append(silhouette_score(log_pca_score, model.labels_, sample_size=None))
     # 轮廓系数计算复杂度高,使用sample_size
    
plt.subplot(121); plt.plot(Ks, rssds)
plt.subplot(122); plt.plot(Ks, silhs)
plt.show()
           

输出:

多元统计分析——聚类分析——K-均值聚类应用场景

左边为样本到类中心的距离和(离差平方和),右边为轮廓系数,结合两个指标,我们确定聚成3类是最合适的。

5.5、聚类特征分析

5.5.1、轮廓系数

k = 3
log_pca_kmeans = KMeans(n_clusters=k, n_init=15).fit(log_pca_score)
silhouette_score(log_pca_score, log_pca_kmeans.labels_)
           

输出:

0.4454977689225694
           

轮廓系数0.445,效果还行。 

5.5.2、降维之后聚类效果

plt.figure(figsize=[4, 3])

for cluster, marker in zip(range(k), markers[:k]):
    x_axis = log_pca_score[:, 0][log_pca_kmeans.labels_ == cluster]
    y_axis = log_pca_score[:, 1][log_pca_kmeans.labels_ == cluster]
    plt.scatter(x_axis, y_axis, marker=marker)
    
plt.show()
           

输出:

多元统计分析——聚类分析——K-均值聚类应用场景

我们发现3个簇之间,样本点相对是比较均匀的。可以根据聚类标签查看各类的样本数。

5.5.3、聚类之后各类的数量

pd.DataFrame(log_pca_score).groupby(log_pca_kmeans.labels_).count()
           

输出:

多元统计分析——聚类分析——K-均值聚类应用场景

从上面可以看出,各类是相对均衡的。

5.5.4、解释模型(特征分析)——使用原始数据

结合聚类结果,根据簇的标签进行分组,看原始数据各簇的质心(平均值)。

co = profile_telecom.iloc[:, 1:5].groupby(log_pca_kmeans.labels_).mean()
co
           

输出:

多元统计分析——聚类分析——K-均值聚类应用场景

由上面我们可知:第一类:打电话最多,其他项目很少;第二类:所有项目用的都不多;第三类:所有项目都有用,且处于正常水平。

结合上面主成分分析输出的主成分:

array([[ 0.22077367,  0.54471581,  0.5687719 ,  0.57536266],
       [ 0.97202048, -0.19050882, -0.08855497, -0.10507422]])
           

第一个主成分,各变量的权重相对接近, 第二个主成分,第一个变量的权重较高。

通过以下的可视化更加直观:

co.T.plot(figsize=[4, 3])
plt.show()
           

输出:

多元统计分析——聚类分析——K-均值聚类应用场景

结论:在电信行业,打电话为基本业务,其他的为增值业务。第0簇:打电话较多,可进行语音包推荐;第1簇:所有项目都不多,属于低端用户,语音为刚性需求,可激活一些流量的需求,如闲时的流量包;第2簇:属于正常用户。

注意:以上的根据“标签分组算平均值”的方法适用于变量少的情况,对于变量维度较多的,我们对聚类结果的特征分析时,可以运用到决策树,从上往下,探索各类用户最主要的特征,如下:

关于决策树,详见《机器学习——有监督——决策树(分类树)相关原理及sklearn实现(信息熵、基尼系数、信息增益、特征重要程度的量化)》。

多元统计分析——聚类分析——K-均值聚类应用场景

继续阅读