K-均值聚类算法

1.k-means概念及特性

K-均值聚类算法是一种无监督学习算法,用于将数据集分成 K 个不同的簇。该算法通过计算每个数据点与其所属簇的中心点之间的距离来确定哪些数据点属于哪些簇。该算法有以下几个步骤:

  1. 随机选择 K 个数据点作为聚类中心。
  2. 对于每个数据点,计算其与每个聚类中心之间的距离,并将其分配给距离最近的聚类中心所属的簇。
  3. 对于每个簇,计算其所有数据点的平均值,并将该平均值作为新的聚类中心。
  4. 重复2-3步骤直到每个簇的聚类中心不再变化或达到最大迭代次数。

2.k-means分类

根据k值的不同,k-均值聚类可以分为以下三类:

  1. 二分k-均值聚类:从一个簇开始,将其分成两个子簇,然后选择其中一个子簇进行继续分裂,直到分成k个簇为止。

  2. 批量k-均值聚类:从n个数据点中随机选择k个作为簇中心,将其余数据点分配到最近的簇中,并重新计算簇中心,不断迭代直到收敛。

  3. 在线k-均值聚类:从头开始依次读取数据点,更新簇中心和数据点的分配,不断调整直到收敛。

3.k-means优缺点

K-均值聚类算法的优点包括:

  1. 实现简单,易于理解和使用。
  2. 对于大型数据集具有可扩展性。
  3. 可以在处理缺失数据时进行适当的处理。

K-均值聚类算法的缺点包括:

  1. 对于初始聚类中心的选择非常敏感,可能会导致结果不理想。
  2. 对于不同密度和形状的簇,聚类效果可能不佳。
  3. 结果可能会收敛到局部最优解而不是全局最优解。

因此,K-均值聚类算法通常用于简单数据集或作为其他聚类算法的基础。

4.k-means用途及例子

K-均值聚类是一种常见的无监督学习算法,用于将数据集中的样本分成K个簇(cluster),并使每个样本都属于其中一个簇。K-均值聚类的常见用途包括:

  1. 市场细分:将顾客分成不同组,以便于分析其行为模式,制定相应的营销策略。

  2. 图像分割:将图像中的像素点根据其颜色或灰度值聚类分组,实现图像的分割。

  3. 自然语言处理:将文本中的词语聚类成不同的主题或类别,实现文本分类和信息提取等任务。

  4. 生物学:将基因序列或生物分子数据聚类成不同的子群,以便于分析其功能和作用等。

以下是一个例子:

假设我们有一批包含100个人的数据集,每个人的年龄和收入如下:

人员编号 年龄 收入
1 25 3000
2 35 5000
3 45 8000
4 28 3500
5 32 4500
... ... ...
100 40 7500

我们希望将这100个人分成K个簇,以便于分析不同年龄和收入水平的人群的特征和行为模式。使用K-均值聚类算法,我们可以按照以下步骤进行:

  1. 随机选择K个簇的质心(centroid)。

  2. 将每个人分配到离其最近的质心所在的簇中。

  3. 计算每个簇的新质心。

  4. 重复步骤2和3,直到簇的质心不再变化或达到最大的迭代次数。

最终,我们可以得到K个簇,每个簇包含若干个人,这些人的年龄和收入水平相似。通过对每个簇进行统计和分析,我们可以找出不同年龄和收入水平的人群的特征和行为模式,从而制定相应的营销策略或人力资源管理策略等。

5.C++实现K-means聚类优化算法

#include 
#include 
#include 
#include 

using namespace std;

// 计算两个向量的欧几里得距离
double dist(vector& a, vector& b) {
    double sum = 0;
    for (int i = 0; i < a.size(); i++) {
        sum += pow(a[i] - b[i], 2);
    }
    return sqrt(sum);
}

// 计算所有点到各个簇心的距离,并返回每个点所属的簇的编号
vector get_clusters(vector>& data, vector>& centers) {
    vector clusters(data.size(), -1);
    for (int i = 0; i < data.size(); i++) {
        double min_dist = numeric_limits::max();
        for (int j = 0; j < centers.size(); j++) {
            double d = dist(data[i], centers[j]);
            if (d < min_dist) {
                min_dist = d;
                clusters[i] = j;
            }
        }
    }
    return clusters;
}

// 根据每个簇的点重新计算簇心
void update_centers(vector>& data, vector& clusters, vector>& centers) {
    for (int i = 0; i < centers.size(); i++) {
        vector sum(data[0].size(), 0);
        int count = 0;
        for (int j = 0; j < data.size(); j++) {
            if (clusters[j] == i) {
                for (int k = 0; k < data[j].size(); k++) {
                    sum[k] += data[j][k];
                }
                count++;
            }
        }
        if (count > 0) {
            for (int k = 0; k < sum.size(); k++) {
                centers[i][k] = sum[k] / count;
            }
        }
    }
}

// 计算所有点到其所属簇心的距离的平方和
double get_sse(vector>& data, vector>& centers, vector& clusters) {
    double sum = 0;
    for (int i = 0; i < data.size(); i++) {
        sum += pow(dist(data[i], centers[clusters[i]]), 2);
    }
    return sum;
}

// K-均值聚类优化算法
vector kmeans(vector>& data, int k, int max_iter = 100) {
    vector> centers(k, vector(data[0].size()));
    random_shuffle(data.begin(), data.end());  // 随机选择K个点作为初始簇心
    for (int i = 0; i < k; i++) {
        centers[i] = data[i];
    }
    vector clusters = get_clusters(data, centers);
    double sse = get_sse(data, centers, clusters);
    double prev_sse = numeric_limits::max();
    int iter = 0;
    while (iter < max_iter && sse < prev_sse) {  // 如果SSE不再减小,就停止迭代
        prev_sse = sse;
        update_centers(data, clusters, centers);
        clusters = get_clusters(data, centers);
        sse = get_sse(data, centers, clusters);
        iter++;
    }
    return clusters;
}

int main() {
    // 构造样本数据
    vector> data = {{-1, -1}, {-2, -1}, {-3, -2}, {1, 1}, {2, 1}, {3, 2}};
    int k = 2;  // 将数据分成两个簇
    // 调用K-均值聚类算法
    vector clusters = kmeans(data, k);
    // 输出结果
    for (int i = 0; i < data.size(); i++) {
        cout << "point " << i << " belongs to cluster " << clusters[i] << endl;
    }
    return 0;
}

在该示例中,我们首先定义了一个计算两个向量的欧几里得距离的函数 dist,然后定义了计算每个点到各个簇心的距离的函数 get_clusters、根据每个簇的点重新计算簇心的函数 update_centers、和计算所有点到其所属簇心的距离的平方和的函数 get_sse。接下来,我们实现了K-均值聚类优化算法 kmeans,其中包括随机初始化簇心、迭代计算直至SSE不再减小、返回每个点所属的簇的编号等步骤。最后,我们使用样本数据调用K-均值聚类算法,并输出每个点所属的簇的编号。

需要注意的是,该示例实现了一个简单的K-均值聚类算法,并没有加入优化算法(如K-Means++算法、Mini-Batch K-Means算法、层次聚类算法等),因此仅适用于小规模的数据集。如果需要处理大规模的数据集,建议使用一些专门针对大数据集的聚类算法,或考虑使用分布式计算框架(如Apache Spark)进行并行计算。

6.基于k-means实现数据分类的例子

假设我们有一个包含20个数据点的数据集,每个数据点有两个特征:x和y。我们将使用k-means算法来将这些数据点分为两个不同的类。

首先,我们导入需要的库并生成随机数据:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans

# 生成随机数据
np.random.seed(0)
X = np.random.randn(20, 2)

接下来,我们初始化k-means模型并拟合数据:

# 初始化k-means模型
kmeans = KMeans(n_clusters=2)

# 拟合数据
kmeans.fit(X)

然后,我们可以使用k-means模型的predict方法来预测每个数据点所属的类别:

# 预测数据点所属的类别
y_pred = kmeans.predict(X)

最后,我们将结果可视化。我们为每个数据点指定一个颜色,以表示它所属的类别。我们还在图上绘制了簇中心:

# 可视化结果
plt.scatter(X[:, 0], X[:, 1], c=y_pred)
plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], marker='*', s=200, c=[0, 1], edgecolors='k')
plt.show()

完整的代码如下:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans

# 生成随机数据
np.random.seed(0)
X = np.random.randn(20, 2)

# 初始化k-means模型
kmeans = KMeans(n_clusters=2)

# 拟合数据
kmeans.fit(X)

# 预测数据点所属的类别
y_pred = kmeans.predict(X)

# 可视化结果
plt.scatter(X[:, 0], X[:, 1], c=y_pred)
plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], marker='*', s=200, c=[0, 1], edgecolors='k')
plt.show()

这将生成一个散点图,其中每个数据点被着色以表示其所属的类别,而星号表示簇中心。

K-均值聚类算法_第1张图片

你可能感兴趣的:(机器学习,机器学习,人工智能)