“原型”是指样本空间中具有代表性的点,原型聚类称为“基于原型的聚类”,此类算法假设聚类结构能通过一组原型刻画,在现实聚类任务中极为常用。通常情况下,算法先对原型进行初始化,然后对原型进行迭代更新求解。采用不同原型表示、不同求解方式,将产生不同算法。
一、K均值聚类
算法步骤如下:
随机选择k个数据点作为初始的簇中心。
对于每个数据点,计算其到每个簇中心的距离,将其划分到距离最近的簇中。
对于每个簇,重新计算其簇中心,即将簇内所有数据点的坐标取平均值。
重复步骤2和步骤3,直到簇中心不再发生变化或达到预设的迭代次数。
最终得到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)是一种监督式聚类算法,其流程如下:
初始化:选择聚类数量K,随机初始化K个聚类中心向量(也称为原型向量)。
计算距离:对于每个数据点,计算它与每个聚类中心向量的距离,选择距离最小的聚类中心作为该数据点所属的聚类。
更新聚类中心:对于每个聚类中心,如果它被至少一个数据点所属,那么更新它的位置。更新规则有多种,常用的是增量学习法和移动聚类中心法。
重复步骤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__
、fit
和predict
。其中,__init__
用于初始化聚类数量k
和学习率alpha
,
fit
用于训练LVQ模型并更新聚类中心,
predict
用于预测样本所属的聚类。在
fit
方法中,首先随机选择k
个数据点作为初始聚类中心,然后迭代训练epochs
次。每次迭代中,对于每个输入样本x
,计算它与所有聚类中心的距离,并找到距离最近的聚类中心j
。如果x
属于聚类j
,则将聚类中心j
向x
的方向移动一步;否则,将聚类中心j
离x
的方向移动一步。在
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)
三、高斯混合聚类
高斯混合聚类是一种基于概率密度函数对数据进行聚类的方法。其基本思想是将每个簇看作是一个高斯分布,数据点来自于不同的高斯分布,通过最大化似然函数来确定每个数据点所属的簇。
其流程如下:
- 初始化高斯分布的参数,包括均值、协方差矩阵和混合系数。
- 对于每个数据点,计算其属于每个高斯分布的概率。
- 根据每个数据点属于每个高斯分布的概率,更新每个高斯分布的参数。
- 重复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
方法用于预测数据点所属的簇。