聚类分析是一种比较常见算法,实际应用也很多,比如大家经常听到的RMF模型、分客群精准营销等都是聚类分析的应用。
我们可以用“物以类聚、人以群分”来简单理解,它是一种无监督的分类算法。但是这种“简单”的算法,在运用到实际工作中会遇到很多问题,比如:
①极端值的影响造成个别几个样本被聚为了一类,剩余绝大部分样本被聚为了一类,相当于没有聚类。
②指标太多,不知道选哪些指标,量纲该如何处理?
③聚出来的客群大的大小的小,无法营销。
④不知道聚类效果如何,是否使用了最好的聚类算法,得到了最佳的N个客群。
聚类算法是基于距离计算的,所以我们选择的指标一定是数值型变量,大部分情况下都需要消除量纲的影响。
聚类算法按照方式不同,可以分为凝聚式和分裂式两种。
凝聚式 Agglometative:顾名思义就是开始时将所有的样本(n个)都视为一类(n类),然后一步步的把距离近的聚为一类,最终所有样本聚为一类的方法。
分裂式 Divisive:开始时将所有样本视为一类,最终拆分到每个样本都是一类。
我们来看一下 Python 中聚类算法的实现。
1. 常见的聚类算法
skleaarn中展示了不同的聚类算法适用的数据分布及运行时间。 链接
可以看到不同的算法适合不同的数据分布,也有不同的时耗,具体使用哪种算法,需要根据数据情况来选择,甚至迭代不同算法不同参数来择优。
%pylab inline from IPython.display import Image Image('cluster methods.png')
2. 聚类算法示例
我们使用内置的鸢尾花数据集来进行聚类。鸢尾花数据集:共150条记录,有花萼长度、花萼宽度、花瓣长度、花瓣宽度、品种5个变量,其中每个品种50条记录。
2.1 使用scipy进行层次聚类
import scipy.cluster.hierarchy as sch import matplotlib.pyplot as plt # 中文和负号的正常显示 plt.rcParams['font.sans-serif'] = ['Microsoft YaHei'] plt.rcParams['axes.unicode_minus'] = False plt.figure(figsize=[15,5]) dendrogram = sch.dendrogram(sch.linkage(iris.data, method='ward')) #ward最小方差法(使用的是欧氏距离) plt.title('鸢尾花聚类树状图') plt.xlabel('鸢尾花数据') plt.ylabel('欧式距离') plt.show()
根据树状图我们可以确定聚为几类及样本分类,这种方法非常直观,但是不适用于大样本。
2.2 凝聚聚类
from sklearn.cluster import AgglomerativeClustering ac = AgglomerativeClustering(n_clusters=3, affinity='euclidean', linkage='ward') y_ac = ac.fit_predict(iris.data)
# 查看聚类结果 # 我们使用鸢尾花的花瓣长度和花瓣宽度做散点图,用散点颜色来区分鸢尾花的品种 import matplotlib.pyplot as plt %matplotlib inline plt.figure(figsize=(12, 12)) plt.subplot(221) color = {0:'r',1:'y',2:'b'} plt.scatter(iris.data[:,2], iris.data[:,3], c=[color[_] for _ in y_ac]) plt.title('Cluster data') color = {0:'y',1:'b',2:'r'} plt.subplot(222) plt.scatter(iris.data[:,2], iris.data[:,3], c=[color[_] for _ in iris.target]) plt.title('Original data') plt.show()
2.3 KMeans聚类
from sklearn.cluster import KMeans model_kmeans = KMeans(n_clusters=3, init='k-means++', random_state=123) y_pred = model_kmeans.fit_predict(iris.data) model_kmeans.cluster_centers_ # 类中心
# 聚类效果可视化 colors = ['red', 'blue', 'green'] for i in range(3): plt.scatter(iris.data[y_pred == i, 2], iris.data[y_pred == i, 3], s = 100, c = colors[i], label = 'Cluster '+str(i+1)) plt.scatter(model_kmeans.cluster_centers_[:,2], model_kmeans.cluster_centers_[:,3], s = 200, c = 'yellow', label = 'Center') plt.title('Clusters of Iris') plt.xlabel('Petal.Length') plt.ylabel('Petal.Width') plt.legend() plt.show()
3. 聚类算法调优
3.1 极端值处理
从散点图来看:鸢尾花数据集中是没有特别极端的值的,但是实际数据中很可能存在离群点或极端值(如某个大客户的交易额),这些样本点会增加极差,聚类效果不佳(绝大部分聚为一类,个别样本聚为一类),但换个角度想,这些恰恰是我们的异常数据,可以做异常检查,比如说刷单客户识别,这样的场景下我们不要对数据分布进行处理。
3.2 聚类个数的确定
我们知道鸢尾花数据集中有setosa、versicolor、virginica三个品种,但实际上聚类算法是无监督学习算法,我们并不知道结果,那么如何确定聚类个数呢? 按照聚类算法“物以类聚,人以群分”的思想,自然是簇内距离最小,簇间距离最大为最好的分群标准。
# 使用inertia或silhouette_score来确定 from sklearn import metrics plt.figure(figsize=[8, 2]) rng1 = range(1, 11) rng2 = range(2, 11) inertia = [] silhs = [] for k in rng1: model = KMeans(n_clusters=k) model.fit(iris.data) inertia.append(model.inertia_) for k in rng2: model = KMeans(n_clusters=k) model.fit(iris.data) silhs.append(metrics.silhouette_score(iris.data, model.predict(iris.data))) plt.subplot(121) plt.title('inertia') plt.plot(rng1, inertia) plt.subplot(122) plt.title('silhouette_score') plt.plot(rng2, silhs) plt.show()
从上图可以看出:inertia在K=2时出现拐点,silhouette_score在K=2时最大,说明聚为2类比较合适。从鸢尾花花瓣的散点图来看,散点确实分布在两个区域。 这里只做算法演示,实际运用中还是要根据客观情况决定。比如本例中我们已知是三个品种的鸢尾花数据,那么肯定是要聚为三类的。
# 看一下聚为两类时各客群的样本量 import pandas as pd model_kmeans = KMeans(n_clusters=2, init='k-means++', random_state=123) y_pred = model_kmeans.fit_predict(iris.data) df_y_pred = pd.DataFrame(y_pred, columns=['cluseter']) df_y_pred['cluseter'].value_counts()
可以看到聚为两类时一个客群97个样本,一个客群53个样本。
3.3 变量的选择
我们在对样本进行聚类时,通常有许多指标可供选择,但是选择哪些指标呢?我们可以从两个方面来选择:一是看数据分布,只选择我们看中的且特征明显的指标;二是对我们认为应该选中的指标进行降维,例如主成分分析(PCA)。
3.3.1 主观选择变量
# 看一下鸢尾花的四个指标的散点图分布 import seaborn as sns df_iris = pd.concat([pd.DataFrame(iris.data, columns=iris.feature_names), pd.DataFrame(iris.target, columns=['species'])], axis=1) sns.pairplot(df_iris, hue='species', kind='reg', diag_kind='kde', size=1.5) plt.show()
可以看到三个品种的花萼长度和花萼宽度散点图区别不大,而花瓣长度和花瓣宽度散点图区别较大,我们只选用花瓣数据进行聚类。
由于我们已知三个鸢尾花,我们使用模型的调整兰德指数来作为聚类效果的评判标准。(注:实际中并不知道分类结果,我们这里只做算法比较用)。 调整兰德指数 adjusted_rand_s:值介于0到1之间,值越大,聚类效果越好。
# 先来看一下使用四个变量聚为三类的模型得分 model_a = KMeans(n_clusters=3, init='k-means++', random_state=123) y_pred_a = model_a.fit_predict(iris.data) ARI_a = metrics.adjusted_rand_score(y_pred_a, iris.target) ARI_a
得到:ARI_a=0.73
# 仅使用花瓣的两个变量聚为三类的模型得分 model_b = KMeans(n_clusters=3, init='k-means++', random_state=123) y_pred_b = model_a.fit_predict(iris.data[:,2:4]) ARI_b = metrics.adjusted_rand_score(y_pred_b, iris.target) ARI_b
得到:ARI_b=0.89
3.3. 2 对多变量降维
from sklearn.decomposition import PCA pca = PCA(n_components=4) pca.fit(iris.data) pca.explained_variance_ratio_
得到主成分的方差解释比例:array([0.92461621, 0.05301557, 0.01718514, 0.00518309]), 可以看到第一个主成分就能解释92%的方差(一般前n个主成分累计超过80%即可),所以我们可以选择一个主成分,但是为了数据展示需要,这里我们选择两个主成分。
pca = PCA(n_components=2) pca.fit(iris.data) iris_data_pca = pca.transform(iris.data)
# 先看一下得到的降维数据三种鸢尾花散点图 plt.scatter(iris_data_pca[:, 0], iris_data_pca[:, 1],c=iris.target) plt.title('pca iris data') plt.show()
# 使用降维后的数据进行聚类 model_c = KMeans(n_clusters=3, init='k-means++', random_state=123) y_pred_c = model_c.fit_predict(iris_data_pca) ARI_c = metrics.adjusted_rand_score(y_pred_c, iris.target) ARI_c
得到:ARI_c=0.72, 略低于ARI_a的0.73。本例中聚类效果没有提升,但使用PCA可以解决高维变量的聚类问题。
3.4 变量分布处理
当我们需要将全部样本数据较均匀的拆分为N个客群时,样本数据的分布会造成较大的影响,为此我们可以改变样本数据的分布形态,来达到均衡客群量的问题。
# 先正态化后再聚类 from sklearn.preprocessing import StandardScaler, Normalizer iris_norm = Normalizer().fit_transform(iris.data) model_d = KMeans(n_clusters=3) y_pred_d = model_d.fit_predict(iris_norm) ARI_d = metrics.adjusted_rand_score(y_pred_d, iris.target) ARI_d
ARI_d提升到了0.90!
# 正态+降维后再聚类 iris_norm_pca = PCA(n_components=2).fit_transform(iris_norm) model_e = KMeans(n_clusters=3).fit(iris_norm_pca) y_pred_e = model_e.fit_predict(iris_norm) ARI_e = metrics.adjusted_rand_score(y_pred_e, iris.target) ARI_e
本例中ARI_e并没有提升。
4. 总结
综上,我们总结一下开篇提到的四个问题:
①极端值问题:若是识别异常客户,极端值是不需要处理的;若是分群,可以对数据进行标准化、正态化处理。
②指标太多、量纲处理:首先可以主观判断,其次可以使用主成分分析。比如使用销售额、利润额和毛利率三个指标直接聚类显然是不合适的。
③客群大小:可以正态化处理让客群大小更加均衡,有时可以调整客群数来满足客群量的问题。
④聚为几类:如果是明确的,就直接聚为几类;也可以通过树状图、inertia、silhouette来确定。
以上,如有不妥之处还请多多指正。
本文由okajun 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。
以上所述就是小编给大家介绍的《聚类分析的一些套路》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 数据分析4要素,轻松掌握小“套路”!
- 4大数据分析要素 “套路”方法要学会!
- 复杂度分析的套路及常见的复杂度
- MySQL 死锁套路:一次诡异的批量插入死锁问题分析
- 慢SQL诊断优化套路包,套路用的对,速度升百倍
- 数据迁移的套路
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
人人都是架构师:分布式系统架构落地与瓶颈突破
高翔龙 / 电子工业出版社 / 2017-5 / 69
《人人都是架构师:分布式系统架构落地与瓶颈突破》并没有过多渲染系统架构的理论知识,而是切切实实站在开发一线角度,为各位读者诠释了大型网站在架构演变过程中出现一系列技术难题时的解决方案。《人人都是架构师:分布式系统架构落地与瓶颈突破》首先从分布式服务案例开始介绍,重点为大家讲解了大规模服务化场景下企业应该如何实施服务治理;然后在大流量限流/消峰案例中,笔者为大家讲解了应该如何有效地对流量实施管制,避......一起来看看 《人人都是架构师:分布式系统架构落地与瓶颈突破》 这本书的介绍吧!