K-Means是一种经典的聚类算法,常用于数据挖掘、机器学习等领域,以下是关于它的详细介绍:
基本原理
- K-Means算法的目标是将给定的数据集划分成K个不同的簇(cluster),使得同一簇内的数据点相似度较高,而不同簇之间的数据点相似度较低。
- 这里的相似度通常是通过计算数据点之间的距离来衡量的,常见的距离度量方式有欧几里得距离等。
算法步骤
- 确定聚类的数量K:这通常需要根据具体问题的领域知识、数据的特点或者通过一些经验法则来预先设定。
- 初始化聚类中心:随机从数据集中选取K个数据点作为初始的聚类中心,也可以采用其他的初始化方法来尽量避免得到局部最优解。
- 分配数据点到最近的聚类中心:对于数据集中的每个数据点,计算它到各个聚类中心的距离,然后将该数据点分配到距离它最近的那个聚类中心所对应的簇中。
- 更新聚类中心:在将所有数据点都分配到相应的簇之后,重新计算每个簇的中心位置,通常是计算该簇内所有数据点的均值作为新的聚类中心。
- 重复步骤3和4:不断重复分配数据点和更新聚类中心的操作,直到聚类中心的位置不再发生明显变化(达到预设的收敛条件,比如前后两次迭代中聚类中心的移动距离小于某个阈值)或者达到了预设的最大迭代次数。
特点
- 优点 :
- 原理简单,容易理解和实现,计算复杂度相对较低,在处理大规模数据时也能有较好的表现。
- 对于具有明显球形分布的数据聚类效果较好。
- 缺点 :
- 需要事先确定聚类的数量K,而K值的选择往往并不容易,如果K值选择不当,可能会得到不合理的聚类结果。
- 对初始聚类中心的选取比较敏感,不同的初始中心可能会导致不同的聚类结果,有可能陷入局部最优解而错过全局最优解。
- 只能处理数值型数据,对于非数值型数据需要进行适当的转换才能应用该算法。
应用场景
-
在市场细分中,根据客户的消费行为、人口统计学特征等数据将客户划分成不同的群体,以便企业制定针对性的营销策略。
-
在图像识别领域,对图像中的像素点进行聚类,从而实现图像分割等任务。
-
在文本挖掘中,对文档向量进行聚类,将相似的文档归为一类,便于信息的整理和分析。
以下是使用Python实现K-Means聚类算法的示例代码
一、代码实现
python
import numpy as np
import random
def kmeans(data, k, max_iterations=100):
"""
K-Means聚类算法实现
:param data: 输入的数据集,形状为 (n_samples, n_features),
n_samples为数据点个数,n_features为每个数据点的特征数
:param k: 要聚类的簇的数量
:param max_iterations: 最大迭代次数,默认为100
:return: centroids(聚类中心)和 labels(每个数据点所属的簇的标签)
"""
# 随机选择k个数据点作为初始聚类中心
n_samples, _ = data.shape
centroids = data[random.sample(range(n_samples), k)]
for _ in range(max_iterations):
# 计算每个数据点到聚类中心的距离,并分配到最近的聚类中心对应的簇
labels = []
for point in data:
distances = [np.linalg.norm(point - centroid) for centroid in centroids]
label = np.argmin(distances)
labels.append(label)
labels = np.array(labels)
# 更新聚类中心
new_centroids = []
for i in range(k):
cluster_points = data[labels == i]
new_centroid = np.mean(cluster_points, axis=0)
new_centroids.append(new_centroid)
new_centroids = np.array(new_centroids)
# 如果聚类中心不再变化,就提前结束迭代
if np.all(centroids == new_centroids):
break
centroids = new_centroids
return centroids, labels
二、函数调用示例
python
# 生成一些示例数据,这里假设数据是二维的,你可以根据实际情况替换
data = np.random.rand(100, 2)
# 设置聚类的簇数量
k = 3
# 调用kmeans函数进行聚类
centroids, labels = kmeans(data, k)
print("聚类中心:", centroids)
print("每个数据点所属的簇的标签:", labels)
三、代码注释说明
-
kmeans
函数:- 这个函数实现了K-Means聚类算法的核心步骤。
- 参数 :
data
:传入的数据集,是一个二维数组,其中第一维表示数据点的数量,第二维表示每个数据点的特征数量。例如,data
可以是一个形状为(100, 2)
的数组,表示有100个数据点,每个数据点有2个特征。k
:指定要将数据集聚类成的簇的数量。max_iterations
:算法的最大迭代次数,默认设置为100次。如果在达到这个次数之前聚类中心不再变化,算法会提前结束迭代。
- 返回值 :返回两个结果,
centroids
是聚类中心的数组,形状为(k, n_features)
,即有k
个聚类中心,每个聚类中心的维度与数据点的特征维度相同;labels
是一个一维数组,其长度等于数据点的数量,每个元素表示对应的数据点所属的簇的标签(从0到k - 1
)。
-
初始化聚类中心:
- 在函数内部,首先通过
n_samples, _ = data.shape
获取数据集的行数(即数据点个数)。 - 然后使用
centroids = data[random.sample(range(n_samples), k)]
随机从数据集中选取k
个数据点作为初始的聚类中心。
- 在函数内部,首先通过
-
迭代过程:
- 在每次迭代中:
- 分配数据点到簇 :
- 对于数据集中的每个数据点,通过循环计算它到各个聚类中心的距离。这里使用
distances = [np.linalg.norm(point - centroid) for centroid in centroids]
计算距离,其中np.linalg.norm
是计算欧几里得距离的函数。然后通过label = np.argmin(distances)
找到距离最近的聚类中心对应的簇标签,并将其添加到labels
列表中。最后将labels
列表转换为数组形式。
- 对于数据集中的每个数据点,通过循环计算它到各个聚类中心的距离。这里使用
- 更新聚类中心 :
- 对于每个簇(从0到
k - 1
),通过cluster_points = data[labels == i]
获取属于该簇的所有数据点。然后使用new_centroid = np.mean(cluster_points, axis=0)
计算这些数据点的均值作为新的聚类中心,并将其添加到new_centroids
列表中。最后将new_centroids
列表转换为数组形式。
- 对于每个簇(从0到
- 检查收敛条件 :
- 通过
if np.all(centroids == new_centroids):
检查当前迭代得到的聚类中心和上一次迭代的聚类中心是否完全相同。如果相同,说明聚类中心已经不再变化,算法提前结束迭代。否则,继续下一次迭代,并更新聚类中心为新得到的聚类中心。
- 通过
- 分配数据点到簇 :
- 在每次迭代中:
-
函数调用示例部分:
- 首先使用
data = np.random.rand(100, 2)
生成了一些随机的二维数据作为示例数据集。这里你可以根据实际情况替换为真实的数据集。 - 接着通过
k = 3
设置了聚类的簇数量为3。 - 最后调用
kmeans
函数进行聚类,并通过print("聚类中心:", centroids)
和print("每个数据点所属的簇的标签:", labels)
输出聚类中心和每个数据点所属的簇的标签。
- 首先使用