Python数据分析与数据化运营

案例-基于自动K值的KMeans广告效果聚类分析

Author
宋天龙
发布于 2018-01-09
3634 次阅读
0 次赞
0 次分享
案例-基于自动K值的KMeans广告效果聚类分析
AI 智能核心导读

本文基于KMeans聚类算法对企业多维度广告渠道数据进行建模分析。通过平均轮廓系数确定最佳K值,将广告渠道精准划分为平庸、质量、精英及引流拉新四类,并利用雷达图直观对比各类别显著特征。分析结果为企业优化广告结构、制定差异化投放策略及提升整体营销ROI提供了科学的数据支持与业务洞察。

企业广告渠道效果聚类分析案例

一、 案例背景与需求预设

某企业由于投放的广告渠道比较多,需要对其做广告效果分析,以实现有针对性的广告效果测量和优化工作。跟以应用为目的的案例不同的是,由于本案例是一个分析型案例,该过程的输出其实是不固定的,因此需要跟业务运营方具体沟通需求。

以下是在开展研究之前的基本预设条件:

  • 广告渠道的范畴是什么?具体包括哪些渠道? 所有站外标记的广告类渠道(以 ad_ 开头)。
  • 数据集时间选择哪个时间段? 最近 90 天的数据。
  • 数据集选择哪些维度和指标? 渠道代号、日均 UV、平均注册率、平均搜索量、访问深度、平均停留时间、订单转化率、投放总时间、素材类型、广告类型、合作方式、广告尺寸、广告卖点。
  • 专题分析要解决什么问题? 将广告分类并找出其重点特征,为接下来的业务讨论和数据分析提供支持。

明确了上述具体需求后,下面开始案例的主要工作部分。本节案例的输入源数据 ad_performance.txt 和源代码 chapter7_code2.py 位于“[附件-chapter7]下载源代码和数据”中,默认工作目录为“[附件-chapter7]”。程序的输出为不同聚类类别的详细信息数据以及雷达图。

二、 核心应用技术

本案例用到的主要技术包括:

  • 数据预处理:数据标准化、字符串分类转整数型分类。
  • 数据建模:KMeans 聚类算法。
  • 数据展示:使用 matplotlib 输出雷达图。

主要用到的库包括:sysnumpypandassklearnmatplotlib,其中 sklearn 是展示数据的核心。KMeans 聚类在“4.1 聚类分析”已经介绍过,本案例的重点有两个:

  1. 基于最优数据尺度确定最佳 K 值:最优佳的聚类类别划分,从数据特征上看是类内距离最小化的同时类间距离最大化。可以使用平均轮廓系数作为指标评估,通过枚举每个 K 计算平均轮廓系数并得到最优值。
  2. 雷达图的绘制:通过极坐标系的设置方式输出雷达图。

三、 案例数据概况

案例数据来自某企业的营销部门数据,该数据基于营销数据、网站分析系统数据和运营系统数据总结而来。

数据基本概况:

  • 维度数:除了渠道唯一标记之外,共 12 个维度。
  • 数据记录数:889 条。
  • 是否有 NA 值:有。
  • 是否有异常值:有。

13 个字段的详细说明:

  • 渠道代号:业务方统一命名规划的唯一渠道标志。
  • 日均 UV:每天的平均独立访客,从一个渠道中带来的一个访客即使一天中到达多次都统计为 1 次。
  • 平均注册率:日均注册的用户数量 / 平均每天的访问量。
  • 平均搜索量:平均每个访问的搜索次数。
  • 访问深度:总页面浏览量 / 平均每天的访问量。
  • 平均停留时间:总停留时间 / 平均每天的访问量。
  • 订单转化率:总订单数量 / 平均每天的访问量。
  • 投放总时间:每个广告媒介在站外投放的天数。
  • 素材类型:广告素材类型,包括 jpg、gif、swf、sp。
  • 广告类型:广告投放类型,包括 banner、tips、横幅、通栏、暂停以及不确定(不知道到底是何种形式)。
  • 合作方式:广告合作方式,包括 roi、cpc、cpm 和 cpd。
  • 广告尺寸:每个广告投放的尺寸大小,包括 140*40、308*388、450*300、600*90、480*360、960*126、900*120、390*270。
  • 广告卖点:广告素材上主要的卖点诉求信息,包括打折、满减、满赠、秒杀、直降、满返。

四、 案例实操过程

步骤 1:导入依赖库

python
1import sys 2reload(sys) 3sys.setdefaultencoding('utf-8') 4import pandas as pd 5import numpy as np 6from sklearn.feature_extraction import DictVectorizer # 字符串分类转整数分类库 7from sklearn.preprocessing import MinMaxScaler # MinMaxScaler库 8from sklearn.cluster import KMeans # KMeans模块 9from sklearn import metrics # 导入sklearn效果评估模块 10import matplotlib.pyplot as plt # 图形库

本案例主要用到了以下库:

  • sys:系统库,用来将默认编码设置为 UTF-8,目的是处理中文。
  • numpy:基本数据处理。
  • pandas:数据读取、审查、异常值处理等。
  • DictVectorizer:用来将字符串分类转换为整数型分类。
  • MinMaxScaler:数据标准化库,用来将数据做标准化处理。
  • KMeans:K 均值聚类算法模块。
  • metrics:sklearn 效果评估模块。
  • pyplot:用来做雷达图展示。

步骤 2:读取原始数据

使用 pandasread_table 方法读取 txt 文件,分隔符为 TAB。

python
1raw_data = pd.read_table('ad_performance.txt', delimiter='\t')

步骤 3:数据审查与校验

该步骤包括多个环节:查看前 2 条数据、查看数据类型分布、查看缺失值、查看数据描述性统计信息、相关性分析等。

1. 查看前 2 条数据

python
1print ('{:*^60}'.format('Data overview:')) 2print (raw_data.head(2)) # 打印输出前2条数据

从返回结果看,原始数据能正常识别且没有异常信息:

code
1***********************Data overview:*********************** 2渠道代号 日均UV 平均注册率 平均搜索量 访问深度 平均停留时间 订单转化率 投放总时间 30 A203 3.69 0.0071 0.0214 2.3071 419.77 0.0258 20.0 jpg banner 41 A387 178.70 0.0040 0.0324 2.0489 157.94 0.0030 19.0 jpg banner 5合作方式 广告尺寸 广告卖点 60 roi 140*40 打折 71 cpc 140*40 满减

2. 查看数据类型分布 使用 dtypes 方法查看数据类型分布,通过 pd.DataFrame 将其结果转换为数据框,然后通过 .T 做转置。

python
1print ('{:*^60}'.format('Data dtypes:')) 2print (pd.DataFrame(raw_data.dtypes).T) # 打印数据类型分布

各个字段类型都能被正确识别:

code
1************************Data dtypes:************************ 2渠道代号 日均UV 平均注册率 平均搜索量 访问深度 平均停留时间 订单转化率 投放总时间 \ 30 object float64 float64 float64 float64 float64 float64 float64 4素材类型 广告类型 合作方式 广告尺寸 广告卖点 50 object object object object object

3. 查看缺失值 使用 isnull().sum() 查看所有字段中具有缺失值数据的统计量。

python
1print ('{:*^60}'.format(' NA counts:')) 2print (pd.DataFrame(raw_data.isnull().sum()).T) # 查看缺失值情况

从结果中发现,在“平均停留时间”字段中有 2 个缺失值:

code
1************************ NA counts:************************* 2渠道代号 日均UV 平均注册率 平均搜索量 访问深度 平均停留时间 订单转化率 投放总时间 素材类型 广告类型 合作方式 \ 30 0 0 0 0 0 2 0 0 0 0 0 4广告尺寸 广告卖点 50 0 0

4. 查看数据描述性统计信息 使用 describe() 查看数据描述性统计信息,并使用 round(2) 保留 2 位小数。

python
1print ('{:*^60}'.format('Data DESC:')) 2print (raw_data.describe().round(2).T) # 打印原始数据基本描述性信息

描述性统计结果反映了 3 个信息点:

  • 日均 UV 波动极大:说明不同渠道间的特征差异非常明显。
  • 平均停留时间缺失:有效数据(非空数据)只有 887,比其他数据少 2 条,印证了缺失值统计结果。
  • 部分指标看似异常:平均注册率、平均搜索量、订单转化率的多个统计量(如最小值、25% 分位数等)都为 0,看似数据不太正常。

以上三类异常点,经过跟业务方的沟通以及再次数据验证,结论如下:

  • 日均 UV 的差异性:由于广告的流量型特征明显,很多广告的流量爆发明显,渠道间确实带有非常大的差异性。这些差异性应该保留,不能作为异常值处理
  • 平均停留时间的缺失值:由于统计缺失导致数据丢失,可以使用均值法做填充。
  • 统计量为 0 的问题:这是由于在打印输出过程中仅保留了 2 位小数,而这几个统计量的数据本身就非常小,将其通过 round(3) 保留 3 位小数后就能正常显示。

5. 相关性分析

python
1print ('{:*^60}'.format('Correlation analysis:')) 2print (raw_data.corr().round(2).T) # 打印原始数据相关性信息

通过相关性结果分析,12 个特征中平均停留时间访问深度的相关系数为 0.72,这两个指标具有较高的相关性,但特征也不是非常明显;其他特征之间的相关性关系都不突出。

步骤 4:数据预处理

本步骤主要涉及到缺失值替换、字符串分类转换为整数分类、数据标准化、数据合并等操作。

Part 1:缺失值替换 使用 fillna 方法将“平均停留时间”中的缺失值替换为均值。

python
1data_fillna = raw_data.fillna(raw_data['平均停留时间'].mean()) # 用均值替换缺失值

Part 2:字符串分类转整数分类 主要区别在于这里由于没有“预测”环节,因此无需区分训练阶段和预测阶段。

首先,定义要转换的数据并建立空列表:

python
1conver_cols = ['素材类型', '广告类型', '合作方式', '广告尺寸', '广告卖点'] 2convert_matrix = data_fillna[conver_cols] # 获得要转换的数组 3lines = data_fillna.shape[0] # 获得总记录数 4dict_list = [] # 总空列表,用于存放字符串与对应索引组成的字典 5unique_list = [] # 总唯一值列表,用于存储每个列的唯一值列表

其次,使用 for 循环获得所有列的唯一值列表,存入 unique_list

python
1for col_name in conver_cols: # 循环读取每个列名 2 cols_unqiue_value = data_fillna[col_name].unique().tolist() # 获取列的唯一值列表 3 unique_list.append(cols_unqiue_value) # 将唯一值列表追加到总列表

接着,使用 for 循环将每条记录的具体值跟其在唯一值列表中的索引做映射:

python
1for line_index in range(lines): # 读取每行索引 2 each_record = convert_matrix.iloc[line_index] # 获得每行数据,是一个Series 3 for each_index, each_data in enumerate(each_record): # 读取Series每行对应的索引值 4 list_value = unique_list[each_index] # 查找唯一值在列表中的位置 5 each_record[each_index] = list_value.index(each_data) # 获得每个值对应到总唯一值列表中的索引 6 each_dict = dict(zip(conver_cols, each_record)) # 将每个值和对应的索引组合字典 7 dict_list.append(each_dict) # 将字典追加到总列表

最后,使用 DictVectorizer 将字符串转换为整数:

python
1model_dvtransform = DictVectorizer(sparse=False, dtype=np.int64) # 建立转换模型对象 2data_dictvec = model_dvtransform.fit_transform(dict_list) # 应用分类转换训练

注:设置 sparse=False 指定转换后的数据集是一个数组,否则默认会是压缩后的稀疏矩阵,后续很多步骤和模型不支持直接基于稀疏矩阵建模。

Part 3:数据标准化 由于不同字段间存在数值的量纲差异(例如日均 UV 有几万的量级,而转化率的范围却是 0-1 之间),因此需要做数据标准化,这里使用的是 Min-Max 标准化方法。

python
1sacle_matrix = data_fillna.ix[:, 1:8] # 获得要转换的矩阵 2minmax_scaler = MinMaxScaler() # 建立MinMaxScaler模型对象 3data_scaled = minmax_scaler.fit_transform(sacle_matrix) # MinMaxScaler标准化处理

Part 4:合并所有输入维度 使用 numpyhstack 方法,将处理后的数值型和字符串型结果合并,形成最终输入 X

python
1X = np.hstack((data_scaled, data_dictvec))

注意:这里的 X 不包含渠道的唯一标志列,因为该列没有实际建模意义。

步骤 5:基于平均轮廓系数确定最佳 K 值

K 值的确定一直是 KMeans 算法的关键。由于 KMeans 是非监督式学习,没有绝对的“最佳”K 值。但从数据特征来讲,最佳 K 值对应的类别下应该是类内距离最小化并且类间距离最大化

我们可以通过枚举法计算每个 K 下的平均轮廓系数值,然后选出平均轮廓系数最大下的 K 值。

注意:即使在数据上聚类特征最明显,也并不意味着聚类结果就是有效的。因为聚类结果用来分析使用,不同类别间需要具有明显的差异性特征,并且类别间的样本量需要大体分布均衡。而单纯依靠算法确定最佳 K 值时,并没有考虑到这些“业务性”因素。

python
1score_list = list() # 用来存储每个K下模型的平局轮廓系数 2silhouette_int = -1 # 初始化的平均轮廓系数阀值 3 4for n_clusters in range(2, 10): # 遍历从2到10几个有限组 5 model_kmeans = KMeans(n_clusters=n_clusters, random_state=0) # 建立聚类模型对象 6 cluster_labels_tmp = model_kmeans.fit_predict(X) # 训练聚类模型 7 silhouette_tmp = metrics.silhouette_score(X, cluster_labels_tmp) # 得到每个K下的平均轮廓系数 8 9 if silhouette_tmp > silhouette_int: # 如果平均轮廓系数更高 10 best_k = n_clusters # 将最好的K存储下来 11 silhouette_int = silhouette_tmp # 将最好的平均轮廓得分存储下来 12 best_kmeans = model_kmeans # 将最好的模型存储下来 13 cluster_labels_k = cluster_labels_tmp # 将最好的聚类标签存储下来 14 15 score_list.append([n_clusters, silhouette_tmp]) # 将每次K及其得分追加到列表 16 17print ('{:*^60}'.format('K value and silhouette summary:')) 18print (np.array(score_list)) # 打印输出所有K下的详细得分 19print ('Best K is:{0} with average silhouette of {1}'.format(best_k, silhouette_int.round(4)))

返回数据如下:

code
1**************K value and silhouette summary:*************** 2[[ 2. 0.46692821] 3 [ 3. 0.54904646] 4 [ 4. 0.56968547] 5 [ 5. 0.48186604] 6 [ 6. 0.45477667] 7 [ 7. 0.48204261] 8 [ 8. 0.50447223] 9 [ 9. 0.52697493]] 10Best K is:4 with average silhouette of 0.5697

就经验看,如果平均轮廓得分值小于 0,意味着聚类效果不佳;如果在 0 到 0.5 之间,说明聚类效果一般;如果大于 0.5,则说明聚类效果比较好。本案例在 K=4 时,得分为 0.5697,说明效果较好。

步骤 6:聚类结果特征分析

Part 1:将原始数据与聚类标签整合

python
1cluster_labels = pd.DataFrame(cluster_labels_k, columns=['clusters']) # 获得训练集下的标签信息 2merge_data = pd.concat((data_fillna, cluster_labels), axis=1) # 将原始处理过的数据跟聚类标签整合

注:这里使用了经过缺失值填充后的 data_fillna 数组做合并,而不是标准化的 X,目的是为了在分析时能够再现不同特征下原始值的特征,便于业务理解。

Part 2:计算每个聚类类别下的样本量和样本占比

python
1clustering_count = pd.DataFrame(merge_data['渠道代号'].groupby(merge_data['clusters']).count()).T.rename({'渠道代号': 'counts'}) # 计算每个聚类类别的样本量 2clustering_ratio = (clustering_count / len(merge_data)).round(2).rename({'counts': 'percentage'}) # 计算每个聚类类别的样本量占比

Part 3:计算各个聚类类别内部最显著特征值

python
1cluster_features = [] # 空列表,用于存储最终合并后的所有特征信息 2for line in range(best_k): # 读取每个类索引 3 label_data = merge_data[merge_data['clusters'] == line] # 获得特定类的数据 4 5 part1_data = label_data.ix[:, 1:8] # 获得数值型数据特征 6 part1_desc = part1_data.describe().round(3) # 得到数值型特征的描述性统计信息 7 merge_data1 = part1_desc.ix[2, :] # 得到数值型特征的均值 8 9 part2_data = label_data.ix[:, 8:-1] # 获得字符串型数据特征 10 part2_desc = part2_data.describe(include='all') # 获得字符串型数据特征的描述性统计信息 11 merge_data2 = part2_desc.ix[2, :] # 获得字符串型数据特征的最频繁值 12 13 merge_line = pd.concat((merge_data1, merge_data2), axis=0) # 将数值型和字符串型典型特征沿行合并 14 cluster_features.append(merge_line) # 将每个类别下的数据特征追加到列表

Part 4:输出完整的类别特征信息

python
1cluster_pd = pd.DataFrame(cluster_features).T # 将列表转化为矩阵 2print ('{:*^60}'.format('Detailed features for all clusters:')) 3all_cluster_set = pd.concat((clustering_count, clustering_ratio, cluster_pd), axis=0) # 将每个聚类类别的所有信息合并 4print (all_cluster_set)

打印输出如下结果:

code
1************Detailed features for all clusters:************* 2clusters 0 1 2 3 3counts 411 297 27 154 4percentage 0.46 0.33 0.03 0.17 5日均UV 1369.81 1194.69 1263.03 2718.7 6平均注册率 0.003 0.003 0.003 0.005 7平均搜索量 0.082 0.144 0.151 0.051 8访问深度 0.918 5.728 9.8 0.948 9平均停留时间 165.094 285.992 374.689 104.14 10订单转化率 0.009 0.016 0.017 0.007 11投放总时间 8.462 8.57 7.996 8.569 12素材类型 swf jpg swf jpg 13广告类型 不确定 不确定 通栏 banner 14合作方式 cpc cpc cpc cpc 15广告尺寸 600*90 600*90 900*120 308*388 16广告卖点 打折 直降 打折 满减

步骤 7:各类别显著数值特征雷达图对比

从上面的各类别特征中可能很难直观发现不同类别的显著性特征,这里通过雷达图的形式对各个聚类类别的数值型特征做对比展示。

1. 各类别数据预处理 由于不同特征的数据量级差异很大,需要先对其做标准化处理。

python
1num_sets = cluster_pd.ix[:6, :].T.astype(np.float64) # 获取要展示的数据 2num_sets_max_min = minmax_scaler.fit_transform(num_sets) # 获得标准化后的数据

2. 画布基本设置

python
1fig = plt.figure() # 建立画布 2ax = fig.add_subplot(111, polar=True) # 增加子网格,注意polar参数 3labels = np.array(merge_data1.index[:-1]) # 设置要展示的数据标签 4cor_list = ['r', 'g', 'b', 'y'] # 定义不同类别的颜色 5angles = np.linspace(0, 2 * np.pi, len(labels), endpoint=False) # 计算各个区间的角度 6angles = np.concatenate((angles, [angles[0]])) # 建立相同首尾字段以便于闭合

相关知识点:极坐标系 极坐标系是指在平面内由极点、极轴和极径组成的坐标系。空间中任意一个点,都可以通过 (ρ,θ) 的有序对的形式表示。极坐标系是一个二维坐标系,与平面直角坐标系(笛卡尔坐标系)可以相互转换:x = ρcosθ, y = ρsinθ

python雷达图
python雷达图

3. 画雷达图

python
1for i in range(len(num_sets)): # 循环每个类别 2 data_tmp = num_sets_max_min[i, :] # 获得对应类数据 3 data = np.concatenate((data_tmp, [data_tmp[0]])) # 建立相同首尾字段以便于闭合 4 ax.plot(angles, data, 'o-', c=cor_list[i], label=i) # 画线

4. 设置图像显示格式

python
1ax.set_thetagrids(angles * 180 / np.pi, labels, fontproperties="SimHei") # 设置极坐标轴 2ax.set_title("各聚类类别显著特征对比", fontproperties="SimHei") # 设置标题放置 3ax.set_rlim(-0.2, 1.2) # 设置坐标轴尺度范围 4plt.legend(loc=0) # 设置图例位置 5plt.show() # 展示图像

最终显示图像如下:

python雷达图
python雷达图

五、 数据结论与业务洞察

初步特征分析

从案例结果来看,所有的渠道被分为 4 个类别,每个类别的样本量分别为 411、297、27、154,对应的占比分别为 46%、33%、3%、17%。第三个类别样本量较少。

结合雷达图,可以清晰地看到不同类别广告媒体的特征倾向:

  1. 聚类 1(索引值为 0):各方面的特征都不明显,效果比较平庸,没有明显的优势或短板。但这些“中庸”的广告媒体却构成了整个广告的主体(占比 46%)。
  2. 聚类 2(索引值为 1):这类广告媒体在访问深度、平均停留时间、订单转化率以及平均搜索量等流量质量的特征上表现较好。除了注册转化率较低外,各方面比较均衡。且规模较大(占比 33%),是一类综合效果较好的媒体。
  3. 聚类 3(索引值为 2):跟聚类 2 非常类似,并且相对聚类 2 的典型特征表现更好。但综合其只有 3% 的媒体数量,属于少量的**“精英”类渠道**。
  4. 聚类 4(索引值为 3):跟其他几类渠道有个明显的特征区隔,其日均 UV 和平均注册率非常突出,证明这是一类**“引流”+“拉新”**的渠道;而其他的流量质量方面的表现却比较差。

深入业务剖析

综合初步分析的结果,再结合输出各渠道详细数据:

  1. 聚类 1 的广告渠道各方面表现均比较一般,因此需要业务部门重点考虑其投放的实际价值。
  2. 聚类 2 的广告渠道短板是日均 UV 和平均注册率,无法为企业带来大量的流量以及新用户。这类广告的特质适合用户转化,尤其是有关订单转化的提升。
  3. 聚类 3 的广告渠道跟聚类 2 的特质非常类似,也适合做订单转化的提升,并且由于其实际效果更好,因此效果会更加明显。
  4. 聚类 4 的广告渠道更加符合广告本身“广而告之”的基础诉求,因此适合在大规模的广告宣传和引流时使用,尤其对于新用户的注册转化上的效果非常明显,适合“拉新”使用。

六、 业务应用与部署策略

对于以上四类广告媒体,需要针对其不同的特征做针对性的运营应用:

  • 针对聚类 1:在资金不足或优化广告结构时,重点考虑其取舍问题。
  • 针对聚类 2 和聚类 3:优化应用的方向有两个:
    • 增加注册转化效果的优化效应:重点从人群匹配、注册引导、注册激励等方面加强运营。打折、直降等优惠宣传点可以重点突出,广告素材本身以较大中等广告为主(例如 900*120)。
    • 发挥整体广告效果的支撑价值:考虑到其流量规模的局限性,这类渠道更加适合在广告结构中作为一类具有流量质量支撑价值的角色,用来提升全局广告的订单质量效果。尤其是聚类 3,应该优先考虑投放组合。
  • 针对聚类 4:可以作为在每次大型促销活动时做引流的骨干。对于这类媒体的单位流量成本需要重点关注,实际投放过程中可以满减为促销点、通过较大尺寸(如 308*338)的广告类型做引导流量点击。

提示:广告流量数量和质量是广告效果的“两条腿”。虽然大多数情况下广告更侧重于流量数量,但如果能够兼顾质量则可以锦上添花。对于广告结构中两类不同倾向的媒体,具体如何组织和结构调整,更多要看营销中心自身的核心目标定位。对于效果不好的媒体(如聚类 1),也不一定就要立刻切掉,这里面可能涉及到多方的利益关联问题。

聚类作为数据探索的初步阶段,还可以为后期的深入分析提供方向:

  • 通过分类方法基于不同的类别划分,找到各自类别内的显著特征,这些特征会成为进一步落地动作确认的基础。
  • 结合特定的广告运营目标并将其作为目标变量,通过分类方法找到各个广告渠道对于目标转化与否的重要性影响程度(如平均注册率、订单转化率等)。
  • 结合不同类别的订单详细信息,提取购买的商品数据,分析平均订单金额、购买频率、商品购买数量,以实现对不同类别渠道购买力、消费潜力的评估。
  • 将广告成本与广告效果评估指标结合起来,通过回归方法预测不同成本下能够达成的广告效果,作为广告媒体策划的基础。

七、 案例避坑指南与引申思考

关键注意点

  • 异常值的保留:异常值对于聚类效果的影响是显著的,但是广告类媒体的一个典型特征就是流量规模差异非常大。因此对于这类的异常值不能轻易去除,它属于业务上的“正常现象”。
  • 描述性统计的分离:在做描述性统计时,一般情况下会将数值型和字符串型的字段分开做统计。如果放在一起,会导致很多字段为空,实际效果并不直观。
  • 标准化方法的选择:在做聚类之前的数据标准化方法选择上,由于数据中涉及到异常值的存在,因此使用的是可以兼顾异常值的处理方法(Min-Max)。
  • 中文字体显示matplolib 中如果要显示中文,需要设置对应的中文字体名称(如 SimHei),否则无法正常显示。

引申思考与优化方向

本案例中通过平均轮廓系数的方法得到的最佳 K 值,不一定在业务上具有明显的解读和应用价值。如果最佳 K 值的解读无效怎么办?有两种思路:

  • 扩大 K 值范围:例如将 K 的范围调整为 [2, 12],然后再次运算看更大范围内得到的 K 值是否更加有效,并且能符合业务解读和应用需求。
  • 选择“次优” K 值:得到平均轮廓系数“次要好”(而不是最好)的 K 值,再对其结果做分析。

对于不同类别的典型特征的对比,除了使用雷达图直观地显示外,还可以使用多个柱形图的形式,将每个类别对应特征的值做柱形图统计,这也是一个非常直观的对比方法。具体参考下图:

KMeans聚类指标评估
KMeans聚类指标评估

分享
最后修订: 2018-01-09