基于python的机器学习(五)—— 聚类(二)

一、k-medoids聚类算法

k-medoids是一种聚类算法,它是基于k-means聚类算法的一种改进。k-medoids算法也是一种迭代算法,但是它将中心点限定为数据集中的实际样本点,而不是任意的点。

具体来说,k-medoids算法从数据集中选择k个初始中心点,然后将数据集中的每个样本分配给最近的中心点,并计算每个中心点的总距离。接下来,算法会尝试用一个未被选中的样本替换每个中心点,并计算新的总距离,选择总距离最小的替换。重复这个过程,直到中心点的位置不再改变或达到预定的迭代次数。

1.1 k-medoids与k-means算法的异同点

k-medoids算法是k-means算法的一个变种,它们都是聚类算法,但在一些方面有所不同。

相同点:

  1. 目标函数:k-medoids和k-means算法的目标都是将数据点划分到k个簇中,使得簇内的数据点相似度最大化,簇间的相似度最小化。
  2. 选择中心点:k-medoids和k-means算法都需要选择k个中心点作为初始点,然后通过迭代算法来更新中心点,直到收敛。
  3. 簇分配:k-medoids和k-means算法都是通过计算数据点与中心点之间的距离来确定数据点的簇分配。

不同点:

  1. 中心点的选择:k-medoids算法选择的中心点必须是实际数据点,而k-means算法的中心点可以是任意点。
  2. 距离度量:k-medoids算法使用的是曼哈顿距离(或其他适合计算离散特征的距离度量),而k-means算法使用的是欧几里德距离(适用于计算连续特征的距离度量)。
  3. 簇的划分:k-medoids算法的簇划分更加稳定,因为每个簇的中心点必须是实际数据点,而k-means算法的簇划分可能会受到初始点的选择影响,可能会得到不同的结果。
  4. 计算复杂度:k-medoids算法的计算复杂度要高于k-means算法,因为它需要计算每个数据点到中心点的距离,并选择最近的中心点作为簇分配。

1.2 k-medoids算法原理和实例

k-medoids算法是一种聚类算法,它的原理是通过将数据集中的每个数据点分配给最近的一个中心点,然后重新计算每个中心点的位置,直到达到收敛的效果为止。

下面是k-medoids算法的步骤:

  1. 初始化k个中心点,可以随机选择k个数据点作为中心点。
  2. 对于每个数据点,计算其到所有中心点的距离,将它分配给距离最近的中心点。
  3. 对于每个中心点,计算它与其他被分配给它的数据点的总距离,选择具有最小总距离的数据点作为新中心点。
  4. 重复步骤2和步骤3,直到中心点不再改变或达到最大迭代次数。

下面是一个简单的示例代码来实现k-medoids算法

python 复制代码
import numpy as np

def k_medoids(X, k):
    # 随机初始化质心
    m, n = X.shape
    centroids_idx = np.random.choice(m, size=k, replace=False)
    centroids = X[centroids_idx]
    
    # 迭代更新质心
    max_iter = 100
    for _ in range(max_iter):
        # 分配每个样本到最近的质心
        distances = np.linalg.norm(X[:, np.newaxis] - centroids, axis=2)
        labels = np.argmin(distances, axis=1)
        
        # 更新质心为最小代价
        for i in range(k):
            cluster_X = X[labels == i]
            cluster_distances = np.linalg.norm(cluster_X[:, np.newaxis] - cluster_X, axis=2)
            costs = np.sum(cluster_distances, axis=1)
            best_idx = np.argmin(costs)
            centroids[i] = cluster_X[best_idx]
    
    return centroids, labels

# 示例用法
X = np.array([[1, 2], [2, 1], [3, 2], [9, 10], [10, 9], [11, 10]])
k = 2
centroids, labels = k_medoids(X, k)

print("质心:")
print(centroids)
print("标签:")
print(labels)

该示例代码中,X是输入数据的特征矩阵,k是聚类的类别数。k_medoids函数使用k-medoids算法进行聚类。它首先随机选择k个样本作为质心,然后迭代更新质心和样本的分配,直到达到最大迭代次数为止。最后返回最终的质心和样本的标签。

1.3 k-medoids聚类算法的优缺点

k-medoids聚类算法是一种基于划分的聚类算法,优点和缺点如下:

优点:

  1. 不受离群值的影响:k-medoids聚类算法使用实际数据点作为聚类中心(medoids),因此对离群值不敏感。这使得k-medoids算法在处理存在离群值的数据集时表现较好。
  2. 适用于任意距离度量:k-medoids算法可以使用任意距离度量来计算数据点之间的相似度,因此可以适用于各种类型的数据集。这使得k-medoids算法在处理非欧几里德空间的数据时具有灵活性。
  3. 可解释性:k-medoids算法生成的聚类结果直观易懂,因为每个聚类中心都是数据集中实际存在的数据点。

缺点:

  1. 对初始聚类中心的敏感性:k-medoids算法对初始聚类中心的选择非常敏感,不同的初始中心可能会导致不同的聚类结果。因此,为了获取稳定和准确的聚类结果,需要使用合适的初始聚类中心选择方法。
  2. 计算复杂度高:k-medoids算法的计算复杂度较高,特别是在处理大规模数据集时。因为算法需要计算每个数据点到每个聚类中心的距离,并且在每一次迭代中都需要重新选择最优的聚类中心。

1.4 k-medoids聚类算法的代码实现

Sklearn 的正式发行版 0.22 并没有提供 k-medoids 聚类模块,但在 GitHub网站中,可下载 k-medoids聚类模块的测试版 ,网址为https://github.com/terkkila/scikit-learn/tree/kmedoids/sklearn/clusterhttps://github.com/terkkila/scikit-learn/tree/kmedoids/sklearn/cluster在该页面中,需要下载**_ init .pyk_medoids.py**两个文件,将其复制到 X:\Anaconda3\lib\site-packages\sklearn\cluster 目录下(会替换掉原来的_ init _.py文件),即可使用 k_medoids 聚类模块。

k-medoids 聚类模块实际上是一个 k_medoids类,k_medoids类的使用方法和 k-means类很相似,它的构造函数的参数有:①簇的个数 n_clusters;②初始簇中心的获取方法 init();③获取初始簇中心的更迭次数 n_init。

用 k_medoids聚类算法将数据聚成2类(数据文件km.txt)。

km.txt 文件内容如下:(与上篇文章中的相同)

python 复制代码
import numpy as np
import matplotlib.pyplot as plt
from pyclust import KMedoids
import treelib

X1, X2 = [], []
fr = open('km.txt')
for line in fr.readlines():
    lineArr = line.strip().split()
    X1.append([int(lineArr[0])])
    X2.append([int(lineArr[1])])
X = np.array(list(zip(X1, X2))).reshape(len(X1), 2)

model = KMedoids(2).fit(X)        # 调用估计器fit()方法进行聚类,聚类数为2
colors = ['b', 'g', 'r', 'c']
markers = ['o', 's', 'x', 'o']

for i, l in enumerate(model.labels_):
    plt.plot(X1[i], X2[i], color=colors[l], marker=markers[i], ls='None')

# 下面用X形绘制中心点
centroids = model.cluster_centers_            # centroids保存了所有中心点

for i in range(2):
    plt.plot(centroids[i][0], centroids[i][1], markers[2])
plt.show()

二、DBSCAN聚类算法

DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一种基于密度的聚类算法。它通过将数据点划分为核心点、边界点和噪音点来进行聚类。DBSCAN算法的基本思想是寻找具有足够密度的数据点,将它们划分为一个簇,并通过连接具有足够密度的相邻数据点来扩展该簇。

2.1 DBSCAN聚类算法中的几个定义

  1. ϵ-领域:ϵ-领域是指一个点周围半径为ϵ的范围内的所有点的集合。具体地说,对于给定的一个点p,其ϵ-领域包括了所有与p的距离小于等于ϵ的点。
  2. 核心对象:核心对象是指一个数据点,如果在指定的半径r内至少有minPts个数据点,则该数据点被视为核心对象。具体来说,一个核心对象需要满足以下两个条件:
    1. 这些数据点必须是在半径r内的,即它们之间的距离必须小于等于r。
    2. 在半径r内至少有minPts个数据点,包括自身。
  3. 密度可达:对于DBSCAN算法中的一个样本点p,如果存在样本点q,使得q在p的ε领域内,并且q的密度达到了MinPts的要求,那么我们称q在以p为中心的ε领域内与p密度可达。而如果存在一系列样本点p1,p2,...,pn,使得p1与p2密度可达,p2与p3密度可达,...,pn-1与pn密度可达,那么我们称pn在以p1为中心的ε领域内与p1密度可达。
  4. 直接密度可达:对于DBSCAN算法中的一个样本点A,如果在半径ε内存在另一个样本点B,且B在A的ε-邻域内,即距离A小于等于ε,则样本点A的直接密度可达于样本点B。

2.2 DBSCAN聚类算法步骤

DBSCAN (Density-Based Spatial Clustering of Applications with Noise) 是一种聚类算法,用于在基于密度的空间中发现聚类。

DBSCAN算法的步骤如下:

  1. 初始化参数:设置半径ε和最小点数MinPts。
  2. 计算密度:对于数据集中的每个数据点,计算它的ε-邻域内的点的数量。如果该数量大于等于MinPts,则将该点标记为核心点。
  3. 标记边界点:对于每个核心点,将其ε-邻域内的点(不包括核心点)标记为边界点。
  4. 构建聚类:初始化一个空的聚类集合,并对每个核心点执行以下步骤: a. 如果该核心点尚未被访问过,则创建一个新的聚类,并将其加入到聚类集合中。 b. 将该核心点加入到当前聚类中。 c. 对于该核心点的ε-邻域内的所有点,如果该点是核心点,则将其加入到当前聚类中;如果该点是边界点且尚未被访问过,则将其加入到当前聚类中,并标记为已访问。
  5. 标记噪音点:对于所有未被访问过的点,如果其不属于任何聚类,则将其标记为噪音点。
  6. 输出结果:返回聚类集合。

2.3 DBSCAN聚类算法举例

假设有一组二维数据点,如下所示:

数据点1:(2, 3) 数据点2:(4, 5) 数据点3:(6, 7) 数据点4:(9, 10) 数据点5:(11, 12) 数据点6:(13, 14) 数据点7:(15, 16) 数据点8:(16, 17) 数据点9:(18, 19)

首先,我们需要选择两个参数:邻域半径eps和最小密度minPts。邻域半径eps决定了一个点的邻域范围,而最小密度minPts决定了一个核心点所需要的邻域内的最小数据点数。

假设我们选择eps=2和minPts=3,然后进行DBSCAN聚类算法。

  1. 随机选择一个未访问的数据点,比如数据点1。
  2. 检查数据点1的邻域内是否有至少minPts个数据点。
    • 数据点2和数据点3在数据点1的邻域内,那么数据点1为核心点,并且将数据点2和数据点3添加到同一个簇中。
    • 数据点4、数据点5、数据点6和数据点7不在数据点1的邻域内,不满足最小密度要求。
    • 数据点8和数据点9不在数据点1的邻域内,不满足最小密度要求。
  3. 随机选择一个未访问的核心点,比如数据点2。
  4. 检查数据点2的邻域内是否有至少minPts个数据点。
    • 数据点3在数据点2的邻域内,那么数据点2为核心点,并且将数据点3添加到同一个簇中。
    • 数据点1不在数据点2的邻域内,不满足最小密度要求。
  5. 随机选择一个未访问的核心点,比如数据点3。
  6. 检查数据点3的邻域内是否有至少minPts个数据点。
    • 数据点2在数据点3的邻域内,那么数据点3为核心点,并且将数据点2添加到同一个簇中。
    • 数据点1不在数据点3的邻域内,不满足最小密度要求。
  7. 继续选择下一个未访问的核心点,并进行相同的操作,直到所有的核心点都被访问过为止。
  8. 如果还有未访问的数据点,则将其标记为噪声点。

根据上述步骤,我们可以得到以下聚类结果:

  • 簇1:数据点1、数据点2、数据点3
  • 噪声点:数据点4、数据点5、数据点6、数据点7、数据点8、数据点9

2.4 DBSCAN聚类算法的优缺点

DBSCAN(Density-Based Spatial Clustering of Applications with Noise)聚类算法的优点和缺点如下:

优点:

  • 不需要事先指定聚类数量,能够自动发现数据中的聚类。
  • 能够处理任意形状的聚类,并且对噪声数据具有较强的鲁棒性。
  • 对于较大的数据集,DBSCAN算法具有较高的计算效率。
  • 对于具有不同密度的聚类,DBSCAN能够自适应地调整聚类的形状和大小。

缺点:

  • 对于高维数据,DBSCAN聚类算法表现不佳,容易出现维度灾难。
  • 对于数据集中密度不均匀的聚类,DBSCAN算法可能难以找到合适的聚类结果。
  • 对于数据集中聚类之间存在较大密度差距的情况,DBSCAN算法可能无法准确地划分聚类。
  • 对于数据集的参数选择较为敏感,需要事先对参数进行调优。

2.5 Sklearn实现DBSCAN聚类算法

使用sklearn库实现DBSCAN聚类算法对三维点进行聚类的示例代码:

python 复制代码
from sklearn.cluster import DBSCAN
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt

# 生成示例数据集
np.random.seed(0)
n_samples = 150
X = np.random.randn(n_samples, 3)

# 使用DBSCAN聚类算法进行聚类
dbscan = DBSCAN(eps=0.4, min_samples=10)
y_pred = dbscan.fit_predict(X)

# 绘制聚类结果
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
colors = ['blue', 'green', 'red', 'purple', 'yellow']
for i in range(len(np.unique(y_pred))):
    ax.scatter(X[y_pred == i, 0], X[y_pred == i, 1], X[y_pred == i, 2], c=colors[i], label='Cluster {}'.format(i))
ax.set_xlabel('Feature 1')
ax.set_ylabel('Feature 2')
ax.set_zlabel('Feature 3')
ax.set_title('DBSCAN Clustering')
plt.legend()
plt.show()

在上述代码中,我们使用np.random.randn函数生成了一个包含150个三维点的示例数据集。然后,我们使用DBSCAN类初始化了一个DBSCAN聚类算法的实例,并指定了epsmin_samples参数。最后,我们调用fit_predict方法对数据进行聚类,并将聚类结果绘制在三维散点图中。

三、OPTICS聚类算法

OPTICS(Ordering Points To Identify the Clustering Structure)是一种基于密度的聚类算法,它通过识别数据集中的密度相对较高的区域来发现聚类结构。与传统的基于密度的聚类算法DBSCAN不同,OPTICS不需要设置邻域大小参数,而是通过自适应地计算邻域大小来进行聚类

OPTICS算法的基本思想是,对于数据集中的每个点,计算它与其他点之间的距离,然后根据距离将数据点排序。通过这种排序方式,OPTICS算法可以在每个数据点的邻域中找到密度相对较高的数据点,从而识别出聚类的结构。

OPTICS算法的输出结果是一个可达距离图(Reachability Plot),它可以用于确定聚类的阈值参数,从而将数据点分为不同的聚类簇。通过分析可达距离图,可以识别出密度相对较高的聚类簇和稀疏区域。

OPTICS算法的主要步骤如下:

  1. 计算每个数据点与其他点之间的距离,构建距离矩阵。
  2. 根据距离矩阵,计算每个数据点的核心距离(core distance)。核心距离是一个自适应的邻域大小,用于判断一个点是否是核心点(core point)。
  3. 根据核心距离和距离矩阵,计算每个数据点的可达距离(reachability distance)。可达距离表示从一个数据点到另一个数据点的最短路径的最大距离。
  4. 根据可达距离,构建可达距离图。
  5. 分析可达距离图,确定聚类的阈值参数,将数据点分为不同的聚类簇。

3.1 Sklearn实现OPTICS聚类算法

使用sklearn库中的cluster.OPTICS类来实现OPTICS聚类算法。

下面是一个使用sklearn库实现OPTICS聚类算法的示例代码:

python 复制代码
from sklearn.cluster import OPTICS
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt

# 生成示例数据
X, y = make_blobs(n_samples=200, centers=4, random_state=0)

# 创建OPTICS聚类模型
optics = OPTICS(min_samples=10, xi=0.05, min_cluster_size=0.1)

# 拟合数据
optics.fit(X)

# 获取聚类标签
labels = optics.labels_

# 获取核心样本的可达距离
reachability_distances = optics.reachability_

# 绘制聚类结果
unique_labels = set(labels)
colors = [plt.cm.Spectral(each) for each in np.linspace(0, 1, len(unique_labels))]

for label, color in zip(unique_labels, colors):
    if label == -1:
        color = [0, 0, 0, 1]  # 将噪声样本用黑色表示

    class_member_mask = (labels == label)

    xy = X[class_member_mask]
    plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=tuple(color),
             markeredgecolor='k', markersize=14)

# 显示聚类结果
plt.title('OPTICS clustering')
plt.show()

在上述示例代码中,make_blobs函数用于生成示例数据。OPTICS类是OPTICS聚类算法的实现类,通过调用fit方法可以拟合数据并进行聚类。labels_属性用于获取聚类标签。reachability_属性用于获取核心样本的可达距离。

相关推荐
轻闲一号机34 分钟前
【机器学习】机器学习笔记
人工智能·笔记·机器学习
天下琴川1 小时前
Dify智能体平台源码二次开发笔记(5) - 多租户的SAAS版实现(2)
人工智能·笔记
小臭希2 小时前
python蓝桥杯备赛常用算法模板
开发语言·python·蓝桥杯
mosaicwang2 小时前
dnf install openssl失败的原因和解决办法
linux·运维·开发语言·python
蹦蹦跳跳真可爱5892 小时前
Python----机器学习(基于PyTorch的乳腺癌逻辑回归)
人工智能·pytorch·python·分类·逻辑回归·学习方法
Bruce_Liuxiaowei2 小时前
基于Flask的Windows事件ID查询系统开发实践
windows·python·flask
carpell2 小时前
二叉树实战篇1
python·二叉树·数据结构与算法
Hali_Botebie3 小时前
【端到端】端到端自动驾驶依赖Occupancy进行运动规划?还是可以具有生成局部地图来规划?
人工智能·机器学习·自动驾驶
CarnivoreRabbit3 小时前
Beamer-LaTeX学习(教程批注版)【2】
学习·latex·beamer
HORSE RUNNING WILD3 小时前
为什么我们需要if __name__ == __main__:
linux·python·bash·学习方法