首先我们要明白我们此时对客户进行细分的目的是什么,根据高峰期电话数等特征我们可以将客户划分为不同的类别,从而采取不同的策略。
聚类分析是属于一种无监督学习,这里我们首先看一下有监督学习和无监督学习处理数据的不同方法,有监督学习时我们对模型输入的是带有类标签的数据,模型通过学习带有标签的数据,然后输入一个新的数据之后模型会根据之前学习的特征然后对新的数据做类别判定。
之前我们学习的如何选择隐形眼镜就是一个典型的有监督学习,通过输入各类数据标签,最后输出决定其是否适合其佩戴的类标签,医生最初是如何决定是否其适合佩戴的就是通过聚合多类标签判断其是否适合佩戴,最终将适合其佩戴的标签选择出来,为后来的决策提供依据。
最简单的无监督学习聚类方法就是Kmeans方法,实现需要指定最终形成的聚类分成几类,就是把所有的数据大致分成几类,然后分成三类之后有新的点需要确定要加入哪个类别时,就会计算每个点到三个类中心的距离,将该点归入最近的类中心,归入类中心之后再次更新每个新类的类中心。
'''step1 调用包'''
import pandas as pd
#import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from sklearn import preprocessing
#Kmeans聚类分析
from sklearn.cluster import KMeans
'''step2 导入数据'''
data = pd.read_excel('data_customer.xlsx',index_col=0)
data1 = pd.read_excel('data_customer.xlsx')
#有无index_col是指有无左边专属的索引列
'''step3 数据预处理'''
#数据标准化,消除特征量纲的影响
#将属性缩放到一个指定范围,即(x-min)/(max-min)
scaler = preprocessing.MinMaxScaler()
z_data = pd.DataFrame(scaler.fit_transform(data))
#为了可视化聚类结果,以下提取data的部分数据的两列特征为例。
# 提取前1000个用户,特征0-高峰期电话数;特征6-国际电话时长
data_used = z_data.iloc[:1001,[0,6]]
#部分数据(两列)可视化
mpl.rcParams['font.sans-serif'] = ['simHei']
mpl.rcParams['axes.unicode_minus'] = False
plt.figure()
plt.plot(data_used.iloc[:,0],data_used.iloc[:,1], 'k.')
plt.xlabel('高峰期电话数')
plt.ylabel('国际电话时长')
'''step4 聚类分析'''
model_km = KMeans(n_clusters=3)#指定分类
model_km.fit(data_used)
label_pred = model_km.labels_ #获取聚类标签
print('聚类类别',label_pred)
centroids = model_km.cluster_centers_ #获取聚类中心
print('聚类中心坐标\n',centroids)
'''step5 结果可视化'''
#原文链接:https://blog.csdn.net/Andy_shenzl/article/details/83276084
plt.figure()
plt.scatter(data_used.iloc[:,0], data_used.iloc[:,1]
, c=model_km.labels_)#原始数据散点图,按照分类查看
centroids = model_km.cluster_centers_
plt.scatter(centroids[:,0], centroids[:,1],
marker='*', s=179, linewidths=3,
color='r', zorder=10)#重心红色X进行突出
plt.xlabel('高峰期电话数')
plt.ylabel('国际电话时长')
一、调用所需要的包
'''step1 调用包'''
import pandas as pd
#import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from sklearn import preprocessing
#Kmeans聚类分析
from sklearn.cluster import KMeans
这里我们可以看到我们所使用的 Kmeans 此刻是从 sklearn 中的 cluster 中调用的,同时我们还要进行一个数据预处理。
二、导入数据
'''step2 导入数据'''
data = pd.read_excel('data_customer.xlsx',index_col=0)
这里我们可以看到一个细节就是将顾客的ID当作了索引列,而不是具体的用来分类的数据,因为当时并没有凭借顾客的ID对顾客的等级进行划分。
三、数据预处理
'''step3 数据预处理'''
#数据标准化,消除特征量纲的影响
#将属性缩放到一个指定范围,即(x-min)/(max-min)
scaler = preprocessing.MinMaxScaler()
z_data = pd.DataFrame(scaler.fit_transform(data))
#为了可视化聚类结果,以下提取data的部分数据的两列特征为例。
# 提取前1000个用户,特征0-高峰期电话数;特征6-国际电话时长
data_used = z_data.iloc[:1001,[0,6]]
#部分数据(两列)可视化
mpl.rcParams['font.sans-serif'] = ['simHei']
mpl.rcParams['axes.unicode_minus'] = False
plt.figure()
plt.plot(data_used.iloc[:,0],data_used.iloc[:,1], 'k.')
plt.xlabel('高峰期电话数')
plt.ylabel('国际电话时长')
这里是选取了最小最大化标准方法来进行标准化,
- 从sklearn.preprocessing导入MinMaxScaler。
- 创建MinMaxScaler对象scaler。
- 调用fit_transform()方法,传入原始DataFrame数据data,对其进行拟合和转换。
- fit_transform()方法会返回归一化后的数据,转化为DataFrame格式,存储在z_data中。
MinMaxScaler会将数据线性缩放到[0, 1]区间。它通过找到数据的最小值和最大值,然后对数据进行如下转换:
X_std = (X - X.min) / (X.max - X.min)
这样可以把不同范围的特征值转换到一个统一的范围内,便于不同特征之间的比较和后续建模。
所以这段代码实现了用MinMaxScaler对DataFrame进行特征归一化的操作。
将数据归一化后存储在 z_data中如图所示,为了可视化聚类效果这里只选取了其中两列数据进行可视化分析, - plt.plot() 是matplotlib库中的绘制方法。
- data_used.iloc[:,0] 取数据框data_used的第0列,作为x轴数据。
- data_used.iloc[:,1] 取数据框data_used的第1列,作为y轴数据。
- ‘k.’ 表示绘制黑色圆点标记的散点图。‘k’表示黑色,’.'表示点的标记样式。
- 所以这行代码最终效果是:
以data_used的第0列为x轴,第1列为y轴,绘制一个黑色圆点标记的散点图。
为了便于分析我们之前是选取的第0列和第6列进行分析,选取完之后数据的列就重新进行规划了,所以说现在作图是选取的第0列和第1列。
‘b’- blue
‘g’- green
‘r’- red
‘c’- cyan
‘m’- magenta
‘y’- yellow
‘k’- black
‘w’- white
常用的点标记样式及其表示:
‘.’ - 点
‘,’ or ‘o’ - 圆圈
‘v’ - 倒三角
‘^’ - 上三角
‘<’ - 左三角
‘>’ - 右三角
‘1’ - 下花三角
‘2’ - 上花三角
‘3’ - 左花三角
‘4’ - 右花三角
‘8’ - 八角形
‘p’ - 五边形
‘*’ - 星形
‘h’ - 六边形 1
‘H’ - 六边形 2
‘+’ - 加号
‘x’ - 叉号
‘D’ - 菱形
‘d’ - 窄菱形
例如:‘r^’ 表示红色上三角标记,‘bo’ 表示蓝色圆圈标记
这里是选取的另一种组合 rh,红色六边形1组合
四、聚类分析
'''step4 聚类分析'''
model_km = KMeans(n_clusters=3)#指定分类
model_km.fit(data_used)
label_pred = model_km.labels_ #获取聚类标签
print('聚类类别',label_pred)
centroids = model_km.cluster_centers_ #获取聚类中心
print('聚类中心坐标\n',centroids)
指定分为三类,通过n_clusters设定分类数。
- model_km 是已训练好的KMeans模型对象。
- KMeans模型有一个labels_属性,它存储了对样本的聚类预测结果。
- labels_属性是一个数组,数组中的每个值代表对应样本被预测到的聚类标签。
- 通过model_km.labels_可以直接获取预测聚类标签。
- 将其赋值给label_pred变量,则label_pred就是模型对所有样本预测的聚类标签。
- 该标签从0开始,最大值为k-1(k是聚类数)。
- 根据标签,就可以知道每个样本被聚类到哪一个类别中。
所以这行代码利用预先训练好的KMeans模型,通过labels_属性很方便地获取聚类预测结果,是模型预测聚类很常见的操作。
分好三类之后便可以获取得到每一类的类中心坐标。
五、结果可视化
plt.figure()
plt.scatter(data_used.iloc[:,0], data_used.iloc[:,1]
, c=model_km.labels_)#原始数据散点图,按照分类查看
centroids = model_km.cluster_centers_
plt.scatter(centroids[:,0], centroids[:,1],
marker='*', s=179, linewidths=3,
color='r', zorder=10)#重心红色X进行突出
plt.xlabel('高峰期电话数')
plt.ylabel('国际电话时长')
这段代码的作用是绘制KMeans聚类模型的聚类中心点,使用特殊的标记样式进行突出显示。
具体来看:
- centroids是一个二维数组,第一列是聚类中心的x坐标,第二列是y坐标。
- plt.scatter绘制散点图,传入centroids的两列作为坐标。
- marker=‘*’ 指定星形标记。
- s=179 设置点的大小。
- linewidths=3 设置点边界线宽度。
- color=‘r’ 设置点的颜色为红色。
- zorder=10 设置绘制层级,使其在最上层显示。
总结:
利用plt.scatter绘制特殊标记(红色星形)的点图,坐标为聚类中心,并设置较大点大小,宽边框和高层级,使其突出显示,以便清晰标注聚类中心的位置,这里虽然聚类中心点只有三个。
zorder参数可以设置绘制的层级,如果想让点图显示在下层,可以将zorder设置为一个负数,例如:
plt.scatter(x, y, zorder=-1)
zorder的参数值含义:
- 正整数:绘制在顶层,数值越大越靠上。
- 负整数:绘制在底层,数值越小越靠下。
- 0:默认的层级。
所以,如果想让点图显示在较底层,可以如下设置:
python
plt.scatter(x, y, zorder=-5) # 画在较底层
plt.plot(x, y, zorder=1) # 画在上层
zorder是一个很有用的参数,通过控制同一幅图中不同元素的层级,可以实现重叠和遮挡等视觉效果。
主要注意的是:
- 越大越靠上层,反之亦然。
- 在同一层级中,后绘制的元素会覆盖先绘制的元素。
合理控制zorder可以使复杂图形的显示更加清晰。