Python之层次聚类/系统聚类(Hierarchical Clustering)、变量聚类

1.层次聚类

简介

别称:系统聚类

英文名:Hierarchical Clustering

基本原理:假设数据类别之间存在层次结构,通过对数据集在不同层次的划分,构造出树状结构的聚类结果

实现方法:聚合方法、分裂方法

实现方法方向步骤描述经典算法
聚合方法自底向上
  • 首先,每个样本自成一簇;
  • 然后,开始迭代,每一次迭代把距离相近的两个簇合并为1个簇;
  • 直至,簇的数量达到预设值;
  • 若无预设值,则最后把所有样本合并为1个簇

AGNES

(Agglomerative Nesting)

分裂方法自顶向下
  • 起初,只有1个簇,即所有样本构成的簇;
  • 使用聚合方法的逆过程;
  • 最终,每个样本自成一簇。
未知

2. AGNES算法

AGNES算法,是一种聚合层次聚类算法

2.1 算法步骤

为了便于理解,下面举一个例子:

 

 图11.1 

2.2 Python实现

方法一:使用 sklearn.cluster中的AgglomerativeClustering

缺点:只会画聚类散点图,不知道怎么画聚类树状图

需要导入的库:sklearn,matplotlib

from sklearn.cluster import AgglomerativeClustering

import matplotlib.pyplot as plt

关键代码介绍
函数AgglomerativeClustering(n_clusters,linkage)

参数解读:

  • n_clusters:聚类数
  • linkage簇间距离计算方式
    层次聚类法的关键就是选择合适的linkage!!!
        single:最小距离
        complete:最大距离
        average:平均距离
        ward:离差平方和
    
  • return返回值:返回一个聚类模型
 model=AgglomerativeClustering(n_clusters,linkage).fit(x)

代码解读:

在AgglomerativeClustering(n_clusters,linkage)后面加上了.fit(x),
表示将聚类模型应用于数据集x

  • x:数据集
  • 得到的是拟合于数据集x的聚类模型
plt.scatter(x[:,0],x[:,1],c=model.labels_)

代码解读:

画散点图

  • x[:,0],x[:,1]:分别是横、纵坐标
  • model.labels_:聚类后,用于表示各个样本属于哪个类别的标签
  • c=model.labels_:用聚类后的标签来区分不同颜色
例一:同心圆数据集、半月数据集
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = ['sans-serif']
plt.rcParams['font.sans-serif'] = ['SimHei']  # 散点图标签可以显示中文
plt.rcParams['axes.unicode_minus'] =False
from sklearn.cluster import AgglomerativeClustering
from sklearn.datasets import make_moons,make_circles # 导入半月数据集、同心圆数据集
# 构造数据集
circle_x,circle_y=make_circles(n_samples=500,factor=0.5,noise=0.05)
print("circle_x:\n",circle_x)
moon_x,moon_y=make_moons(n_samples=500,noise=0.05,random_state=0)
print("moon_x:\n",moon_x)

circle_model=AgglomerativeClustering(n_clusters=2,linkage="single").fit(circle_x)
moon_model=AgglomerativeClustering(n_clusters=2,linkage="single").fit(moon_x)
'''AgglomerativeClustering
参数解读:
linkage簇间距离计算方式,共有3种选择:
    single:最小距离
    complete:最大距离
    average:平均距离'''

# 绘图
plt.figure(figsize=(12,5))   # 设置画布大小
plt.subplot(121)
plt.title("AGENS on circle dataset",y=-0.15)
plt.scatter(circle_x[:,0],circle_x[:,1],
            c=circle_model.labels_)  # circle_model.labels_得到各类的标签
plt.subplot(122)
plt.title("AGENS on moon dataset",y=-0.15)
plt.scatter(moon_x[:,0],moon_x[:,1],c=moon_model.labels_)
plt.show()

结果如下:

 

例二:采用多种linkage聚类

例一只采用了linkage="single"的簇间距离计算方式,下面采用多种linkage分别对多个数据集进行聚类

import matplotlib.pyplot as plt
plt.rcParams['font.family'] = ['sans-serif']
plt.rcParams['font.sans-serif'] = ['SimHei']  # 散点图标签可以显示中文
plt.rcParams['axes.unicode_minus'] =False
from sklearn.cluster import AgglomerativeClustering
from sklearn.datasets import make_moons,make_circles,make_blobs,make_s_curve

# 构造数据集
circle_x,circle_y=make_circles(n_samples=500,factor=0.5,noise=0.05)
print("circle_x:\n",circle_x)
moon_x,moon_y=make_moons(n_samples=500,noise=0.05,random_state=0)
print("moon_x:\n",moon_x)
blobs_x,blobs_y=make_blobs(n_samples=200,random_state=0)
print("blobs_x:\n",blobs_x)
curve_x,curve_y=make_s_curve(n_samples=100,noise=0.05,random_state=5)
print("curve_x:\n",curve_x)

'''下面以不同的linkage方式,对不同数据集 进行聚类'''
plt.figure(figsize=(12,12))  # 设置画布大小
i=1
for x in [circle_x,moon_x,blobs_x,curve_x]:
    for link in ["single","complete","average","ward"]:
        # 得到聚类数据集
        model=AgglomerativeClustering(n_clusters=2,linkage=link).fit(x)
        plt.subplot(4,4,i)
        plt.scatter(x[:, 0], x[:, 1], c=model.labels_)
        i+=1
plt.show()

结果如下:

不难发现,对于不同的数据集,选择不同的linkage会有不同的聚类效果。

因此,层次聚类法的关键就是选择合适的linkage!!!

方法二:使用scipy.cluster.hierarchy 中的linkage、fcluster、dendrogram

优点:既可以画聚类树状图、又可以画聚类散点图

需要导入的库:scipymatplotlib

import scipy.cluster.hierarchy as sch

import matplotlib.pyplot as plt

关键代码介绍
Z=sch.linkage(x,method,metric)

作用:根据method和metric,利用数据集x,生成聚类树的数据矩阵Z

参数解读:

  • x:数据集
  • method:簇间距离计算方式(与方法一中的linkage是指同一个东西)
  • 层次聚类法的关键就是选择合适的簇间距离计算方式,即:method!!!
    method取值及其含义
    字符串含义
    "single"
    最短距离(默认值)
    "complete"
    最大距离
    "average"
    (不加权)平均距离
    "ward"
    离差平方和方法
    "centroid"
    重心距离
    "weighted"
    加权分组平均
    
  • metric:距离度量
    metric取值及其含义
    字符串含义
    "euclidean"
    欧几里德距离
    "seuclidean"
    标准欧几里德距离
    "minkowski"
    闵氏距离
    "cityblock"
    绝对值距离
    "mahalanobis"
    马氏距离
    "cosine"
    两个向量夹角的余弦
    "correlation"
    样本相关系数
    "hamming"
    汉明距离
    "jaccard"
    Jaccard系数
    "chebyshev"
    切比雪夫距离
  • return 返回值:数据矩阵Z

T=sch.fcluster(Z,criterion,t)

作用:根据criterion和t,从Z中获取聚类结果T

参数解读:

  • ​​​Z : Z=sch.linkage(x,method,metric)得到的数据矩阵
  • criterion:聚类准则(要结合t一起用)
  • t
  • return 返回值:聚类结果
    不同criterion下t的含义
    criterion的取值t的含义
    "inconsistent"

    t值应该在0-1之间波动,

    t越接近1代表两个数据之间的相关性越大;

    t越趋于0表明两个数据的相关性越小。

    这种相关性可以用来比较两个向量之间的相关性,可用于高维空间的聚类

    "distance"
    簇的最大距离为t
    "maxclust"
    最大分类簇数为t
    "monocrit"
    t的选择不是固定的,而是根据一个函数monocrit[j]来确定。
    "maxclust_monocrit"
    在最大聚类数量为t的同时,将阈值t减小到最小的不一致性

    criterion的取值中,较常用的是:"distance","maxclust"

sch.dendrogram(Z)

作用:根据聚类树的数据矩阵Z,画出聚类树状图

然后直接plt.show()即可

参数解读:

  • ​​​Z : Z=sch.linkage(x,method,metric)得到的数据矩阵
plt.scatter(x[:,0],x[:,1],c=T)

作用:画出聚类后的散点图

参数解读:

  • x[:,0],x[:,1]:数据集的横、纵坐标
  • T:从T=sch.fcluster(Z,criterion,t)得到的聚类结果
  • c=T:用聚类后的标签来区分不同颜色

例子:同心圆数据集
import scipy.cluster.hierarchy as sch
import matplotlib.pyplot as plt
import numpy as np
from sklearn.datasets import make_circles  # 导入同心圆数据集 

# 构造数据集
circle_x,circle_y=make_circles(n_samples=500,factor=0.5,noise=0.05)
print("circle_x:\n",circle_x)

# 计算数据矩阵Z
Z=sch.linkage(circle_x,  # 数据
              method="single",
              metric="euclidean")
print("数据矩阵Z:\n",Z)
'''linkage
参数解读:
method 簇间距离计算方式:
"single"最短距离、"complete"最大距离、"average"(不加权)平均距离、"ward"离差平方和方法、"centroid"重心距离、"weighted"加权分组平均
metric 距离度量:
"euclidean"欧几里德距离、"seuclidean"标准欧几里德距离、"minkowski"闵氏距离、"cityblock"绝对值距离、"mahalanobis"马氏距离、
"cosine"两个向量夹角的余弦、"correlation"样本相关系数、"hamming"汉明距离、"jaccard"Jaccard系数、"chebyshev"切比雪夫距离
'''

# 得到分类结果
T=sch.fcluster(Z,criterion="maxclust",t=2)  # 根据给定的类数t,创建Z的聚类
print(T)
'''sch.fcluster
参数解读:
criterion聚类准则(要结合t一起用):
"inconsistent"、"distance"簇的距离不超过t、"maxclust"最大分类簇数为t、"monocrit"、"maxclust_monocrit"
其中"distance""maxclust"较为常用
'''

# 用数据矩阵Z画出聚类树状图
sch.dendrogram(Z)

plt.show()

# 画出聚类散点图
plt.scatter(circle_x[:,0],circle_x[:,1],c=T)
plt.show()

 聚类树状图如下:

       由此可见,当样本点很多时,聚类树状图非常密集,因此样本点很多时,不太适合画聚类树状图,画聚类散点图更合适、更美观。

 聚类散点图如下:

3.变量聚类

简介

  • 基本原理:根据变量的相似关系来聚类
  • 步骤:
    1.先计算变量之间的相似关系
    2.计算两变量之间的距离
    3.用层次聚类的方法对变量进行聚类
  • 与其他聚类方法的区别:其他聚类方法聚类的对象都是“样本点”,而变量聚类的对象是“变量”
  • 本质:用层次聚类的方法,对变量进行聚类

3.1 算法描述

3.2 Python实现

需要导入的库:scipy,matplotlib

import scipy.cluster.hierarchy as sch

import matplotlib.pyplot as plt

步骤:

  1. 先求出相似关系r
  2. 再求变量间的距离d:d=1-abs(r) 
  3. 用层次聚类的方法进行聚类

例子:

(注:数据文件data11_8.xlsx在本文开头)

import scipy.cluster.hierarchy as sch
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

data=pd.read_excel("data11_8.xlsx",header=None)
print("各因素之间的相关系数表:\n",data)

# 取出非nan的元素,即data中对角线下方的元素
b=np.triu(data.values.T,k=1)
print(b)
r=b[np.nonzero(b)]  # 得到全部相关系数
d=1-abs(r)  # 计算两类变量之间的距离

# 用系统聚类的方法对变量进行聚类
Z=sch.linkage(d,"complete")
sch.dendrogram(Z,labels=range(1,15))
plt.show()

结果如下:

参考文献

[1]司守奎,孙玺.Python数学建模算法与应用 

[2]左飞.Python机器学习中的数学修炼 

[3]python的scipy层次聚类参数详解https://blog.csdn.net/enigma_tong/article/details/79081449

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值