聚类算法学习笔记(1)--原型聚类

“原型”是指样本空间中具有代表性的点,原型聚类称为“基于原型的聚类”,此类算法假设聚类结构能通过一组原型刻画,在现实聚类任务中极为常用。通常情况下,算法先对原型进行初始化,然后对原型进行迭代更新求解。采用不同原型表示、不同求解方式,将产生不同算法。

一、K均值聚类

算法步骤如下:

  1. 随机选择k个数据点作为初始的簇中心。

  2. 对于每个数据点,计算其到每个簇中心的距离,将其划分到距离最近的簇中。

  3. 对于每个簇,重新计算其簇中心,即将簇内所有数据点的坐标取平均值。

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

  5. 最终得到k个簇,每个簇内的数据点距离尽可能接近,不同簇间的数据点距离尽可能远。

在实际应用中,k-means聚类算法可以用于图像分割、文本聚类、用户分群等领域。

K均值聚类代码示例:

import numpy as np
import matplotlib.pyplot as plt

def k_means(data, k):
    # 随机初始化k个簇中心 
    centroids = data[np.random.choice(len(data), k, replace=False)]
    # 初始化簇分配和簇距离数组
    cluster_assign = np.zeros(len(data))
    cluster_dist = np.zeros(len(data))
    # 迭代计算簇中心和簇分配
    for _ in range(100):
        # 计算每个数据点到每个簇中心的距离
        for i, x in enumerate(data):
            dists = np.linalg.norm(x - centroids, axis=1)
            cluster_assign[i] = np.argmin(dists)
            cluster_dist[i] = np.min(dists)
        # 计算每个簇的新中心
        for j in range(k):
            centroids[j] = np.mean(data[cluster_assign == j], axis=0)
    return cluster_assign, cluster_dist, centroids

# 生成随机数据
data = np.random.rand(100, 2)
# 聚类并绘制结果
cluster_assign, _, centroids = k_means(data, 3)
plt.scatter(data[:,0], data[:,1], c=cluster_assign)
plt.scatter(centroids[:,0], centroids[:,1], marker='x', s=200, linewidths=3, color='r')
plt.show()

二、学习向量量化

学习向量量化(LVQ)是一种监督式聚类算法,其流程如下:

  1. 初始化:选择聚类数量K,随机初始化K个聚类中心向量(也称为原型向量)。

  2. 计算距离:对于每个数据点,计算它与每个聚类中心向量的距离,选择距离最小的聚类中心作为该数据点所属的聚类。

  3. 更新聚类中心:对于每个聚类中心,如果它被至少一个数据点所属,那么更新它的位置。更新规则有多种,常用的是增量学习法和移动聚类中心法。

  4. 重复步骤2和3,直到聚类中心不再改变或达到预设的最大迭代次数。

定理方面,LVQ的目标是最小化聚类误差,即所有数据点与它们所属聚类中心之间的距离之和。因此,LVQ可以被视为一个优化问题,可以使用梯度下降等方法求解。

另外,LVQ也可以用于分类问题。与聚类不同,分类需要事先定义好每个类别的标签,并将标签信息纳入到LVQ的训练过程中。在分类任务中,LVQ的目标是最大化正确分类的数量。

学习向量量化代码示例:

import numpy as np

class LVQ:
    def __init__(self, k, alpha):
        self.k = k # 聚类数量
        self.alpha = alpha # 学习率 
        self.centers = None # 聚类中心

    def fit(self, X, y, epochs):
        self.centers = X[np.random.choice(X.shape[0], self.k, replace=False)]
        for epoch in range(epochs):
            for i, x in enumerate(X):
                # 计算距离并找到最近的聚类中心
                distances = np.sum((x - self.centers) ** 2, axis=1)
                j = np.argmin(distances)
                # 更新最近的聚类中心
                if y[i] == j:
                    self.centers[j] += self.alpha * (x - self.centers[j])
                else:
                    self.centers[j] -= self.alpha * (x - self.centers[j])

    def predict(self, X):
        distances = np.sum((X[:, np.newaxis] - self.centers) ** 2, axis=2)
        return np.argmin(distances, axis=1)

该代码定义了一个名为LVQ的类,它包含三个方法:__init__fitpredict。其中,__init__用于初始化聚类数量k和学习率alpha

fit用于训练LVQ模型并更新聚类中心,

predict用于预测样本所属的聚类。

fit方法中,首先随机选择k个数据点作为初始聚类中心,然后迭代训练epochs次。每次迭代中,对于每个输入样本x,计算它与所有聚类中心的距离,并找到距离最近的聚类中心j。如果x属于聚类j,则将聚类中心jx的方向移动一步;否则,将聚类中心jx的方向移动一步。

predict方法中,对于输入样本X,计算它们与所有聚类中心的距离,并返回距离最近的聚类的索引。

使用示例:

# 生成一些随机数据
X = np.random.rand(100, 2)
y = np.random.randint(0, 2, size=100)

# 训练LVQ模型
lvq = LVQ(k=2, alpha=0.1)
lvq.fit(X, y, epochs=100)

# 预测新数据点的聚类
X_new = np.random.rand(10, 2)
y_pred = lvq.predict(X_new)

三、高斯混合聚类

高斯混合聚类是一种基于概率密度函数对数据进行聚类的方法。其基本思想是将每个簇看作是一个高斯分布,数据点来自于不同的高斯分布,通过最大化似然函数来确定每个数据点所属的簇。

其流程如下:

  1. 初始化高斯分布的参数,包括均值、协方差矩阵和混合系数。
  2. 对于每个数据点,计算其属于每个高斯分布的概率。
  3. 根据每个数据点属于每个高斯分布的概率,更新每个高斯分布的参数。
  4. 重复2-3步骤直到收敛。

高斯混合聚类代码示例:

import numpy as np
from scipy.stats import multivariate_normal

class GMM:
    def __init__(self, n_clusters, max_iter=100):
        self.n_clusters = n_clusters
        self.max_iter = max_iter

    def fit(self, X):
        n_samples, n_features = X.shape

        # 初始化高斯分布的参数
        self.means = np.random.randn(self.n_clusters, n_features)
        self.covs = np.array([np.eye(n_features)] * self.n_clusters)
        self.weights = np.ones(self.n_clusters) / self.n_clusters

        for _ in range(self.max_iter):
            # E 步:计算每个数据点属于每个高斯分布的概率
            probs = np.zeros((n_samples, self.n_clusters))
            for i in range(self.n_clusters):
                probs[:, i] = self.weights[i] * multivariate_normal.pdf(X, self.means[i], self.covs[i])
            probs /= probs.sum(axis=1, keepdims=True)

            # M 步:更新每个高斯分布的参数
            for i in range(self.n_clusters):
                weight_i = probs[:, i].sum()
                self.weights[i] = weight_i / n_samples
                self.means[i] = np.sum(probs[:, i].reshape(-1, 1) * X, axis=0) / weight_i
                diff = X - self.means[i]
                self.covs[i] = np.dot(probs[:, i] * diff.T, diff) / weight_i
                    
    def predict(self, X):
        probs = np.zeros((X.shape[0], self.n_clusters))
        for i in range(self.n_clusters):
            probs[:, i] = self.weights[i] * multivariate_normal.pdf(X, self.means[i], self.covs[i])
        return np.argmax(probs, axis=1)

其中,n_clusters表示簇的数量,max_iter表示最大迭代次数,fit方法用于训练模型,predict方法用于预测数据点所属的簇。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
原型聚类是一种基于数据点之间相似度度量的聚类算法。其主要思想是通过计算数据点之间的相似度(或距离),将相似度较高的数据点聚集成一个簇。相似度的计算方式有多种,如欧几里得距离、曼哈顿距离、余弦相似度等。其中,欧几里得距离是最常用的相似度计算方式。 原型聚类算法的核心是原型向量。原型向量是指每个簇中心点的坐标值,可以是任意一个数据点的坐标值。原型向量在聚类过程中不断更新,直到达到一定的收敛条件为止。 原型聚类算法主要分为两类:基于密度的原型聚类和基于距离的原型聚类。基于密度的原型聚类是指将原型向量设置在密度较高的区域,以便更好地捕捉簇的特征;而基于距离的原型聚类是指将原型向量设置在簇的中心位置,以便更好地表示簇的几何形状。 在基于密度的原型聚类算法中,最常用的算法是DBSCAN(Density-Based Spatial Clustering of Applications with Noise)。DBSCAN算法通过设置一个密度阈值,将密度较高的区域划分为一个簇。在这个簇的周围,如果有密度较低的点,则被视为噪声点。这种算法可以有效地处理数据中存在噪声点和数据分布不均匀的情况。 在基于距离的原型聚类算法中,最常用的算法是K-Means算法。K-Means算法是一种迭代算法,通过不断更新每个簇的中心点,直到达到收敛条件为止。具体实现过程中,首先随机初始化簇的中心点,然后将每个数据点分配到距离最近的簇中心点中。接着,根据簇内的数据点重新计算簇中心点,直到簇中心点不再发生变化为止。 原型聚类算法具有以下优点: 1. 算法简单易懂,实现较为容易。 2. 能够识别出数据中存在的噪声点。 3. 可以处理非球形簇和数据分布不均匀的情况。 但原型聚类算法也存在以下缺点: 1. 对于初始原型向量的选择较为敏感,不同的初始选择可能导致不同的聚类结果。 2. 对于数据量较大的情况,计算量较大,时间复杂度较高。 3. 对于数据存在重叠的情况,可能会导致识别出的簇之间存在重叠部分。 综上所述,原型聚类算法是一种简单有效的聚类算法,可以应用于各种领域的数据分析中。在实际应用中,需要根据具体的数据特点和分析目的选择合适的算法和调整参数,以获得更好的聚类效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值