一、聚类算法简介

1、概念

聚类算法:根据样本之间的相似性,将样本划分到不同的类别中;不同的相似度计算方法,会得到不

                  同的聚类结果,常用的相似度计算方法有欧式距离法。

                  聚类算法的目的是在没有先验知识的情况下,自动发现数据集中的内在结构和模式。

                  无监督学习算法。

使用不同的聚类准则,产生的聚类结果不同。

比如书店里的书,可以按照国家来划分,也可以按照专业来划分,也可以按照漫画书或者文学书去划分,不同的规则划分出去的书也不同。

2、应用场景

        (1)用户画像,广告推荐,Data Segmentation,搜索引擎的流量推荐,恶意流量识别

        (2)基于位置信息的商业推送 新闻聚类,筛选排序

        (3)图像分割,降维,识别;离群点检测,信用卡异常消费;发掘相同功能的基因片段

3、分类

        (1)根据聚类颗粒度分类:细聚类和粗聚类

        (2)根据实现方法分类

        a、K-means:按照质心分类,主要介绍K-means,通用、普遍

        b、层次聚类:对数据进行逐层划分,直到达到聚类的类别个数

        c、DBSCAN聚类是一种基于密度的聚类算法

        d、谱聚类是一种基于图论的聚类算法

二、聚类算法API

1、聚类算法API

        sklearn.cluster.KMeans(n_clusters=k)

        参数:n_clusters: 开始的聚类中心数量

                                       整形,k:生成的聚类数,即产生的质心(centroids)数。

        方法:estimator . fit(x)

                   estimator . predict(x)

                   estimator . fit_predict(x):计算聚类中心并预测每个样本属于哪个类别,相当于先

                                                                 调用fit(x),然后再调用predict(x)。

2、代码案例

        随机创建不同二维数据集作为训练集,并结合k-means算法将其聚类,尝试分别聚类不同数量的簇,并观察聚类效果

        1. 导包  sklearn.cluster.KMeans sklearn.datasets.make_blobs

        2. 创建数据集

        3. 实例化Kmeans模型并预测

        4. 展示聚类效果

        5. 评估聚类效果好坏

# 必须放在第一个位置上
import os
os.environ['OMP_NUM_THREADS']='4'
#导包
from sklearn.cluster import KMeans  #聚类API  采用指定 质心 分簇
import matplotlib.pyplot as plt
from sklearn.datasets import  make_blobs  
# 默认会按照高斯分布(正态分布)生成数据集 ,只需要 指定 均值 ,标准差
from sklearn.metrics import   calinski_harabasz_score  
# 评估指标   值越大 , 聚类效果越好

# 1、准备数据
x, y = make_blobs(n_samples = 1000, n_features = 2,\
centers = [[-1,1],[0,0],[1,1],[2,2]],\
cluster_std = [0.4,0.2,0.2,0.2],random_state = 666)

# 2、绘制上述的图形
# 参1: 横坐标    参2: 纵坐标
plt.scatter(x[:,0],x[:,1])
plt.show()

# 3、创建KMeans
# 参1: 聚类数量    参2: 随机种子
es = KMeans(n_clusters = 4, random_state=666)

# 4、模型训练和预测
y_pre = es.fit_predict(x)    # 把样本分簇
print(f"预测值:\n{y_pre}")

# 5、绘制预测结果
plt.scatter(x[:,0],x[:,1],c = y_pre)
plt.show()

#6、评估指标
print(f"评估指标:{calinski_harabasz_score(x,y_pre)}")    # 数值越大越好

三、KMeans实现流程

1 、事先确定常数K ,常数K意味着最终的聚类类别数

2、随机选择 K 个样本点作为初始聚类中心

3、计算每个样本到 K 个中心的距离,选择最近的聚类中心点作为标记类别

4、根据每个类别中的样本点,重新计算出新的聚类中心点(平均值),如果计算得出的新中心点与原中心点一样则停止聚类,否则重新进行第 3 步过程,直到聚类中心不再变化

四、模型评估方法

1、SSE聚类评估指标

误差平方和SSE (The sum of squares due to error)         SSE = \sum_{i=1}^{k}\sum_{p\in C_{i}}^{}\left | p-m_{i} \right |^{2}

Ci 表示簇,k 表示聚类中心的个数,p 表示某个簇内的样本,m 表示质心点

SSE 越小,表示数据点越接近它们的中心,聚类效果越好

"肘" 方法通过 SSE 确定 n_clusters 的值

1. 对于n个点的数据集,迭代计算 k from 1 to n,每次聚类完成后计算 SSE

2. SSE 是会逐渐变小的,因为每个点都是它所在的簇中心本身。

3. SSE 变化过程中会出现一个拐点,下降率突然变缓时即认为是最佳 n_clusters 值。

4.在决定什么时候停止训练时,肘形判据同样有效,数据通常有更多的噪音,在增加分类无法带来更多回报时,我们停止增加类别。

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

代码实现

import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '4'
# 导包
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.metrics import silhouette_score, calinski_harabasz_score


# 1、定义函数  演示:SSE + 肘部法
def dm01_see():
    # 0、定义SSE列表,目的:记录每个K值的SSE值
    sse_list = []
    # 1、获取数据
    # 参1: 样本数量   参2: 特征数量   参3: 4个簇的质点   参4: std标准差   参5: 随机种子
    x,y = make_blobs(
        n_samples=1000,
        n_features=2,
        centers=[[-1, 1], [0, 0], [1, 1], [2, 2]],
        cluster_std=[0.4, 0.2, 0.2, 0.2],
        random_state=22
    )

    # 2、for循环 训练   获取每个K值,对应的SSE值
    for k in range(1, 100):
        # 2.1 创建模型
        # 参1: 簇的数量   参2: 最大迭代次数   参3: 固定随机种子
        es = KMeans(n_clusters=k,max_iter = 100, random_state= 22)
        # 2.2 训练模型
        es.fit(x)
        # 2.3 获取每个簇的SSE值
        sse_value = es.inertia_
        # 2.4 将每个K值对应的SSE值,添加到sse_list
        sse_list.append(sse_value)

    # 3、绘制SSE曲线 -> 数据可视化
    # print(sse_list)
    # 3.1 创建画布
    plt.figure(figsize=(20,10))
    # 3.2 设置标题
    plt.title("sse value")
    # 3.3 设置x轴
    plt.xticks(range(0,100,3))
    # 参1: K值    参2: 该K值对应的SSE值
    # o 代表 圆点样式   r 代表 红色   - 代表 连接数据点的样式(实线)
    plt.plot(range(1,100),sse_list,'or-')
    plt.xlabel("K")
    plt.ylabel("sse")
    plt.grid()
    plt.show()

2、SC聚类评估指标

轮廓系数法考虑簇内的内聚程度(Cohesion),簇外的分离程度(Separation)。其计算过程如下

1、对计算每一个样本 i 到同簇内其他样本的平均距离 ai,该值越小,说明簇内的相似程度越大

2、计算每一个样本i到最近簇 j 内的所有样本的平均距离 bij,该值越大,说明该样本越不属于其他簇 j

3、根据下面公式计算该样本的轮廓系数:S=\frac{b-a}{max(a,b)}

4、计算所有样本的平均轮廓系数

5、轮廓系数的范围为:[-1, 1],SC值越大聚类效果越好

主要考量:簇内聚程度、簇间分离程度

代码实现

import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '4'
# 导包
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.metrics import silhouette_score, calinski_harabasz_score


def dm02_sc轮廓系数法():
    # 0、定义sc列表,目的:记录每个K值的SSE值
    sc_list = []
    # 1、获取数据
    # 参1: 样本数量   参2: 特征数量   参3: 4个簇的质点   参4: std标准差   参5: 随机种子
    x, y = make_blobs(
        n_samples=1000,
        n_features=2,
        centers=[[-1, 1], [0, 0], [1, 1], [2, 2]],
        cluster_std=[0.4, 0.2, 0.2, 0.2],
        random_state=22
    )
    # 3、遍历for循环,获取每个K值,计算对应SC值,并添加到sc_list列表汇总
    for k in range(2,100):      # 考虑簇外,至少2簇
        es = KMeans(n_clusters=k, max_iter=100, random_state=23)
        es.fit(x)
        y_pre = es.predict(x)
        sc_value = silhouette_score(x, y_pre)
        sc_list.append(sc_value)

    # 绘制sc曲线 -> 数据可视化
    plt.figure(figsize=(20,10))
    plt.title("sc value")
    plt.xticks(range(0,100,3))
    plt.xlabel("K")
    plt.ylabel("sc")
    plt.grid()
    plt.plot(range(2,100),sc_list)
    plt.show()

3、CH聚类评估指标

CH 系数考虑簇内的内聚程度、簇外的离散程度、质心的个数

分数s高则聚类效果越好

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

主要考量:簇内聚程度、簇间分离程度、质心个数

类别内部数据的距离平方和越小越好,类别之间的距离平方和越大越好。聚类的种类数越少越好

CH(k)=\frac{SSW}{SSB}\frac{m-k}{k-1}                m 表示样本数量        k 表示质心个数

SSW = \sum_{i=1}^{m}\left \| x_{i}-C_{pi} \right \|^{2}                SSB = \sum_{j=1}^{k}n_{j}\left \| C_{j}-\overline{X} \right \|^{2}

SSW 的含义:相当于SSE,簇内距离

C_{pi}表示质心 ,x_{i}表示某个样本 ,SSW 值是计算每个样本点到质心的距离,并累加起来 ,SSW 表示表示簇内的内聚程度,越小越好。

SSB 的含义:簇间距离

C_{j}表示质心,\overline{X}表示质心的均值,n_{j}表示样本的个数 SSB 表示簇与簇之间的分离程度,SSB 越大越好.

import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '4'
# 导包
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.metrics import silhouette_score, calinski_harabasz_score

def dm03_ch_簇内_簇外_质心点个数():
    # 0、定义ch列表,目的:记录每个K值的SSE值
    ch_list = []
    # 1、获取数据
    # 参1: 样本数量   参2: 特征数量   参3: 4个簇的质点   参4: std标准差   参5: 随机种子
    x, y = make_blobs(
        n_samples=1000,
        n_features=2,
        centers=[[-1, 1], [0, 0], [1, 1], [2, 2]],
        cluster_std=[0.4, 0.2, 0.2, 0.2],
        random_state=22
    )
    # 3、 for循环 k
    for k in range(2,100):
        es = KMeans(n_clusters=k,max_iter=100,random_state=23)
        es.fit(x)
        y_pre = es.predict(x)
        # 获取每一个簇的ch值
        ch_value = calinski_harabasz_score(x,y_pre)
        ch_list.append(ch_value)

    # 4、绘图 ch 曲线 -> 数据可视化
    plt.figure(figsize=(20,10))
    plt.title("ch value")
    plt.xticks(range(0,100,3))
    plt.xlabel("K")
    plt.ylabel("ch")
    plt.grid()
    plt.plot(range(2,100),ch_list,'or-')
    plt.show()

五、代码习题        

案例:顾客数据聚类分析('customers.csv')

已知:客户性别、年龄、年收入、消费指数

需求:对客户进行分析,找到业务突破口,寻找黄金客户

步骤解析:1、寻找最优K,确定进行评估需要分几类(肘方法、sh系数)

                  2、按照第1步得到的K进行聚类算法划分数据源,绘图

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐