大部分人对聚类的认识可以归纳为以下几个方面:
-
数据分组:许多人将聚类视为将数据划分为不同的组或簇,使得同一组内的数据点更加相似或相关。这种观点认为聚类是一种无监督学习技术,用于发现数据中的内在结构和模式。
-
相似性度量:通常认为聚类算法通过计算数据点之间的相似性或距离来确定它们是否属于同一簇。相似性度量可以基于欧氏距离、余弦相似度等方法。
-
发现未知群体:聚类被视为一种工具,用于发现现有数据中隐藏的未知群体。通过聚类分析,可以发现数据集中的潜在模式、群体或类别,从而帮助了解数据的特征和结构。
-
应用领域:人们普遍认为聚类广泛应用于各个领域,如市场细分、客户分析、图像分割、推荐系统等。聚类可以帮助理解和利用大规模数据集,探索数据中的关联性和趋势。
然而,值得注意的是,不同人对聚类的认识和理解可能存在差异,因为聚类本质上是一个多样化的领域,涉及多种算法和技术。此外,聚类也可能面临一些挑战,如选择合适的距离度量、确定最佳簇的数量等。因此,在使用聚类算法时,需要根据具体问题和数据特点进行适当的选择和调整。
今天就来详细说说常见的几种:
-
K均值聚类
-
层次聚类
-
密度聚类
-
谱聚类
-
EM聚类
-
模糊聚类
以下代码均可直接运行起来,方便学习!
K均值聚类
K均值聚类是一种常用的无监督学习算法,用于将数据点划分为不同的簇,使得同一簇内的数据点彼此相似度较高,不同簇之间的数据点相似度较低。
这个算法的目标是将数据点分为K个簇,其中K是用户定义的参数。K均值聚类的原理相对简单,主要思想是通过迭代寻找K个簇的中心点,将每个数据点分配给距离其最近的中心点,然后更新中心点的位置,直到满足停止条件为止。
原理介绍
1、选择要分成的簇的数量K。
2、随机初始化K个中心点,这些中心点可以是从数据集中随机选择的数据点。
3、重复以下过程,直到满足停止条件:
-
将每个数据点分配到距离其最近的中心点所属的簇。
-
对每个簇,计算所有数据点的平均值,并将其作为新的中心点。
停止条件通常可以是以下之一:
-
中心点不再改变或改变非常小。
-
数据点不再改变其所属簇。
公式表达
K均值聚类的主要公式包括:
-
距离度量(一般使用欧氏距离):
对于两个数据点X和Y,它们之间的欧氏距离可以表示为:
一个案例
一个用Python实现K均值聚类:
import numpy as np
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
# 生成随机数据
np.random.seed(0)
X = np.random.rand(100, 2)
# 使用K均值聚类,假设要分成3个簇
kmeans = KMeans(n_clusters=3)
kmeans.fit(X)
# 获取簇的中心点和每个数据点的所属簇
centers = kmeans.cluster_centers_
labels = kmeans.labels_
# 绘制数据点和簇中心
plt.scatter(X[:, 0], X[:, 1], c=labels)
plt.scatter(centers[:, 0], centers[:, 1], marker='x', s=200, linewidths=3, color='r')
plt.title('K-Means Clustering')
plt.show()
这段代码首先生成一些随机数据,然后使用scikit-learn库的KMeans类进行聚类,并绘制了数据点和簇中心的图形。
可以看到K均值聚类是如何将数据点分成不同的簇的,并找到簇的中心点。图形展示了数据点的分布以及簇中心的位置。
层次聚类
层次聚类 通过构建数据点之间的层次结构来组织簇。这种层次结构通常以树状图(树状图或谱系图)的形式呈现,可以帮助理解数据点之间的相似性关系以及簇之间的关系。
层次聚类可以分为两种主要类型:自上而下的凝聚聚类和自下而上的分裂聚类。
原理介绍
-
凝聚聚类(Agglomerative Clustering):从底部开始,每个数据点被视为一个单独的簇,然后迭代地合并最接近的簇,直到只剩下一个大的簇。
-
分裂聚类(Divisive Clustering):从顶部开始,所有数据点被视为一个大的簇,然后逐渐分裂成更小的簇,直到每个数据点都是一个单独的簇。
层次聚类的主要步骤包括:
-
初始化:将每个数据点视为一个独立的簇。
-
合并(对于凝聚聚类)或分裂(对于分裂聚类)簇以创建一个新的层次结构。
-
重复步骤2,直到满足停止条件。
公式表达
在层次聚类中,距离度量是关键。常用的距离度量包括欧氏距离、曼哈顿距离、马氏距离等,具体选择取决于问题的性质。合并或分裂簇的准则也可以有多种,例如最短距离、最长距离、平均距离等。
一个Python案例
使用 scikit-learn 实现层次聚类:
import numpy as np
from sklearn.cluster import AgglomerativeClustering
import matplotlib.pyplot as plt
from scipy.cluster.hierarchy import dendrogram
# 生成随机数据
np.random.seed(0)
X = np.random.rand(10, 2)
# 使用凝聚聚类,假设要分成2个簇
agg_clustering = AgglomerativeClustering(n_clusters=2)
agg_clustering.fit(X)
# 绘制树状图(谱系图)
linkage_matrix = np.column_stack([agg_clustering.children_, agg_clustering.distances_])
dendrogram(linkage_matrix, p=10, truncate_mode='level')
plt.title('Hierarchical Clustering Dendrogram')
plt.xlabel('Data point index')
plt.ylabel('Distance')
plt.show()
首先生成一些随机数据,然后使用scikit-learn库的AgglomerativeClustering类进行凝聚聚类,并绘制了树状图(谱系图)。树状图显示了数据点的分层结构,以及簇之间的合并情况。
密度聚类
密度聚类 根据数据点周围的密度来发现簇。最著名的密度聚类算法之一是DBSCAN(Density-Based Spatial Clustering of Applications with Noise)。
DBSCAN是一种基于密度的聚类算法,它的主要思想是根据数据点周围的密度来确定簇的边界。
与K均值等算法不同,DBSCAN不需要事先指定簇的数量,而且能够发现各种形状的簇,同时还能识别异常点(噪声)。
原理介绍
DBSCAN 算法的核心思想是通过以下两个参数来定义簇:
1、**ε (epsilon)**:表示半径,它用来确定一个点的邻域范围。
2、MinPts:表示一个点的邻域内至少包含的数据点数目。
DBSCAN 算法的工作流程如下:
1、随机选择一个未被访问的数据点作为起始点。
2、计算该点的ε邻域内的数据点数量。
3、如果邻域内的数据点数目大于等于MinPts,则将该点标记为核心点(Core Point),并将其邻域内的所有点加入同一簇中。
4、重复以上过程,直到无法找到更多的核心点。
5、选择下一个未被访问的数据点,继续上述过程,直到所有数据点都被访问。
最终,所有被访问的点都将属于某个簇或者被标记为噪声点。
关键概念
-
ε邻域:对于点P,它的ε邻域包含了距离点P不超过ε的所有点。
-
核心点(Core Point):如果点P的ε邻域内至少包含MinPts个数据点,那么点P被标记为核心点。
-
边界点(Border Point):如果点P的ε邻域内包含少于MinPts个数据点,但它是某个核心点的邻接点,那么点P被标记为边界点。
-
噪声点(Noise Point):如果点P不是核心点,也不是边界点,那么点P被标记为噪声点。
一个案例
使用 Scikit-Learn 中的DBSCAN 做一个密度聚类。
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import DBSCAN
from sklearn.datasets import make_blobs
# 创建一个随机数据集
X, _ = make_blobs(n_samples=1000, centers=3, cluster_std=1.0, random_state=42)
# 使用DBSCAN算法进行密度聚类
dbscan = DBSCAN(eps=0.5, min_samples=5)
dbscan.fit(X)
# 获取每个点的簇标签
labels = dbscan.labels_
# 绘制聚类结果
unique_labels = np.unique(labels)
colors = plt.cm.Spectral(np.linspace(0, 1, len(unique_labels)))
for label, color in zip(unique_labels, colors):
if label == -1:
# 噪声点用黑色表示
color = 'k'
class_member_mask = (labels == label)
xy = X[class_member_mask]
plt.scatter(xy[:, 0], xy[:, 1], c=color, s=20, label='Cluster %d' % label)
plt.title('DBSCAN Clustering')
plt.legend()
plt.show()
这个示例使用了Scikit-Learn中的DBSCAN类来对一个具有3个簇的数据集进行聚类。
实际情况中,可以根据自己的数据和参数来调整代码以适应不同的情况。
谱聚类
谱聚类 通过将数据集表示为图的形式来进行聚类分析。
谱聚类在图论、线性代数和谱分析等领域有广泛的应用,它能够有效地处理复杂的数据结构,并且在一些情况下表现出色。
原理介绍
1、构建相似度图(Affinity Matrix):首先,将数据集中的样本视为图的节点,计算每一对样本之间的相似度。通常使用高斯核函数来度量相似性,具体计算方式如下:
一个Python案例
依旧使用 Scikit-Learn 进行实现:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_moons
from sklearn.cluster import SpectralClustering
from sklearn.metrics import pairwise_distances
from scipy.sparse import csgraph
# 生成一个随机的月亮形状的数据集
X, _ = make_moons(n_samples=1000, noise=0.05, random_state=42)
# 计算相似度矩阵
sigma = 0.2
W = np.exp(-pairwise_distances(X, metric="sqeuclidean") / (2.0 * sigma ** 2))
# 构建对称归一化拉普拉斯矩阵
D = np.diag(W.sum(axis=1))
L = D - W
D_sqrt_inv = np.linalg.inv(np.sqrt(D))
L_sym = np.dot(np.dot(D_sqrt_inv, L), D_sqrt_inv)
# 计算特征向量
k = 2 # 聚类数
eigenvalues, eigenvectors = np.linalg.eigh(L_sym)
X_new = eigenvectors[:, :k]
# 使用谱聚类
sc = SpectralClustering(n_clusters=k, affinity="precomputed", random_state=42)
labels = sc.fit_predict(W)
# 可视化结果
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
plt.scatter(X[:, 0], X[:, 1], c=labels, cmap="viridis")
plt.title("Spectral Clustering Result")
plt.subplot(1, 2, 2)
plt.scatter(X[:, 0], X[:, 1], c=_, cmap="viridis")
plt.title("Original Data")
plt.show()
首先生成一个月亮形状的数据集,然后计算相似度矩阵,构建对称归一化拉普拉斯矩阵,计算特征向量,最后使用谱聚类对数据集进行聚类,并可视化聚类结果和原始数据。
未完待续。。。