【机器学习】聚类算法(三)

六、基于图的算法

6.1 谱聚类

bad20ffaa4987541bea192ec5a97fc33.png

9bea3812cd27f5deb657e0fd7cd5ae05.png

6.2 算法原理

9ced25798be739e82d616d5cdd6cbf47.png

RatioCut算法

d34aba80ed2040cd24209e99da13e180.png

NCut算法

69eac61b2c03ce2515b40e4a242d8eea.png

6.3 如何选择合适的K值

4a25b95969bd3c561b4ea7ea21371603.png

6.4 谱聚类的应用场景

53dfec12234d09eeec10c674102a3d37.png

9af727437e95d87084d7c2553adba885.png

示例代码1:对鸢尾花数据集进行聚类,并绘制结果

# 导入所需的库
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.cluster import KMeans
from sklearn.metrics.pairwise import rbf_kernel


# 加载鸢尾花数据集
iris = load_iris()
X = iris.data
y = iris.target


# 定义谱聚类的函数
def spectral_clustering(X, k, gamma):
  # 计算相似度矩阵
  S = rbf_kernel(X, gamma=gamma)
  # 计算度矩阵
  D = np.diag(np.sum(S, axis=1))
  # 计算拉普拉斯矩阵
  L = D - S
  # 计算特征值和特征向量
  eig_val, eig_vec = np.linalg.eig(L)
  # 选择最小的k个特征值对应的特征向量
  idx = np.argsort(eig_val)[:k]
  U = eig_vec[:, idx]
  # 对每一行进行归一化
  T = np.linalg.norm(U, axis=1, keepdims=True)
  U = U / T
  # 应用k-means算法
  kmeans = KMeans(n_clusters=k, random_state=0)
  kmeans.fit(U)
  # 返回簇标签
  return kmeans.labels_


# 调用谱聚类的函数,设置k=3,gamma=0.1
y_pred = spectral_clustering(X, k=3, gamma=0.1)


# 绘制原始数据和聚类结果的散点图
plt.figure(figsize=(12, 6))
plt.subplot(121)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap='rainbow')
plt.title('Original Data')
plt.xlabel('Sepal Length')
plt.ylabel('Sepal Width')
plt.subplot(122)
plt.scatter(X[:, 0], X[:, 1], c=y_pred, cmap='rainbow')
plt.title('Spectral Clustering')
plt.xlabel('Sepal Length')
plt.ylabel('Sepal Width')
plt.show()

9efb5e960de14a50a13f2ced5ccd4ebd.png

示例代码2:

这是一个用于评估聚类结果的函数,它可以计算互信息、准确度和纯度等指标。这些指标都是用来评估聚类结果的有效性的。

  • 互信息 (Mutual Information) 是衡量两个随机变量之间的依赖程度的一个度量,它反映了两个变量共享的信息量。在聚类中,互信息可以用来衡量聚类结果与真实标签之间的一致性,互信息越大,表示聚类结果越符合真实标签。

  • 准确度 (Accuracy) 是衡量聚类结果与真实标签之间的匹配程度的一个度量,它反映了聚类结果中正确分类的样本比例。在聚类中,准确度可以用来衡量聚类结果的正确性,准确度越高,表示聚类结果越正确。

  • 纯度 (Purity) 是衡量聚类结果中每个簇的纯净程度的一个度量,它反映了每个簇中占比最大的真实标签的比例。在聚类中,纯度可以用来衡量聚类结果的纯净性,纯度越高,表示聚类结果越纯净。

# 导入 math 模块,用于进行数学运算
import math
# 导入 numpy 模块,用于进行数组操作
import numpy as np


# 定义一个函数,名为 eva,接受两个参数,分别是 A 和 B,表示两种聚类结果的标签
def eva(A, B):
    # 计算样本点数,即 A 和 B 的长度,赋值给 total
    total = len(A)
    # 将 A 中的不同标签转换为一个集合,赋值给 A_ids
    A_ids = set(A)
    # 将 B 中的不同标签转换为一个集合,赋值给 B_ids
    B_ids = set(B)
    # 初始化互信息为 0,赋值给 MI
    MI = 0
    # 定义一个很小的正数,赋值给 eps,用于避免对 0 取对数的错误
    eps = 1.4e-45
    # 初始化准确度为 0,赋值给 acc
    acc = 0
    # 初始化纯度为 0,赋值给 purity
    purity = 0
    # 对于 A 中的每个标签,赋值给 idA
    for idA in A_ids:
        # 初始化最大纯度为 0.0,赋值给 max_purity
        max_purity = 0.0
        # 对于 B 中的每个标签,赋值给 idB
        for idB in B_ids:
            # 找出 A 中标签为 idA 的样本的索引,赋值给 idAOccur
            idAOccur = np.where(A == idA)                     # 返回下标
            # 找出 B 中标签为 idB 的样本的索引,赋值给 idBOccur
            idBOccur = np.where(B == idB)
            # 找出 A 和 B 中同时标签为 idA 和 idB 的样本的索引,赋值给 idABOccur
            idABOccur = np.intersect1d(idAOccur, idBOccur)
            # 计算 A 中标签为 idA 的样本的比例,赋值给 px
            px = 1.0*len(idAOccur[0])/total
            # 计算 B 中标签为 idB 的样本的比例,赋值给 py
            py = 1.0*len(idBOccur[0])/total
            # 计算 A 和 B 中同时标签为 idA 和 idB 的样本的比例,赋值给 pxy
            pxy = 1.0*len(idABOccur)/total
            # 根据公式计算互信息,累加到 MI 上
            MI = MI + pxy*math.log(pxy/(px*py)+eps, 2)       # 互信息计算


            # 如果 idA 和 idB 相等,说明 A 和 B 中的标签一致
            if idA == idB:
                # 将 pxy 累加到 acc 上,表示准确度
                acc = acc + pxy                              # 准确度计算


            # 如果 idABOccur 的长度大于 max_purity,说明这是一个较纯的簇
            if len(idABOccur) > max_purity:                  # 纯度计算
                # 更新 max_purity 的值
                max_purity = len(idABOccur)
                # 将 idABOccur 的比例累加到 purity 上,表示纯度
                purity = purity + 1.0*len(idABOccur)/total


    # 计算标准化互信息,即互信息除以 A 和 B 的熵的平均值
    # 初始化 A 的熵为 0,赋值给 Hx
    Hx = 0
    # 对于 A 中的每个标签,赋值给 idA
    for idA in A_ids:
        # 计算 A 中标签为 idA 的样本的个数,赋值给 idAOccurCount
        idAOccurCount = 1.0*len(np.where(A == idA)[0])
        # 根据公式计算 A 的熵,累加到 Hx 上
        Hx = Hx - (idAOccurCount/total)*math.log(idAOccurCount/total+eps, 2)
    # 初始化 B 的熵为 0,赋值给 Hy
    Hy = 0
    # 对于 B 中的每个标签,赋值给 idB
    for idB in B_ids:
        # 计算 B 中标签为 idB 的样本的个数,赋值给 idBOccurCount
        idBOccurCount = 1.0*len(np.where(B == idB)[0])
        # 根据公式计算 B 的熵,累加到 Hy 上
        Hy = Hy - (idBOccurCount/total)*math.log(idBOccurCount/total+eps, 2)
    # 计算标准化互信息,赋值给 NMI
    NMI = 2.0*MI/(Hx+Hy)
    # 返回 NMI,acc 和 purity 三个指标
    return NMI, acc, purity

这是一个用于实现谱聚类算法的源代码,它可以对不同形状的数据进行聚类分析

5501986dcf3c019115c013cecd6c5a5f.png

flame.txt 数据集

# 从 sklearn.cluster 模块导入 KMeans 函数,用于进行 K-Means 聚类
from sklearn.cluster import KMeans
# 导入 numpy 模块,用于进行数组操作
import numpy as np
# 导入 math 模块,用于进行数学运算
import math as m
# 导入 matplotlib.pyplot 模块,用于绘制图形
import matplotlib.pyplot as plt
# 导入 evaluate 模块,用于评估聚类结果
import evaluate as eval


# 定义几个数据集的文件名,用于读取数据
# flame.txt
# Jain_cluster=2.txt
# Aggregation_cluster=7.txt
# Spiral_cluster=3.txt
# Pathbased_cluster=3.txt


# 定义数据集的路径,这里使用 flame.txt 数据集
d
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值