前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >分群思维(四)基于KMeans聚类的广告效果分析

分群思维(四)基于KMeans聚类的广告效果分析

作者头像
HsuHeinrich
发布2023-03-29 13:53:18
6340
发布2023-03-29 13:53:18
举报
文章被收录于专栏:HsuHeinrich

分群思维(四)基于KMeans聚类的广告效果分析

小P:小H,我手上有各个产品的多维数据,像uv啊、注册率啊等等,这么多数据方便分类吗 小H:方便啊,做个聚类就好了 小P:那可以分成多少类啊,我也不确定需要分成多少类 小H:只要指定大致的范围就可以计算出最佳的簇数,一般不建议过多或过少,2至4是最佳的

  • 导库
代码语言:javascript
复制
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from sklearn.metrics import silhouette_score  # 导入轮廓系数指标
from sklearn.cluster import KMeans
from sklearn.preprocessing import MinMaxScaler, OneHotEncoder
  • 数据预处理

以下数据如果有需要的同学可关注公众号HsuHeinrich,回复【分群思维04】自动获取~

代码语言:javascript
复制
# 读取数据
raw_data = pd.read_table('ad_performance.txt', delimiter='\t')
raw_data.head()

image-20230206151545251

代码语言:javascript
复制
# 数据描述
raw_data.describe().round(2).T

image-20230206151610337

代码语言:javascript
复制
# 相关性分析
raw_data.corr().round(2).T 

image-20230206151648487

代码语言:javascript
复制
# 高相关性对基于距离的算法有显著影响,因此去掉一个
raw_data2 = raw_data.drop(['平均停留时间'], axis=1) 
代码语言:javascript
复制
# 字符串分类onehotencode处理
cols = ['素材类型','广告类型','合作方式','广告尺寸','广告卖点']
model_ohe = OneHotEncoder(sparse=False)
ohe_matrix = model_ohe.fit_transform(raw_data2[cols])
print(ohe_matrix[:2])
代码语言:javascript
复制
[[0. 1. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 1. 1. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0.
  0. 0. 0.]
 [0. 1. 0. 0. 1. 0. 0. 0. 0. 1. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0.
  0. 0. 0.]]
代码语言:javascript
复制
# 数值型数据标准化
sacle_matrix = raw_data2.iloc[:, 1:7]
model_scaler = MinMaxScaler()
data_scaled = model_scaler.fit_transform(sacle_matrix)
print(data_scaled.round(2))
代码语言:javascript
复制
[[0.   0.18 0.02 0.01 0.12 0.66]
 [0.01 0.1  0.03 0.01 0.01 0.62]
 [0.   0.06 0.05 0.01 0.01 0.1 ]
 ...
 [0.01 0.01 0.   0.   0.   0.72]
 [0.05 0.   0.   0.   0.   0.31]
 [0.   0.   0.   0.53 0.   0.62]]
代码语言:javascript
复制
# 合并所有维度
X = np.hstack((data_scaled, ohe_matrix))
  • 模型训练
代码语言:javascript
复制
# 通过平均轮廓系数检验得到最佳KMeans聚类模型
score_list = list() 
silhouette_int = -1 
for n_clusters in range(2, 5):  # 初始2至4个类别
    model_kmeans = KMeans(n_clusters=n_clusters) 
    labels_tmp = model_kmeans.fit_predict(X) 
    silhouette_tmp = silhouette_score(X, labels_tmp)  # 计算轮廓系数
    if silhouette_tmp > silhouette_int: 
        best_k = n_clusters  # 保存最大轮廓系数下的k
        silhouette_int = silhouette_tmp 
        best_kmeans = model_kmeans 
        cluster_labels_k = labels_tmp 
    score_list.append([n_clusters, silhouette_tmp])

print(np.array(score_list))  # 打印所有K的轮廓系数
print('Best K is:{0} with average silhouette of {1}'.format(best_k, silhouette_int))
代码语言:javascript
复制
[[2.         0.38655493]
 [3.         0.45864451]
 [4.         0.50209812]]
Best K is:4 with average silhouette of 0.5020981194788053
  • 模型结果
代码语言:javascript
复制
# 1. 将原始数据与聚类标签整合
cluster_labels = pd.DataFrame(cluster_labels_k, columns=['clusters'])  # 获取聚类标签
merge_data = pd.concat((raw_data2, cluster_labels), axis=1)

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

# 3. 计算各个聚类类别内部最显著特征值
cluster_features = []  # 空列表,用于存储最终合并后的所有特征信息
for line in range(best_k):  # 读取每个类索引
    label_data = merge_data[merge_data['clusters'] == line]  # 获得特定类的数据

    part1_data = label_data.iloc[:, 1:7]  # 获得数值型数据特征
    part1_desc = part1_data.describe().round(3)  # 得到数值型特征的描述性统计信息
    merge_data1 = part1_desc.iloc[1, :]  # 得到数值型特征的均值

    part2_data = label_data.iloc[:, 7:-1]  # 获得字符串型数据特征
    part2_desc = part2_data.describe(include='all')  # 获得字符串型数据特征的描述性统计信息
    merge_data2 = part2_desc.iloc[2, :]  # 获得字符串型数据特征的最频繁值

    merge_line = pd.concat((merge_data1, merge_data2), axis=0)  # 将数值型和字符串型典型特征沿行合并
    cluster_features.append(merge_line)  # 将每个类别下的数据特征追加到列表
# 4. 输出完整的类别特征信息
cluster_pd = pd.DataFrame(cluster_features).T  # 将列表转化为矩阵
print('{:*^60}'.format('Detailed features for all clusters:'))
all_cluster_set = pd.concat((clustering_count, clustering_ratio, cluster_pd),axis=0)  # 将每个聚类类别的所有信息合并
print(all_cluster_set)
代码语言:javascript
复制
************Detailed features for all clusters:*************
                  0        1        2        3
counts          349      313      154       73
percentage     0.39     0.35     0.17     0.08
日均UV        300.205  572.521  613.836  1401.53
平均注册率         0.001    0.001    0.003    0.001
平均搜索量         0.016    0.051     0.02    0.033
访问深度           2.27    2.145     2.19    1.727
订单转化率         0.002    0.004    0.003    0.002
投放总时间         15.35   17.125   15.682   15.603
素材类型            jpg      swf      jpg      swf
广告类型             横幅      不确定   banner     tips
合作方式            cpc      roi      cpc      cpm
广告尺寸         600*90   600*90  308*388  450*300
广告卖点             直降       打折       满减       打折
  • 通过雷达图观察分类结果
代码语言:javascript
复制
# 1. 各类别数据预处理
num_sets = cluster_pd.iloc[:6, :].T.astype(np.float64)  # 获取要展示的数据
num_sets_max_min = model_scaler.fit_transform(num_sets)  # 获得标准化后的数据
# 2. 画布基本设置
fig = plt.figure(figsize=(6,6))  # 建立画布
ax = fig.add_subplot(111, polar=True)  # 增加子网格,注意polar参数
labels = np.array(merge_data1.index)  # 设置要展示的数据标签
cor_list = ['b', 'g', 'r', 'c', 'm', 'y', 'k', 'w']  # 定义不同类别的颜色
angles = np.linspace(0, 2 * np.pi, len(labels), endpoint=False)  # 计算各个区间的角度
angles = np.concatenate((angles, [angles[0]]))  # 建立相同首尾字段以便于闭合
labels = np.concatenate((labels,[labels[0]]))   # 新版本增加,对labels进行封闭
# 3. 画雷达图
for i in range(len(num_sets)):  # 循环每个类别
    data_tmp = num_sets_max_min[i, :]  # 获得对应类数据
    data = np.concatenate((data_tmp, [data_tmp[0]]))  # 建立相同首尾字段以便于闭合
    ax.plot(angles, data, 'o-', c=cor_list[i], label=i)  # 画线
# 4. 设置图像显示格式
ax.set_thetagrids(angles * 180 / np.pi, labels, fontproperties="SimHei")  # 设置极坐标轴
ax.set_title("各聚类类别显著特征对比", fontproperties="SimHei")  # 设置标题放置
ax.set_rlim(-0.2, 1.2)  # 设置坐标轴尺度范围
plt.legend(loc=0)  # 设置图例位置
plt.show()

output_17_0

从雷达图我们发现四个各类别在6个数字特征上具有较大差异,0类更偏向访问深度,3类更偏向日均uv,2和3类在多个指标表现都较好,但也存在差异。

总结

聚类能很好的解决多维数据的分类问题,雷达图能很好的观察差异。当然聚类的方法有很多,例如K均值的变体k-means++、bi-kmeans、kernel k-means,密度聚类的DBSCAN,层次聚类的Agglomerative等等

共勉~

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-03-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 HsuHeinrich 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 分群思维(四)基于KMeans聚类的广告效果分析
    • 总结
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档