机器学习第九章-聚类

目录

9.1聚类任务

9.2性能度量

9.3距离计算

9.4圆形聚类

9.4.1k均值算法

9.4.2学习向量量化法(LVQ)

9.4.3高斯混合聚类

9.5密度聚类

 9.6层次聚类


9.1聚类任务

        在"无监督学习"中研究最多、应用最广的是"聚类" .聚类试图将数据集中的样本划分为若干个通常是不相交的子集,每个子集称为一个"簇" .聚类过程仅能自动形成簇结构,簇所对应的概念语义需由使用者来把握和命名。聚类的结果可用包含m个元素的簇标记向量 λ=(λ1;λ2;... ;λm) 表示.

9.2性能度量

        聚类性能度量亦称聚类"有效性指标"聚类性能度量大致有两类. 一类是将聚类结果与某个"参考模型" 进行比较,称为"外部指标" ; 另一类是直接考察聚类结果而不利用任何参考模型,称为"内部指标" 。

        聚类性能度量外部指标有如下:

Jaccard 系数(计算聚类结果与参考模型之间的交集与并集的比值)   JC=\frac{a}{a+b+c}
FM 指数(计算聚类结果与参考模型之间的精确度和召回率的调和平均数) :                                                                        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        FMI=\sqrt{\frac{a}{a+b}*\frac{a}{a+b}}
Rand 指数(计算聚类结果与参考模型之间的一致决策和不一致决策的比值)   RI=\frac{2(a+b)}{m(m-1)}
上述性能度量的结果值均在 [0 1] 区间,值越大越好.
         聚类性能度量内部指标有如下:
DB 指数 (通过衡量各个簇的紧密度和分离度来评估聚类的效果): 
        ​​​​​​​        ​​​​​​​        ​​​​​​​         \mathrm{DBI}=\frac{1}{k} \sum_{i=1}^{k} \max _{j \neq i}\left(\frac{\operatorname{avg}\left(C_{i}\right)+\operatorname{avg}\left(C_{j}\right)}{d_{\text {cen }}\left(\boldsymbol{\mu}_{i}, \boldsymbol{\mu}_{j}\right)}\right)
Du nn 指数(通过比较簇内的紧密度和簇间的分离度来评估聚类的质量):
        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​   \mathrm{DI}=\min _{1 \leqslant i \leqslant k}\left\{\min _{j \neq i}\left(\frac{d_{\min }\left(C_{i}, C_{j}\right)}{\max _{1 \leqslant l \leqslant k} \operatorname{diam}\left(C_{l}\right)}\right)\right\}
DBI 的值越小越好,而 DI 则相反,值越大越好.

9.3距离计算

        对函数 dist(. ,.),若它是一个"距离度量" (distance measure) ,则需满足一 些基本性质:

        非负性: dist(Xi , Xj) >=   0 ;
        同一性: dist(Xi , Xj)=0当且仅当 Xi = Xj ;
        对称性: dist(Xi , Xj)) = dist(xj , Xi) ;
        直递性: dist(Xi , Xj) <= dist(Xi , Xk) + dist(Xk,Xj)
最常用的是 "闵可夫斯基距离":       \operatorname{dist}_{\mathrm{mk}}\left(\boldsymbol{x}_{i}, \boldsymbol{x}_{j}\right)=\left(\sum_{u=1}^{n}\left|x_{i u}-x_{j u}\right|^{p}\right)^{\frac{1}{p}},p>=1
p=2 时,闵可夫斯基距离即欧氏距离:\operatorname{dist}_{e d}\left(\boldsymbol{x}_{i}, \boldsymbol{x}_{j}\right)=\left\|\boldsymbol{x}_{i}-\boldsymbol{x}_{j}\right\|_{2}=\sqrt{\sum_{u=1}^{n}\left|x_{i u}-x_{j u}\right|^{2}} .
p=1 时,闵可夫斯基距离即曼哈顿距离:\operatorname{dist}_{\text {man }}\left(\boldsymbol{x}_{i}, \boldsymbol{x}_{j}\right)=\left\|\boldsymbol{x}_{i}-\boldsymbol{x}_{j}\right\|_{1}=\sum_{u=1}^{n}\left|x_{i u}-x_{j u}\right|
        我们常将属性划分为"连续属性" 和"离散属性" ,前者在定义域上有无穷多个可能的取值,后者在定义域上是有限个取值.
        对无序属性可采用 VDM,m_{u,a}表示在属性 u上取值为a 的样本数, m_{u,a,i}表示在第i个样本簇
中在属性u 上取值为a 的样本数 ,k 为样本簇数,则属性u 上两个离散值a,b之间的 VDM 距离为:
                        
                                 \operatorname{VDM}_{p}(a, b)=\sum_{i=1}^{k}\left|\frac{m_{u, a, i}}{m_{u, a}}-\frac{m_{u, b, i}}{m_{u, b}}\right|^{p}
         当样本空间中不同属性的重要 性不同时 ,可使用" 加权距 离", 以加权闵 可夫 斯基距离为 例:
        ​​​​​​​         \operatorname{dist}_{\text {wmk }}\left(\boldsymbol{x}_{i}, \boldsymbol{x}_{j}\right)=\left(w_{1} \cdot\left|x_{i 1}-x_{j 1}\right|^{p}+\ldots+w_{n} \cdot\left|x_{i n}-x_{j n}\right|^{p}\right)^{\frac{1}{p}}
        

9.4圆形聚类

        算法先对原型进行初始化,然后对原型进行迭代更新求解.采用不同的原型表示、不同的求解方式,将产生不同的算法.

9.4.1k均值算法

        给定样本集 D=\left \{ x_{1},x_{2},...x_{m} \right \} "k 均值" 算法针对聚类所得簇划分 C=\left \{ C_{1},C_{2},...C_{m} \right \}最小化平方误差:

                                        E=\sum_{i=1}^{k} \sum_{\boldsymbol{x} \in C_{i}}\left\|\boldsymbol{x}-\boldsymbol{\mu}_{i}\right\|_{2}^{2}

        步骤如下:

  1. 选择K值:确定要分成的簇的数量K。

  2. 初始化中心:随机选择K个点作为初始簇中心(质心)。

  3. 分配簇:将每个数据点分配到距离其最近的簇中心所属的簇。

  4. 更新中心:重新计算每个簇的质心,质心是簇中所有点的均值。

  5. 重复迭代:重复步骤3和步骤4,直到簇中心不再发生显著变化,或者达到预设的迭代次数。

  6. 停止:算法结束时,簇的划分稳定,所有点被划分到其最终的簇中。

下面是关于k均值算法的实验过程及分析结果:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs

# 生成样本数据
X, y = make_blobs(n_samples=300, centers=4, cluster_std=0.60, random_state=0)

# 执行K均值算法
kmeans = KMeans(n_clusters=4)
kmeans.fit(X)

# 获取簇中心和每个点的簇标签
centers = kmeans.cluster_centers_
labels = kmeans.labels_

# 可视化结果
plt.scatter(X[:, 0], X[:, 1], c=labels, s=50, cmap='viridis')
plt.scatter(centers[:, 0], centers[:, 1], c='red', s=200, alpha=0.75, marker='X')
plt.title('K-Means Clustering')
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.show()

分析:

1.数据生成:生成了300个样本数据,划分为4个簇,每个簇的标准差为0.60。

2.K均值算法:对这些数据执行了K均值聚类,指定了4个簇。

3.可视化:结果图展示了数据点按簇进行着色,簇中心以红色“X”标记。   

        通过运行代码,可以直观地看到数据点如何被聚类到4个不同的簇中,以及每个簇的中心位置。这有助于验证K均值算法在实际数据上的效果。

实验结果:

9.4.2学习向量量化法(LVQ)

        LVQ 假设数据样本带有类别标记,学习过程利用样本的这些监督信息来辅助聚类。

步骤如下:

  1. 初始化:从训练数据中随机选择若干样本点作为初始的原型向量(或质心),这些原型向量的数量通常等于类别数。

  2. 分配类别:为每个原型向量分配一个类别标签,通常是其所属的训练样本的类别。

  3. 训练过程:对每个训练样本:

    • 更新原型
      • 如果样本点的真实类别与最近原型的类别相同,则将原型向量向样本点移动(调整原型向量的位置)。
      • 如果样本点的真实类别与最近原型的类别不同,则将原型向量远离样本点移动。
    • 选择最近原型:找到距离样本点最近的原型向量,并确定其类别标签。
    • 计算距离:计算样本点到所有原型向量的距离。
  4. 重复训练:重复步骤3,直到原型向量的位置稳定,或者达到预设的训练次数。

  5. 分类:使用训练好的原型向量对新样本进行分类:计算新样本与所有原型向量的距离,并将样本分配给距离最近的原型的类别

学习向量量化的实验过程及分析结果如下:

import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.preprocessing import StandardScaler

class LVQ:
    def __init__(self, n_prototypes):
        self.n_prototypes = n_prototypes

    def fit(self, X, y, n_iter=100, lr=0.01):
        self.classes = np.unique(y)
        self.prototypes = np.zeros((self.n_prototypes, X.shape[1]))
        self.labels = np.zeros(self.n_prototypes, dtype=int)
        
        # Initialize prototypes randomly
        for i in range(self.n_prototypes):
            idx = np.random.choice(len(X))
            self.prototypes[i] = X[idx]
            self.labels[i] = y[idx]
        
        for _ in range(n_iter):
            for i, x in enumerate(X):
                dists = np.linalg.norm(x - self.prototypes, axis=1)
                closest_idx = np.argmin(dists)
                if y[i] == self.labels[closest_idx]:
                    self.prototypes[closest_idx] += lr * (x - self.prototypes[closest_idx])
                else:
                    self.prototypes[closest_idx] -= lr * (x - self.prototypes[closest_idx])

    def predict(self, X):
        dists = np.linalg.norm(X[:, np.newaxis] - self.prototypes, axis=2)
        closest_idx = np.argmin(dists, axis=1)
        return self.labels[closest_idx]

# Load Iris dataset
data = load_iris()
X = data.data
y = data.target

# Standardize the features
scaler = StandardScaler()
X = scaler.fit_transform(X)

# Split into training and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# Initialize and train LVQ model
model = LVQ(n_prototypes=10)
model.fit(X_train, y_train)

# Predict and evaluate
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)

print(f'准确率: {accuracy:.2f}')

分析:        

        这个实现没有依赖于 sklearn_lvq 库,而是手动实现了 LVQ 算法。使用了 numpyscikit-learn 进行数据处理和评估。

  1. 初始化 LVQ 类:定义 LVQ 类及其方法。
  2. 训练模型:初始化原型,更新原型的位置。
  3. 预测和评估:通过计算距离并预测类别,评估模型性能。

实验结果:

9.4.3高斯混合聚类

        高斯混合聚类采用概率模型来表达聚类原型。对n维样本空间X中的随机向量 x,若x服从高斯分布,其概率密度函数为:p(\boldsymbol{x})=\frac{1}{(2 \pi)^{\frac{n}{2}}|\boldsymbol{\Sigma}|^{\frac{1}{2}}} e^{-\frac{1}{2}(\boldsymbol{x}-\boldsymbol{\mu})^{\mathrm{T}} \boldsymbol{\Sigma}^{-1}(\boldsymbol{x}-\boldsymbol{\mu})},

步骤如下:        

1. 初始化参数

2. 期望步骤(E-Step)

3. 最大化步骤(M-Step)

4. 收敛性检查

5. 结果解释

下面是关于高斯混合聚类算法的实验过程及分析结果:

import numpy as np
from sklearn.mixture import GaussianMixture
import matplotlib.pyplot as plt

# 生成示例数据
np.random.seed(0)
n_samples = 300
C = np.array([[0.7, -0.7], [0.7, 0.7]])
X = np.dot(np.random.randn(n_samples, 2), C)

# 应用高斯混合模型
gmm = GaussianMixture(n_components=2, random_state=0)
gmm.fit(X)
labels = gmm.predict(X)

# 结果可视化
plt.figure(figsize=(8, 6))
plt.scatter(X[:, 0], X[:, 1], c=labels, s=40, cmap='viridis')
plt.title('GMM Clustering')
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')

# 绘制高斯分布
ax = plt.gca()
x = np.linspace(X[:, 0].min(), X[:, 0].max(), 100)
y = np.linspace(X[:, 1].min(), X[:, 1].max(), 100)
X_grid, Y_grid = np.meshgrid(x, y)
Z = np.exp(gmm.score_samples(np.c_[X_grid.ravel(), Y_grid.ravel()]))
Z = Z.reshape(X_grid.shape)
contour = ax.contour(X_grid, Y_grid, Z, levels=5, cmap='Greys', alpha=0.5)
plt.colorbar(contour)
plt.show()

# 输出分析结果
print("GMM Converged:", gmm.converged_)
print("Number of Iterations:", gmm.n_iter_)
print("Means of the clusters:\n", gmm.means_)
print("Covariances of the clusters:\n", gmm.covariances_)

  分析:

  1. 聚类可视化:散点图显示了数据点根据模型预测的簇标签进行着色。等高线图显示了高斯分布的轮廓。
  2. GMM 收敛状态:通过 gmm.converged_ 判断模型是否收敛。
  3. 迭代次数gmm.n_iter_ 表示模型收敛的迭代次数。
  4. 均值和协方差gmm.means_ 和 gmm.covariances_ 提供了每个簇的均值和协方差矩阵。

这个代码和结果分析展示了高斯混合模型在二维数据上的应用。

实验结果:

9.5密度聚类

        密度聚类算法从样本密度的角度来考察样本之间的可连接性,并基于可连接样本不断扩展聚类簇以获得最终的聚类结果.DBSCAN 是一种著名的密度聚类算法,它基于一组"邻域"参数来刻画样本分布的紧密程度.

DBSCAN算法步骤如下:

  1. 选择参数:设置两个参数,eps(邻域的半径)和 min_samples(一个簇的最小样本数)。

  2. 遍历数据点:对于数据集中的每一个点,计算其 eps 邻域内的点数。

  3. 密度检验

    • 如果邻域内点数大于或等于 min_samples,将该点标记为核心点,并形成一个新簇。
    • 否则,标记为噪声点(如果它在任何核心点的邻域内)。
  4. 扩展簇

    • 从核心点开始,递归地将所有密度可达的点加入到同一簇中。
    • 对于新加入的点,再检查其邻域,重复此过程直到所有密度可达的点被处理完。
  5. 重复:对数据集中尚未标记的点重复步骤2至4,直到所有点被处理完。

  6. 处理噪声:所有未被分配到任何簇的点被标记为噪声。

DBSCAN的优点是能够发现任意形状的簇,并能自动识别噪声点。

下面是关于DBSCAN算法的实验代码及分析结果:

import numpy as np
from sklearn.cluster import DBSCAN
import matplotlib.pyplot as plt
from sklearn.datasets import make_moons

# 生成示例数据
X, _ = make_moons(n_samples=300, noise=0.1, random_state=42)

# 应用 DBSCAN 算法
dbscan = DBSCAN(eps=0.3, min_samples=5)
labels = dbscan.fit_predict(X)

# 结果可视化
plt.figure(figsize=(8, 6))
unique_labels = np.unique(labels)
colors = plt.cm.get_cmap('viridis', len(unique_labels))

for label in unique_labels:
    mask = (labels == label)
    plt.scatter(X[mask, 0], X[mask, 1], c=[colors(label)], label=f'Cluster {label}' if label != -1 else 'Noise', s=50)

plt.title('DBSCAN Clustering')
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.legend()
plt.show()

# 输出分析结果
print("Cluster labels:", np.unique(labels))
print("Number of clusters found:", len(set(labels)) - (1 if -1 in labels else 0))
print("Number of noise points:", list(labels).count(-1))

分析结果:

  1. 聚类可视化

    散点图展示了通过 DBSCAN 聚类得到的结果。不同的颜色表示不同的簇,噪声点(未分配到任何簇的点)通常会被标记为单独的颜色。
  2. 簇标签

    np.unique(labels) 列出了所有簇标签。标签 -1 表示噪声点。
  3. 簇数量

    len(set(labels)) - (1 if -1 in labels else 0) 计算了簇的数量。-1 被排除在外,因为它代表噪声点,不属于任何簇。
  4. 噪声点数量

    list(labels).count(-1) 计算了噪声点的数量。

实验结果:

 9.6层次聚类

        层次聚类试图 不同层次对数据集进行划分,从而形成树聚类结构 ,数据集的划分采用"自 底向上 "的聚合策略,也可采 "自顶向下" 分拆策略.

        AGNES 是一种采用自底 向上聚合策略的层次聚类算法.它先将数据集中的每个样本看作初始聚类簇,然后在算法运行的每一步中找出离最近的两个聚类簇进行合并,该过程不断重复,直至达到预设的聚类簇个数.

步骤如下:

  1. 初始化:将每个数据点视为一个单独的簇。

  2. 计算距离:计算所有簇之间的距离。初始时,距离是数据点之间的距离。

  3. 合并簇

    • 找到距离最小的两个簇,将它们合并成一个新的簇。
    • 更新簇间的距离。具体方法取决于距离度量,例如单链接、全链接或平均链接。
  4. 重复:重复步骤2和3,直到所有点被合并成一个簇或达到预定的簇数量。

  5. 停止条件:算法结束时,得到一个树状图(dendrogram),表示不同簇的合并过程。

下面是AGNES算法的实验代码和分析结果:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import AgglomerativeClustering
from sklearn.datasets import make_moons
import scipy.cluster.hierarchy as sch

# 生成示例数据
X, _ = make_moons(n_samples=300, noise=0.1, random_state=42)

# 应用 AGNES 算法(AgglomerativeClustering)
agnes = AgglomerativeClustering(n_clusters=2, linkage='ward')
labels = agnes.fit_predict(X)

# 结果可视化
plt.figure(figsize=(8, 6))
plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis', s=50, edgecolor='k')
plt.title('Agglomerative Clustering (AGNES)')
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.show()

# 生成树状图(dendrogram)
plt.figure(figsize=(10, 7))
dendrogram = sch.dendrogram(sch.linkage(X, method='ward'))
plt.title('Dendrogram for AGNES')
plt.xlabel('Sample index')
plt.ylabel('Distance')
plt.show()

# 输出分析结果
print("Cluster labels:", np.unique(labels))
print("Number of clusters found:", len(set(labels)))

分析结果:

  1. 聚类可视化

    散点图展示了通过 AGNES 聚类得到的结果。不同的颜色表示不同的簇,便于观察数据的分组情况。
  2. 树状图

    树状图展示了数据点合并的过程。每次合并操作都会在树状图上形成一个连接线,线的高度表示合并时的距离。通过观察树状图,可以确定不同簇的形成过程和距离。
  3. 簇标签

    np.unique(labels) 列出了所有簇的标签。与散点图中的颜色对应。
  4. 簇数量

    len(set(labels)) 计算了最终得到的簇的数量。这与在 AGNES 中设定的 n_clusters 参数一致。

这段代码展示了如何使用 AGNES 进行层次聚类,并通过可视化结果和树状图来分析聚类效果

实验结果:

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值