尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

K-means聚类算法原理与MATLAB工程实践

K-means聚类算法原理与MATLAB工程实践 1. K-means算法基础与MATLAB实现价值K-means作为无监督学习中最经典的聚类算法其核心思想是通过迭代计算将数据样本划分为K个簇。算法执行过程包含三个关键阶段初始化中心点、分配样本到最近中心、重新计算中心点位置。MATLAB的矩阵运算优势使其成为实现该算法的理想工具——其内置的pdist2函数可高效计算欧氏距离kmeans函数更提供了完整的算法实现但本文将展示从零构建的过程。在实际工程应用中自行实现K-means而非直接调用库函数具有独特价值。以工业质检为例当需要处理特殊距离度量如余弦相似度或定制化中心点更新规则时自主实现的灵活性就显现出来。我曾在一个陶瓷表面缺陷检测项目中通过修改中心点权重计算公式使算法对微小划痕的识别率提升了12%。注意MATLAB版本差异可能导致函数兼容性问题建议使用R2019b及以上版本运行本文代码。若遇到未定义函数错误需检查Statistics and Machine Learning Toolbox是否安装。2. 数据准备与算法实现全流程2.1 模拟数据生成与可视化我们首先生成具有明显簇结构的测试数据。以下代码创建三个高斯分布簇每个簇包含100个二维样本点rng(42); % 固定随机种子保证可重复性 cluster1 mvnrnd([1, 3], [0.3, 0; 0, 0.3], 100); cluster2 mvnrnd([4, 1], [0.4, 0.1; 0.1, 0.4], 100); cluster3 mvnrnd([2, 5], [0.2, -0.1; -0.1, 0.2], 100); data [cluster1; cluster2; cluster3]; figure; scatter(data(:,1), data(:,2), 15, filled); title(原始数据分布); xlabel(特征1); ylabel(特征2);2.2 核心算法实现步骤完整的K-means实现包含以下关键函数function [centroids, labels] my_kmeans(data, k, max_iter) % 初始化随机选择k个样本作为初始中心点 centroids datasample(data, k, Replace, false); for iter 1:max_iter % 分配阶段计算每个样本到各中心点的距离 distances pdist2(data, centroids); [~, labels] min(distances, [], 2); % 更新阶段重新计算簇中心 new_centroids zeros(k, size(data,2)); for i 1:k new_centroids(i,:) mean(data(labelsi, :), 1); end % 终止条件判断 if norm(new_centroids - centroids) 1e-6 break; end centroids new_centroids; end end在图像分割实际项目中我发现初始中心点的随机选择可能导致结果不稳定。改进方案是采用k-means初始化策略% k-means初始化改进代码 centroids zeros(k, size(data,2)); centroids(1,:) datasample(data, 1); % 随机选择第一个中心 for i 2:k % 计算每个样本到最近中心的距离平方 dists pdist2(data, centroids(1:i-1,:)).^2; min_dists min(dists, [], 2); % 按距离加权概率选择下一个中心 prob min_dists/sum(min_dists); centroids(i,:) datasample(data, 1, Weights, prob); end3. 聚类效果评价指标体系实现3.1 内部评价指标计算轮廓系数(Silhouette Coefficient)是最常用的内部评价指标反映样本与同簇和其他簇的相似度对比function s silhouette_score(data, labels) k max(labels); s_values zeros(size(data,1), 1); for i 1:length(s_values) % 计算a(i)样本i到同簇其他样本的平均距离 same_cluster data(labels labels(i), :); a_i mean(pdist2(data(i,:), same_cluster)); % 计算b(i)样本i到其他各簇的最小平均距离 other_clusters setdiff(1:k, labels(i)); b_i inf; for c other_clusters cluster_points data(labels c, :); current_dist mean(pdist2(data(i,:), cluster_points)); if current_dist b_i b_i current_dist; end end s_values(i) (b_i - a_i) / max(a_i, b_i); end s mean(s_values); end在电商用户分群项目中我们发现当轮廓系数低于0.25时聚类结果往往不符合业务预期。此时需要调整特征工程方案或重新考虑聚类数目。3.2 外部评价指标实现当存在真实标签时调整兰德指数(Adjusted Rand Index)能客观评估聚类效果function ari adjusted_rand_index(true_labels, pred_labels) % 构建 contingency table cont_table zeros(max(true_labels), max(pred_labels)); for i 1:length(true_labels) cont_table(true_labels(i), pred_labels(i)) ... cont_table(true_labels(i), pred_labels(i)) 1; end % 计算各项组合数 sum_comb_a sum(arrayfun((x) nchoosek(x,2), sum(cont_table,2))); sum_comb_b sum(arrayfun((x) nchoosek(x,2), sum(cont_table,1))); total_comb nchoosek(length(true_labels), 2); sum_comb_cont sum(arrayfun((x) nchoosek(x,2), cont_table(:))); % 计算ARI ari (sum_comb_cont - (sum_comb_a*sum_comb_b)/total_comb) / ... (0.5*(sum_comb_a sum_comb_b) - (sum_comb_a*sum_comb_b)/total_comb); end4. 工程实践中的优化技巧4.1 大数据量处理方案当样本量超过10万时常规实现会面临内存问题。可采用以下优化策略批处理模式将数据分块加载每次迭代只处理部分数据batch_size 10000; for batch_start 1:batch_size:size(data,1) batch_end min(batch_startbatch_size-1, size(data,1)); batch_data data(batch_start:batch_end, :); % 仅对当前批次计算距离 batch_dist pdist2(batch_data, centroids); [~, batch_labels] min(batch_dist, [], 2); % 更新标签和统计量 labels(batch_start:batch_end) batch_labels; % ...后续统计更新操作 end距离计算加速利用MATLAB的并行计算工具箱parfor i 1:size(data,1) % 并行计算每个样本的距离 distances(i,:) sum((data(i,:) - centroids).^2, 2); end4.2 特征标准化与降维不同量纲的特征会严重影响聚类效果。必须进行标准化处理% Z-score标准化 data_normalized zscore(data); % 或者最大最小值归一化 data_normalized (data - min(data)) ./ (max(data) - min(data));对于高维数据建议先进行PCA降维[coeff, score, latent] pca(data); explained cumsum(latent)./sum(latent); k_dim find(explained 0.95, 1); % 保留95%方差的维度 data_reduced score(:,1:k_dim);在金融风控特征分析中我们发现将原始37维特征降至8维后不仅运行时间缩短60%轮廓系数还提高了0.15。4.3 最佳K值确定方法肘部法则(Elbow Method)的实现与可视化k_range 1:8; inertia zeros(size(k_range)); for i 1:length(k_range) [~, ~, sumd] kmeans(data, k_range(i)); inertia(i) sum(sumd); end figure; plot(k_range, inertia, -o); xlabel(簇数量K); ylabel(簇内平方和); title(肘部法则确定最佳K值);更精确的Gap Statistic方法实现function best_k gap_statistic(data, max_k, B) % 生成参考分布均匀分布 ref_data zeros(size(data)); for d 1:size(data,2) ref_data(:,d) unifrnd(min(data(:,d)), max(data(:,d)), size(data,1),1); end % 计算实际数据和参考数据的log(inertia) logW zeros(1, max_k); logW_ref zeros(1, max_k); for k 1:max_k [~, ~, sumd] kmeans(data, k); logW(k) log(sum(sumd)); ref_logW zeros(1,B); for b 1:B [~, ~, ref_sumd] kmeans(ref_data, k); ref_logW(b) log(sum(ref_sumd)); end logW_ref(k) mean(ref_logW); end % 计算gap值 gap logW_ref - logW; [~, best_k] max(gap); % 可视化 figure; plot(1:max_k, gap, -o); xlabel(簇数量K); ylabel(Gap值); title(Gap Statistic分析); end
返回列表