聚类算法

K-means

Posted by 新宇 on February 24, 2020

物以类聚,人以群分

一、简介

1. 什么是聚类算法?

  • 一种典型的无监督学习算法,主要用于将相似的样本自动归到一个类别中。
  • 在聚类算法中根据样本之间的相似性,将样本划分到不同的类别中,对于不同的相似度计算方法,会得到不同的聚类结果,常用的相似度计算 方法有欧式距离法

2. 分类

  • 粗聚类
  • 细聚类

二、聚类算法实现流程

  • 随机设置K个特征空间内的点作为初始的聚类中心
  • 对于其他每个点计算到K个中心的距离,未知的点选择最近的一个聚类中心点作为标记类别
  • 接着对着标记的聚类中心之后,重新计算出每个聚类的新中心点(平均值)
  • 如果计算得出的新中心点与原中心点一样(质心不再移动),那么结束,否则重新进行第二步过程

  • 注意: 由于每次都要计算所有的样本与每一个质心之间的相似度,故在大规模的数据集上,K-Means算法的收敛速度比较慢。

三、聚类算法API实现

  • sklearn.cluster.KMeans(n_clusters=8)
    • 参数:
      • n_clusters:开始的聚类中心数量
      • 整型,缺省值=8,生成的聚类数,即产生的质心(centroids)数。
    • 方法:
      • estimator.fit(x)
      • estimator.predict(x)
      • estimator.fit_predict(x)
        • 计算聚类中心并预测每个样本属于哪个类别,相当于先调用fit(x),然后再调用predict(x)

四、k-means算法小结

  • 优点:
    • 1.原理简单(靠近中心点),实现容易
    • 2.聚类效果中上(依赖K的选择)
    • 3.空间复杂度o(N),时间复杂度o(IKN)
  • 缺点:
    • 1.对离群点,噪声敏感 (中心点易偏移)
    • 2.很难发现大小差别很大的簇及进行增量计算
    • 3.结果不一定是全局最优,只能保证局部最优(与K的个数及初值选取有关)

五、模型评估

1. 误差平方和(SSE\The sum of squares due to error)

误差平方和的值越小越好

2. “肘”方法 (Elbow method) — K值确定

下降率突然变缓时即认为是最佳的k值

3. 轮廓系数法(Silhouette Coefficient)

取值为[-1, 1],其值越大越好

4. CH系数(Calinski-Harabasz Index)

分数s高则聚类效果越好

CH需要达到的目的:用尽量少的类别聚类尽量多的样本,同时获得较好的聚类效果。

  • 类别内部数据的协方差越小越好,类别之间的协方差越大越好(换句话说:类别内部数据的距离平方和越小越好,类别之间的距离平方和越大 越好),这样的Calinski-Harabasz分数s会高,分数s高则聚类效果越好

五、算法优化(待完善)

1. Canopy算法配合初始聚类

使用同心圆去选择最优的聚类中心;

2. K-means++

让前后两个聚类中心点的距离最大; 参考链接

3. 二分k-means

每次分裂都是分成2个类簇,将SSE较大的类簇进一步进行划分;

4. k-medoids(k-中心聚类算法)

与k-means非常相似,区别在于k-mediods每次在选取中心点时,使用的是自身样本集中的数据点,而不是直接计算出来的可能不存在的数据点,受异常值的影响较小;

5. Kernel k-means

6. ISODATA

7. Mini Batch K-Means

8. 总结

六、案例分析

  • 探究用户对物品类别的喜好细分
  • 来自kaggle平台

import pandas as pd
from sklearn.decomposition import PCA
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score

# 1.获取数据
order_product = pd.read_csv("./data/instacart/order_products__prior.csv") 
products = pd.read_csv("./data/instacart/products.csv")
orders = pd.read_csv("./data/instacart/orders.csv")
aisles = pd.read_csv("./data/instacart/aisles.csv")
# 2.1 合并表格

table1 = pd.merge(order_product, products, on=["product_id", "product_id"]) 
table2 = pd.merge(table1, orders, on=["order_id", "order_id"])
table = pd.merge(table2, aisles, on=["aisle_id", "aisle_id"])
# 2.2 交叉表合并(查看两列之间的关系)

table = pd.crosstab(table["user_id"], table["aisle"])
# 2.3 数据截取(数据量太大,只学习截取数据)

table = table[:1000]

# 3. 特征降维

transfer = PCA(n_components=0.9) 
data = transfer.fit_transform(table)

# 4. 机器学习(k-means)

estimator = KMeans(n_clusters=8, random_state=22) 
estimator.fit_predict(data)

# 5. 模型评估(使用轮廓系数法)

silhouette_score(data, y_predict)