python实现鸢尾花三种聚类算法(K-means,AGNES,DBScan)

  • Post category:Python

Python实现鸢尾花三种聚类算法(K-means, AGNES, DBScan)

1. 简介

聚类是一种无监督学习算法,它将相似的数据点分组到同一个簇中。本文将介绍如何使用Python实现三种聚类算法:K-means、AGNES和DBScan,并使用鸢尾花数据集进行演示。

2. 数据集

我们将使用鸢尾花数据集来演示如何使用聚类算法。该数据集包含150个样本,每个样本有四个特征:花萼长度、花萼宽度、花瓣长度和花瓣宽度。以下是数据集的示例:

花萼长度 花萼宽度 花瓣长度 花瓣宽度 类别
5.1 3.5 1.4 0.2 0
4.9 3.0 1.4 0.2 0
7.0 3.2 4.7 1.4 1
6.4 3.2 4.5 1.5 1
6.3 3.3 6.0 2.5 2
5.8 2.7 5.1 1.9 2

3. K-means算法

K-means算法是一种基于距离的聚类算法,它将数据点分为K个簇,使得每个簇内的数据点相似度较高,而不同簇之间的相似度较低。具体实现步骤如下:

  1. 随机选择K个数据点作为初始质心。
  2. 对于每个数据点,计算它与每个质心的距离,并将它分配到距离最近的质心所在的簇中。
  3. 对于每个簇,重新计算它的质心。
  4. 重复步骤2和步骤3,直到质心不再发生变化或达到最大迭代次数。

以下是使用Python实现K-means算法的代码:

import numpy as np
from sklearn.datasets import load_iris

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

    def fit(self, X):
        self.centroids = X[np.random.choice(X.shape[0], self.n_clusters, replace=False)]
        for i in range(self.max_iter):
            clusters = [[] for _ in range(self.n_clusters)]
            for x in X:
                distances = np.linalg.norm(self.centroids - x, axis=1)
                cluster = np.argmin(distances)
                clusters[cluster].append(x)
            new_centroids = np.array([np.mean(cluster, axis=0) for cluster in clusters])
            if np.allclose(self.centroids, new_centroids):
                break
            self.centroids = new_centroids

    def predict(self, X):
        distances = np.linalg.norm(self.centroids - X[:, np.newaxis], axis=2)
        return np.argmin(distances, axis=1)

这个代码实现了一个名为KMeans的类,它包含两个方法:

  • fit(X):用于训练K-means聚类器,其中X是一个二维数组,表示每个样本的特征。
  • predict(X):用于对新样本进行聚类,其中X是一个二维数组,表示每个样本的特征;返回一个一维数组,表示每个样本所属的簇。

4. AGNES算法

AGNES算法是一种基于层次的聚类算法,它将数据点逐层合并,直到所有数据点都在同一个簇中。具体实现步骤如下:

  1. 将每个数据点看作一个簇。
  2. 计算每两个簇之间的距离,并将距离最近的两个簇合并成一个新的簇。
  3. 重复步骤2,直到所有数据点都在同一个簇中。

以下是使用Python实现AGNES算法的代码:

import numpy as np
from sklearn.datasets import load_iris

class AGNES:
    def __init__(self, n_clusters=3):
        self.n_clusters = n_clusters

    def fit(self, X):
        self.clusters = [[x] for x in X]
        while len(self.clusters) > self.n_clusters:
            distances = np.zeros((len(self.clusters), len(self.clusters)))
            for i in range(len(self.clusters)):
                for j in range(i+1, len(self.clusters)):
                    distances[i, j] = np.min(np.linalg.norm(np.array(self.clusters[i]) - np.array(self.clusters[j]), axis=1))
            i, j = np.unravel_index(np.argmin(distances), distances.shape)
            self.clusters[i] += self.clusters[j]
            del self.clusters[j]

    def predict(self, X):
        labels = np.zeros(len(X))
        for i, x in enumerate(X):
            for j, cluster in enumerate(self.clusters):
                if x in cluster:
                    labels[i] = j
                    break
        return labels

这个代码实现了一个名为AGNES的类,它包含两个方法:

  • fit(X):用于训练AGNES聚类器,其中X是一个二维数组,表示每个样本的特征。
  • predict(X):用于对新样本进行聚类,其中X是一个二维数组,表示每个样本的特征;返回一个一维数组,表示每个样本所属的簇。

5. DBScan算法

DBScan算法是一种基于密度的聚类算法,它将数据点分为核心点、边界点和噪声点三类。具体实现步骤如下:

  1. 对于每个数据点,计算它的密度(即在以该点为圆心、以一定半径为半径的圆内包含的数据点数)。
  2. 将密度大于某个阈值的数据点标记为核心点。
  3. 对于每个核心点,将距离它在一定半径内的所有数据点标记为该核心点的邻居点。
  4. 将没有邻居点的数据点标记为噪声点,将邻居点数小于某个阈值的核心点标记为边界点。
  5. 将所有邻居点数大于等于某个阈值的核心点及其邻居点分为一个簇,重复步骤3和步骤4,直到所有数据点都被标记为核心点、边界点或噪声点。

以下是使用Python实现DBScan算法的代码:

import numpy as np
from sklearn.datasets import load_iris

class DBScan:
    def __init__(self, eps=0.5, min_samples=5):
        self.eps = eps
        self.min_samples = min_samples

    def fit(self, X):
        self.labels_ = np.zeros(len(X))
        cluster_id = 0
        for i, x in enumerate(X):
            if self.labels_[i] != 0:
                continue
            neighbors = self.region_query(X, i)
            if len(neighbors) < self.min_samples:
                self.labels_[i] = -1
            else:
                cluster_id += 1
                self.labels_[i] = cluster_id
                self.expand_cluster(X, i, neighbors, cluster_id)

    def predict(self, X):
        return self.labels_

    def region_query(self, X, i):
        distances = np.linalg.norm(X - X[i], axis=1)
        return np.where(distances <= self.eps)[0]

    def expand_cluster(self, X, i, neighbors, cluster_id):
        for j in neighbors:
            if self.labels_[j] == -1:
                self.labels_[j] = cluster_id
            elif self.labels_[j] == 0:
                self.labels_[j] = cluster_id
                new_neighbors = self.region_query(X, j)
                if len(new_neighbors) >= self.min_samples:
                    neighbors = np.concatenate((neighbors, new_neighbors))

这个代码实现了一个名为DBScan的类,它包含三个方法:

  • fit(X):用于训练DBScan聚类器,其中X是一个二维数组,表示每个样本的特征。
  • predict(X):用于对新样本进行聚类,其中X是一个二维数组,表示每个样本的特征;返回一个一维数组,表示每个样本所属的簇。
  • region_query(X, i):用于计算第i个数据点的邻居点,其中X是一个二维数组,表示每个样本的特征;返回一个一维数组,表示第i个数据点的邻居点的索引。

6. 示例

示例1

在示例1中,我们使用了鸢尾花数据集,使用KMeans、AGNES和DBScan三种聚类算法对数据集进行聚类,并输出聚类结果。

from sklearn.datasets import load_iris
from sklearn.metrics import adjusted_rand_score

iris = load_iris()
X = iris.data
y = iris.target

kmeans = KMeans(n_clusters=3)
kmeans.fit(X)
kmeans_labels = kmeans.predict(X)
print('KMeans ARI:', adjusted_rand_score(y, kmeans_labels))

agnes = AGNES(n_clusters=3)
agnes.fit(X)
agnes_labels = agnes.predict(X)
print('AGNES ARI:', adjusted_rand_score(y, agnes_labels))

dbscan = DBScan(eps=0.5, min_samples=5)
dbscan.fit(X)
dbscan_labels = dbscan.predict(X)
print('DBScan ARI:', adjusted_rand_score(y, dbscan_labels))

这个示例将使用上述代码对鸢尾花数据集进行聚类,并输出聚类结果的ARI值。

示例2

在示例2中,我们使用了一个包含6个样本的数据集,每个样本有两个征:长度和宽度。我们使用KMeans聚类算法对数据集进行聚类,并输出聚类结果。

import numpy as np

X = np.array([
    [1, 2],
    [2, 3],
    [3, 3],
    [3, 4],
    [4, 4],
    [5, 5],
])

kmeans = KMeans(n_clusters=2)
kmeans.fit(X)
labels = kmeans.predict(X)
print(labels)

这个示例将使用上述代码对数据集进行聚类,并输出聚类结果。

7. 总结

本文介绍了如何使用Python实现三种聚类算法:K-means、AGNES和DBScan,并使用鸢尾花数据集进行演示。聚类算法是一种无监督学习算法,它将相似的数据点分组到同一个簇中。在实际用中,我们可以根据数据集的特点选择合适的聚类算法,并使用Python实现相应的聚类器。