1. K-Means聚类算法概述
K-Means是数据挖掘和机器学习领域最经典的聚类算法之一,由J.B. MacQueen在1967年首次提出。这个算法通过迭代过程将n个数据点划分到k个簇中,使得每个数据点都属于离它最近的均值(即簇中心)对应的簇。算法名称中的"K"代表要形成的簇的数量,"Means"表示每个簇的中心由该簇中所有点的均值确定。
在实际应用中,K-Means常用于客户细分、图像压缩、异常检测等场景。比如电商平台可以用它分析用户购买行为,将用户分成不同群体;新闻网站可以用它对文章自动分类;工厂可以用它检测生产线上的异常产品。
算法核心思想:通过最小化簇内平方和(WCSS)来优化聚类结果,即让每个点到其所属簇中心的距离平方和最小。
2. K-Means算法原理详解
2.1 数学基础与距离度量
K-Means算法的数学基础建立在距离度量上。给定数据集X={x₁,x₂,...,xₙ},其中每个xᵢ∈ℝᵈ,算法需要找到k个簇中心C={c₁,c₂,...,cₖ},使得目标函数最小化:
code复制J = Σᵢ=1ⁿ Σⱼ=1ᵏ wᵢⱼ ||xᵢ - cⱼ||²
其中wᵢⱼ是指示变量,当xᵢ属于簇j时为1,否则为0。
常用的距离度量包括:
- 欧氏距离(默认):d(x,c) = √Σ(xᵢ - cᵢ)²
- 曼哈顿距离:d(x,c) = Σ|xᵢ - cᵢ|
- 余弦相似度:d(x,c) = 1 - (x·c)/(||x||·||c||)
在MATLAB中,可以通过'Distance'参数指定不同的距离度量方式:
matlab复制[idx, C] = kmeans(X, k, 'Distance', 'cityblock'); % 使用曼哈顿距离
2.2 算法流程与迭代过程
标准K-Means算法遵循以下步骤:
- 初始化:随机选择k个数据点作为初始簇中心
- 分配阶段:将每个数据点分配到最近的簇中心
- 更新阶段:重新计算每个簇的中心(均值)
- 收敛判断:如果簇中心变化小于阈值或达到最大迭代次数则停止,否则返回步骤2
MATLAB实现示例:
matlab复制% 生成随机数据
rng(1); % 设置随机种子保证可重复性
X = [randn(100,2)*0.75+ones(100,2);
randn(100,2)*0.5-ones(100,2)];
% 执行K-Means聚类
opts = statset('Display','final');
[idx, C] = kmeans(X, 2, 'Options', opts, 'Replicates', 5);
2.3 K-Means++优化算法
传统K-Means对初始中心敏感,可能收敛到局部最优。K-Means++通过改进初始化过程来解决这个问题:
- 随机选择第一个中心
- 对于每个后续中心,选择与已选中心距离较远的点,概率与距离平方成正比
- 继续直到选出k个中心
MATLAB中这是默认初始化方法,也可以显式指定:
matlab复制[idx, C] = kmeans(X, k, 'Start', 'plus');
3. 关键参数与调优技巧
3.1 簇数k的选择
确定最佳k值是关键挑战,常用方法包括:
- 肘部法则:绘制不同k值对应的WCSS曲线,选择拐点
matlab复制% 肘部法则实现
wcss = zeros(1,10);
for k = 1:10
[~, ~, sumd] = kmeans(X, k);
wcss(k) = sum(sumd);
end
plot(1:10, wcss, '-o')
xlabel('Number of clusters')
ylabel('WCSS')
- 轮廓系数:衡量簇内紧密度和簇间分离度
matlab复制% 计算轮廓系数
silhouette(X, idx)
- Gap统计量:比较实际数据与参考分布的WCSS差异
3.2 其他重要参数
| 参数 | 说明 | 推荐设置 |
|---|---|---|
| Replicates | 重复运行次数 | 5-10(避免局部最优) |
| MaxIter | 最大迭代次数 | 100-1000(根据数据规模调整) |
| OnlinePhase | 在线更新阶段 | 'on'(提高收敛质量) |
| EmptyAction | 空簇处理 | 'singleton'(避免空簇) |
4. 高级应用与性能优化
4.1 处理大规模数据
对于大数据集,可以采用以下优化策略:
- Mini-Batch K-Means:每次迭代使用数据子集
- 并行计算:利用多核CPU加速
matlab复制% 启用并行计算
options = statset('UseParallel',1);
[idx, C] = kmeans(X, k, 'Options', options);
- 降维预处理:先用PCA减少维度
4.2 处理非数值数据
通过适当距离度量扩展K-Means:
- 文本数据:使用TF-IDF向量化后配合余弦距离
- 分类数据:采用汉明距离
matlab复制[idx, C] = kmeans(X, k, 'Distance', 'hamming');
4.3 评估聚类质量
常用评估指标:
- 轮廓系数(-1到1,越大越好)
- Davies-Bouldin指数(越小越好)
- Calinski-Harabasz指数(越大越好)
MATLAB实现:
matlab复制% 计算Calinski-Harabasz指数
eva = evalclusters(X, idx, 'CalinskiHarabasz')
5. 实际案例:客户细分
5.1 数据准备与探索
假设我们有客户消费数据:
matlab复制% 加载并预处理数据
data = readtable('customer_data.csv');
X = [data.AnnualIncome, data.SpendingScore];
X = normalize(X); % 标准化数据
figure
plot(X(:,1), X(:,2), 'k.');
xlabel('年收入(标准化)');
ylabel('消费分数(标准化)');
5.2 确定最佳簇数
matlab复制% 使用轮廓系数确定k
klist = 2:8;
silh = zeros(size(klist));
for i = 1:length(klist)
k = klist(i);
idx = kmeans(X, k);
silh(i) = mean(silhouette(X, idx));
end
[~, bestK] = max(silh);
bestK = klist(bestK);
5.3 最终聚类与可视化
matlab复制% 执行聚类并可视化
[idx, C] = kmeans(X, bestK, 'Replicates', 10);
colors = hsv(bestK);
figure
hold on
for i = 1:bestK
scatter(X(idx==i,1), X(idx==i,2), 36, colors(i,:), 'filled');
end
plot(C(:,1), C(:,2), 'kx', 'MarkerSize', 15, 'LineWidth', 3);
legend('Cluster 1', 'Cluster 2', 'Cluster 3', 'Centroids');
xlabel('年收入(标准化)');
ylabel('消费分数(标准化)');
title('客户细分结果');
6. 常见问题与解决方案
6.1 空簇问题
当簇失去所有成员时,处理方式:
- 重新分配最远的点到空簇('singleton')
- 移除空簇('drop')
- 报错终止('error')
建议设置:
matlab复制[idx, C] = kmeans(X, k, 'EmptyAction', 'singleton');
6.2 局部最优问题
通过多次随机初始化缓解:
matlab复制[idx, C, sumd] = kmeans(X, k, 'Replicates', 10);
[~, bestIdx] = min(sumd); % 选择最佳结果
6.3 数据标准化的重要性
不同量纲的特征会扭曲距离计算,必须标准化:
matlab复制X = normalize(X); % Z-score标准化
% 或
X = rescale(X, 0, 1); % 归一化到[0,1]
7. 与其他聚类算法比较
| 算法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| K-Means | 简单高效,线性复杂度 | 需指定k,对异常值敏感 | 球形簇,中等规模数据 |
| DBSCAN | 自动确定簇数,抗噪声 | 对参数敏感,高维效果差 | 任意形状簇,噪声数据 |
| 层次聚类 | 可视化好(树状图) | 计算复杂度高 | 小数据集,需要层次结构 |
| GMM | 概率化输出,更灵活 | 计算复杂,可能过拟合 | 非球形簇,概率需求 |
在实际项目中,我通常会先用K-Means快速获得基线结果,再根据需求尝试更复杂的算法。对于超参数调优,网格搜索配合轮廓系数是不错的选择。
