基于Python的k均值聚类不同规格的商品名
前言
聚类的目标是使得同一簇内的点之间的距离较短,而不同簇中点之间的距离较大。以此来区分不同的群体。
本篇讲述使用k均值算法对超市购物记录集中的商品名称进行聚类,实现同一类商品,不同规格汇聚成一个大类的要求。
原理分析及流程
聚类介绍
聚类的目标是使得同一簇内的点之间的距离较短,而不同簇中点之间的距离较大。以此来区分不同的群体。
两种主要的聚类方法是:层次法和点分配法。
1.层次法
将每个点都看成簇,簇与簇之间按照接近度(closeness)来组合,当达到预先给定的簇数目,或者簇的紧密度达到预定值时停止聚簇。
2.点分配法
先设置初始化簇心,然后按照某个顺序依次将每个点分配到最适合的簇中。可以进行簇合并或分裂,或者当点为离群点时可以不将该点分配到任何簇中。
距离测度
欧式空间下的点集采用距离测度来进行聚类,常见的距离测度有
假定有一些点组成的集合,我们称这个集合为空间。该空间下的距离测度是一个函数d(x,y),以空间中的两个点作为参数,输出是一个实数值。该函数必须满足下列准则:
(1)d(x,y)≥0(距离非负);
(2)当且仅当x=y时,d(x,y)=0(只有点到自身的距离为0,其他距离都大于0);
(3)d(x,y)=d(y,x)(距离具有对称性);
(4)d(x,y)≤d(x,z)+d(z,y)(三角不等式。
三角不等式是上述条件中最复杂的条件。它的直观意义是:如果从x点进行到y点,那么经过某个特定的第三点z不会有任何好处。三角不等式准则使得所有的距离测度表现得如同描述的是从一个点到另一个点的最短路径的长度。
常见的距离测度有:欧氏距离、jaccard距离、余弦距离、编辑距离、海明距离、马氏距离等。
k-均值算法
k-均值算法的步骤是先选择明显不在相同簇里的k个点为簇心,再对剩余的点,计算它与每个簇心的距离,加入距离最近的那个簇,并根据新数据调整簇心,如此反复,直到簇心基本收敛。
若要更加详细了解请查看这一篇:KMeans详细介绍
k值选择
一个该解决的问题就是k值应该选择多少?即应该聚为几个簇较为合理。如果簇数选择太多的话,我们可能把原本应该是同一个簇的样本给拆分了,反之,我们可能把原本不该是同一个簇的两个样本聚集到了同一个簇中。
为了解决这个问题,通常我们会使用探索法,即在给定不同k值下,对比某些评估指标的变动情况,进而选择一个比较合理的k值。三种常用的评估方法是:簇内离差平方和拐点法、轮廓系数法以及间隔量统计法。
实现流程
所给数据集basket_row.csv的每一行是一次购物中的商品,目标是对超市购物记录集中的商品名称进行聚类,实现同一类商品,不同规格汇聚成一个大类。
首先我们按行读取数据并拆分成单独的商品名(去重)。此处我们的商品名为不可直接计算距离的字符串,所以我们采用编辑距离作为距离测度,具体做法是将每一个商品与所有计算编辑距离,形成一个向量,如果商品名称接近,形成的向量可想而知应该是比较接近的,然后我们对所有向量进行聚类,即是对商品进行聚类。具体步骤如下:
具体实现
导入所需要的包
# 导入所需要的包
import pandas as pd
import Levenshtein
from sklearn.cluster import KMeans
商品名去重后保存起来,查看其前5行如下:
In [4]: data_F.head()
Out[4]:
shopname
0 苦瓜(一级)
1 南瓜(一级)
2 蒙牛益生菌酸牛奶(原味)1.2kg
3 光明酸牛奶(红枣味)180g
4 鲜鸡蛋
定义一个与其他所有商品计算编辑距离的函数calculate_compile_distance,并对所有商品使用,求出向量矩阵,查看其前5行如下:
然后提取出向量矩阵,并设置合理的簇数进行聚类。
In [12]: # 提取向量矩阵
...: X = data_F.drop('shopname', axis = 1)
...:
...: # 设置合理的簇数进行聚类
...: kmeans = KMeans(n_clusters=1900)
...: kmeans.fit(X)
Out[12]:
KMeans(algorithm='auto', copy_x=True, init='k-means++', max_iter=300,
n_clusters=1900, n_init=10, n_jobs=None, precompute_distances='auto',
random_state=None, tol=0.0001, verbose=0)
聚类完成后,将商品名与其类别标签整合,按照类别标签为key进行分桶,分到所属的簇中,保存那些商品数量大于2的簇(即有不同的规格),查看其中部分数据如下:
['海天特级味极鲜酱油500ml', '海天特级一品鲜酱油500ml']
['上好佳芝士条40g', '上好佳鲜虾片40g']
['喜之郎果冻爽苹果味150克', '喜之郎果冻爽荔枝味150克', '喜之郎果冻爽菠萝味150克', '喜之郎果冻爽柠檬味150克', '喜之郎果冻爽香橙味150克']
['味聚特烧烤藕片80克', '味聚特山椒藕片80克']
['二级哈密瓜', '一级哈密瓜']
如上结果所示,我们将相同商品不同规格聚为了一类。
注:此处的聚类结果可能由于簇数的设置不合理而使得部分结果不合理,我们可以多次试探寻找更加合理的簇数
总结
聚类的目标是使得同一簇内的点之间的距离较短,而不同簇中点之间的距离较大。以此来区分不同的群体。
聚类在实际中有许多应用,如:划分不同的消费人群、商品热度等等,聚类的算法有许多,各自有不同的适用场景,聚类在实际中可以给我们提供多方面的参考。
附录
数据集:basket_row.csv 及完整代码已放置于:Github