【火炉炼AI】机器学习027-项目案例:用聚类算法建立客户细分模型

【火炉炼AI】机器学习027-项目案例:用聚类算法建立客户细分模型

(本文所使用的Python库和版本号: Python 3.6, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 )

客户细分是市场营销成功的前提,我们从市场中获取的数据一般都没有标记,要想对这些市场数据进行客户细分,将客户划分簇群,这也是一种典型的无监督学习问题。

本项目拟用各种不同的聚类算法来建立客户细分模型,并比较这些聚类算法在这一问题上的优虐。


1. 准备数据集

本项目案例所使用到的原始数据集来源于: UCI大学数据集,这个数据集来源于一个批发商,一共包含有440个样本数据,每个样本数据包含有8列,但是其中的6列作为features,此处由于是无监督学习,不需要标记,故而只需要其中的六列数据,这些数据的说明如下表所示。

image

对于这6个features,数据集已经告诉我们这6列的min,max mean等信息,我把它们整理成一个表格,如下所示:

image

数据集的加载可以采用pd.read_csv函数来完成,代码可以参考我的github,下面我们随便选择两个feature,将其绘制到二维平面图上,看看这些数据点的分布情况,比如下图:

(X=fresh y=milk)的数据分布图
(X=grocery, y=delicassen)的数据分布图


2. 构建均值漂移聚类模型

本项目用均值漂移算法来构建模型,模型的构建和训练过程和我以前的文章【火炉炼AI】机器学习022-使用均值漂移聚类算法构建模型一样,如下代码,只不过该代码还打印出聚类后簇群的数量,并把每一种簇群的质心点位置打印出来。

# 构建均值漂移聚类模型
from sklearn.cluster import MeanShift, estimate_bandwidth
bandwidth=estimate_bandwidth(dataset,quantile=0.8,
                             n_samples=len(dataset))
meanshift=MeanShift(bandwidth=bandwidth,bin_seeding=True)
meanshift.fit(dataset) # 使用评估的带宽构建均值漂移模型,并进行训练
labels=meanshift.labels_
cluster_num=len(np.unique(labels))
centroids=meanshift.cluster_centers_
# 下面打印出簇群种类,和质心位置信息
print('Number of Clusters: {}'.format(cluster_num))
print('\t'.join([col_name[:5] for col_name in col_names]))
for centroid in centroids:
    print('\t'.join(str(int(x)) for x in centroid))

-------------------------------------输---------出--------------------------------

Number of Clusters: 8
Fresh Milk Groce Froze Deter Delic
9632 4671 6593 2570 2296 1248
40204 46314 57584 5518 25436 4241
16117 46197 92780 1026 40827 2944
22925 73498 32114 987 20070 903
112151 29627 18148 16745 4948 8550
36847 43950 20170 36534 239 47943
32717 16784 13626 60869 1272 5609
8565 4980 67298 131 38102 1215

--------------------------------------------完-------------------------------------

由此可见,均值漂移算法自动将本项目的数据集划分为8个不同类别,那么怎么查看聚类算法的效果图了?我先自定义了一个显示函数,用于展示各种不同聚类算法在不同数据集上的聚类效果,这个函数有一定的通用性,不仅可以可以用于均值漂移算法,还可以用于其他的各种聚类算法。如下为代码和运行结果。

def visual_cluster_effect(cluster,dataset,title,col_id):
    assert isinstance(col_id,list) and len(col_id)==2,'col_id must be list type and length must be 2'
    
    labels=cluster.labels_ # 每一个样本对应的簇群号码
#     print(labels.shape) # (440,) 440个样本
    markers=['.',',','o','v','^','<','>','1','2','3','4','8'
                 ,'s','p','*','h','H','+','x','D','d','|']
    colors=['tab:blue', 'tab:orange', 'tab:green', 'tab:red', 'tab:purple', 
            'tab:brown', 'tab:pink', 'tab:gray', 'tab:olive', 'tab:cyan']
    
    # 将数据集绘制到图表中
    plt.figure()
    for class_id in set(labels):
        one_class=dataset[class_id==labels]
        print('label: {}, smaple_num: {}'.format(class_id,len(one_class)))
        plt.scatter(one_class[:,0],one_class[:,1],marker=markers[class_id%len(markers)],
                    c=colors[class_id%len(colors)],label='class_'+str(class_id))
    plt.legend()
        
    # 将中心点绘制到图中
    centroids=meanshift.cluster_centers_
#     print(centroids.shape)# eg (8, 6) 8个簇群,6个features
    plt.scatter(centroids[:,col_id[0]],centroids[:,col_id[1]],marker='o',
                s=100,linewidths=2,color='k',zorder=5,facecolors='b')
    plt.title(title) 
    plt.xlabel('feature_0')
    plt.ylabel('feature_1')
    plt.show()

使用这个函数,我们可以看到本聚类算法在数据集上的表现,如下代码中,我们主要查看Fresh vs milk这一类产品的聚类效果。

visual_cluster_effect(meanshift,dataset,'MeanShift-X=fresh,y=milk',[0,1]) # X=fresh, y=milk 

-------------------------------------输---------出--------------------------------

label: 0, smaple_num: 428
label: 1, smaple_num: 3
label: 2, smaple_num: 1
label: 3, smaple_num: 1
label: 4, smaple_num: 3
label: 5, smaple_num: 1
label: 6, smaple_num: 1
label: 7, smaple_num: 2

--------------------------------------------完-------------------------------------

均值漂移算法在数据集(X=fresh,y=milk)的表现
visual_cluster_effect(meanshift,dataset,'MeanShift-X=grocery,y=delica',[2,5]) # X=grocery, y=delicassen
均值漂移算法在数据集(X=grocery,y=delica)的表现

从上面的图中我们很难看出模型到底是好还是坏,那我们就用指标来判断吧,前面我们学习过轮廓系数,可以用来评估模型的优虐,如下是评价代码。

# 使用轮廓系数评估模型的优虐
from sklearn.metrics import silhouette_score
si_score=silhouette_score(dataset,meanshift.labels_,
                          metric='euclidean',sample_size=len(dataset))
print('si_score: {:.4f}'.format(si_score))

-------------------------------------输---------出--------------------------------

si_score: 0.6548

--------------------------------------------完-------------------------------------

########################小**********结###############################

1,本文的数据集基本上都是已经处理过的,我们只需要加载后即可使用。

2,构建均值漂移算法的模型和训练该模型非常简单,但是里面额quantile参数可能需要进行优化才能得到最佳值。

3,为了查看本聚类算法在数据集上的表现优虐,我们先通过数据可视化,将聚类之后的簇群以及簇群质心绘制到图标中,这是一个多features数据集,故而数据的可视化只能一次取其中的两列来查看。

4,另外,我们还用轮廓系数来评估模型的好坏,此处模型的轮廓系数为0.6548,貌似不是太差,但也不是太好,看来还有优化空间,或者,我们可以采用其他算法来构建模型,比如前面我们学习到的K-means,DBSCAN,凝聚层次聚类等,看看其轮廓系数。

#################################################################


注:本部分代码已经全部上传到(我的github)上,欢迎下载。

参考资料:

1, Python机器学习经典实例,Prateek Joshi著,陶俊杰,陈小莉译

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,084评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,623评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,450评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,322评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,370评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,274评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,126评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,980评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,414评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,599评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,773评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,470评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,080评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,713评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,852评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,865评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,689评论 2 354

推荐阅读更多精彩内容