MATLAB实现鸢尾花数据集的K-means聚类分析

MATLAB实现鸢尾花数据集的K-means聚类分析

1. 鸢尾花数据集与K-means聚类概述

鸢尾花数据集(Iris Dataset)是模式识别领域最经典的入门数据集之一,由统计学家Ronald Fisher在1936年首次引入。这个数据集包含150个样本,每个样本代表一朵鸢尾花的测量数据,涵盖三个品种(Setosa、Versicolor和Virginica),每个样本有四个特征:萼片长度、萼片宽度、花瓣长度和花瓣宽度(单位均为厘米)。数据集的简洁性和明确的分类边界使其成为机器学习算法测试的理想选择。

K-means算法作为最基础的聚类方法,其核心思想是通过迭代计算将数据划分为K个簇,使得同一簇内的数据点尽可能相似,而不同簇间的数据点差异明显。算法流程通常包括四个步骤:初始化中心点、分配数据点到最近中心、重新计算中心点位置、重复迭代直至收敛。在MATLAB环境下实现该算法,既能验证数据特征,又能直观展示多维数据的聚类过程。

注意:鸢尾花数据集虽然结构简单,但三个品种中Versicolor和Virginica存在特征重叠,这为验证聚类算法对非线性可分数据的处理能力提供了天然测试场景。

2. MATLAB环境准备与数据预处理

2.1 数据集加载与探索

MATLAB自带了鸢尾花数据集,可通过load fisheriris命令直接载入工作区。该命令会生成两个变量:meas(150x4的测量数据矩阵)和species(150x1的品种标签元胞数组)。建议在正式分析前先进行基础数据探查:

% 查看数据维度 disp(size(meas)); % 应显示[150 4] disp(unique(species)); % 显示三个品种名称 % 绘制特征散点图矩阵 gplotmatrix(meas,[],species,'rgb','osd',[],'on','',... {'SepalL','SepalW','PetalL','PetalW'});

2.2 数据标准化处理

由于不同特征的量纲和数值范围差异(萼片宽度通常在2-4cm,而花瓣长度可达1-7cm),必须进行标准化处理以避免量纲对距离计算的影响。最常用的方法是Z-score标准化:

normalized_meas = zscore(meas); % 均值归零,标准差归一 % 验证标准化效果 disp([mean(normalized_meas); std(normalized_meas)]);

实操心得:对于存在明显离群点的数据集,建议改用Robust Z-score(基于中位数和MAD)或最大最小值归一化,但鸢尾花数据集质量较高,常规Z-score已足够。

3. K-means算法实现细节

3.1 MATLAB内置函数参数解析

MATLAB的kmeans函数提供丰富的可配置参数,核心调用格式为:

[idx, C, sumd, D] = kmeans(data, k, 'Name',Value,...)

关键参数说明:

  • 'Distance':距离度量(默认'sqeuclidean'欧氏距离平方)
  • 'Replicates':随机初始化的重复次数(建议≥10)
  • 'MaxIter':最大迭代次数(默认100)
  • 'Options':设置显示输出等选项

典型调用示例:

opts = statset('Display','final'); [idx, centroids] = kmeans(normalized_meas, 3, 'Distance','sqeuclidean',... 'Replicates',20, 'Options',opts);

3.2 手写K-means实现

理解算法本质的最佳方式是手动实现。以下是精简版实现代码:

function [idx, C] = my_kmeans(X, k, max_iter) [n, d] = size(X); % 随机初始化中心点 C = X(randperm(n, k), :); idx = zeros(n, 1); for iter = 1:max_iter % 分配阶段:计算每个点到中心的距离 dists = pdist2(X, C, 'squaredeuclidean'); [~, new_idx] = min(dists, [], 2); % 检查收敛 if isequal(idx, new_idx) break; end idx = new_idx; % 更新阶段:重新计算中心点 for i = 1:k C(i,:) = mean(X(idx==i, :), 1); end end end

注意事项:实际应用中应添加空簇检测和处理机制,避免某些中心点失去所有归属数据点的情况。

4. 聚类结果评估与可视化

4.1 内部评估指标

虽然鸢尾花数据集有真实标签,但作为无监督学习,我们仍需掌握无标签评估方法:

% 轮廓系数计算 silhouette_values = silhouette(normalized_meas, idx); mean_sil = mean(silhouette_values); % 簇内平方和(WCSS) total_wcss = sum(sumd); between_ss = sum(pdist2(C, mean(normalized_meas)).^2) * n; ratio = between_ss / (total_wcss + between_ss);

4.2 降维可视化

由于原始数据是四维的,需要通过降维技术展示聚类效果:

% PCA降维 [coeff, score] = pca(normalized_meas); figure; gscatter(score(:,1), score(:,2), idx, 'rgb','osd'); title('PCA投影下的聚类结果'); % 平行坐标图 figure; parallelcoords(normalized_meas, 'Group',species,... 'Quantile',0.25,'Labels',{'SepalL','SepalW','PetalL','PetalW'});

4.3 与真实标签对比

虽然聚类是无监督过程,但通过与真实标签对比可以验证算法有效性:

conf_mat = confusionmat(grp2idx(species), idx); disp(conf_mat); % 调整Rand指数 ari = adjustedRandIndex(grp2idx(species), idx);

5. 工程实践中的关键问题

5.1 K值选择策略

鸢尾花数据集已知K=3,但实际应用中K常未知,常用选择方法:

  1. 肘部法则:绘制不同K值的WCSS曲线
wcss = zeros(1,5); for k = 1:5 [~,~,sumd] = kmeans(normalized_meas, k); wcss(k) = sum(sumd); end plot(1:5, wcss, '-o'); xlabel('Number of clusters'); ylabel('Within-cluster sum of squares');
  1. Gap统计量:比较实际数据与参考分布的WCSS差异
eva = evalclusters(normalized_meas,'kmeans','gap','KList',1:5); plot(eva);

5.2 高维数据挑战

当特征维度增加时,K-means可能面临"维度灾难":

  • 距离度量失效:高维空间中所有点对距离趋于相似
  • 解决方案:特征选择(如基于方差过滤)、维度缩减(PCA/t-SNE)、改用子空间聚类

5.3 算法优化技巧

  1. K-means++初始化:MATLAB默认采用此方法,显著改善收敛速度
  2. Mini-batch K-means:大数据集时可使用kmeans函数的'onlinephase'选项
  3. 并行计算:设置'Options',statset('UseParallel',true)

6. 完整实现案例

以下是一个端到端的分析流程示例:

%% 环境准备 clear; clc; load fisheriris; normalized_meas = zscore(meas); %% 确定最佳K值 eva = evalclusters(normalized_meas,'kmeans','silhouette','KList',1:5); optimal_k = eva.OptimalK; % 通常应得3 %% 执行聚类 rng(123); % 设置随机种子保证可重复性 opts = statset('Display','final','UseParallel',true); [idx, C, sumd] = kmeans(normalized_meas, optimal_k,... 'Replicates',20,'Options',opts); %% 结果评估 % 轮廓系数 figure; silhouette(normalized_meas, idx); title(sprintf('平均轮廓系数: %.3f',mean(silhouette(normalized_meas, idx)))); % 与真实标签对比 species_num = grp2idx(species); conf_mat = confusionmat(species_num, idx); disp('混淆矩阵:'); disp(conf_mat); %% 可视化 % PCA投影 [~,score] = pca(normalized_meas); figure; subplot(1,2,1); gscatter(score(:,1), score(:,2), species_num, 'rgb','osd'); title('真实分类'); subplot(1,2,2); gscatter(score(:,1), score(:,2), idx, 'rgb','osd'); title('聚类结果'); % 平行坐标图 figure; subplot(2,1,1); parallelcoords(normalized_meas, 'Group',species); title('真实分类特征分布'); subplot(2,1,2); parallelcoords(normalized_meas, 'Group',idx); title('聚类结果特征分布');

7. 常见问题与解决方案

7.1 结果不稳定

  • 现象:每次运行得到不同聚类结果
  • 原因:随机初始化敏感
  • 解决:增加Replicates参数(建议≥10),使用rng固定随机种子

7.2 空簇出现

  • 现象:某些簇没有分配到任何数据点
  • 原因:初始化中心点不合适
  • 解决:实现时添加中心点重置逻辑,或改用K-means++

7.3 特征重要性分析

  • 需求:了解各特征对聚类结果的贡献
  • 方法
% 通过特征权重分析 feature_importance = zeros(1,4); for i = 1:4 reduced_data = normalized_meas; reduced_data(:,i) = randn(size(normalized_meas,1),1); % 随机打乱该特征 [~,~,sumd] = kmeans(reduced_data, 3); feature_importance(i) = sum(sumd); end [~,imp_order] = sort(feature_importance); disp('特征重要性排序:'); disp({'SepalL','SepalW','PetalL','PetalW'}(imp_order));

7.4 大数据集处理

当数据量超过内存容量时:

  1. 使用datastore分批读取
  2. 采用Mini-batch K-means:
opts = statset('UseParallel',true); [idx, C] = kmeans(normalized_meas, 3, ... 'Options',opts, 'OnlinePhase','on');

8. 扩展应用与进阶方向

8.1 半监督学习结合

当部分数据有标签时:

% 假设前50个样本已知标签(Setosa) constrained_idx = [ones(50,1); idx(51:end)]; constrained_C = [mean(normalized_meas(1:50,:)); C(2:3,:)];

8.2 核K-means

通过核函数处理非线性可分数据:

% 使用高斯核 K = exp(-pdist2(normalized_meas,normalized_meas).^2/(2*1^2)); [idx,~] = kmeans(K, 3, 'Distance','correlation');

8.3 与其他算法对比

% 层次聚类 Z = linkage(normalized_meas,'ward'); hier_idx = cluster(Z,'maxclust',3); % GMM聚类 gmm = fitgmdist(normalized_meas,3); gmm_idx = cluster(gmm,normalized_meas); % 结果对比 disp(['K-means ARI: ',num2str(adjustedRandIndex(species_num,idx))]); disp(['层次聚类 ARI: ',num2str(adjustedRandIndex(species_num,hier_idx))]); disp(['GMM ARI: ',num2str(adjustedRandIndex(species_num,gmm_idx))]);

在实际项目中,K-means因其简单高效常作为基线模型,但需要根据数据特性决定是否采用更复杂的聚类算法。鸢尾花数据集的实践价值不仅在于掌握基础算法,更在于培养对聚类问题系统化的分析思路——从数据理解、预处理、算法实现到结果评估的全流程能力。