MATLAB实现二分K-means报逻辑索引越界错误 如何解决
MATLAB运行K-means聚类时报错:
The logical indices in position 1 contain a true value outside of the array bounds,即位置1的逻辑索引在数组边界外存在真值,属于数组索引越界类错误。
报错核心诱因
你遇到的逻辑索引越界问题,根源是代码的聚类结果变量维护逻辑完全不符合二分K-means的实现要求,具体问题点:
- 每次拆分簇时,直接用拆分小簇生成的
idx/C/sumd覆盖了全数据集对应的全局聚类变量。新生成的idx长度仅等于被拆分的那个簇的样本量,远小于原数据集X的总行数,下一轮循环用这个短长度的逻辑数组去索引全量X时,一旦逻辑值出现的位置超过短数组对应到原数组的长度范围,就会触发边界外真值的报错。 - 没有做聚类结果的全局更新:二分K-means要求每次拆分SSE(即
sumd存储的簇内平方和)最大的簇为2个子簇后,要把2个新子簇的标签、质心、SSE更新回全局聚类结果中,总簇数逐轮+1直到达到目标值。原代码没有做这个全局更新步骤,相当于每轮循环都在上一轮拆分出的小数据集上重复聚类,数据规模逐轮缩小,和全局变量的维度差越来越大,必然触发索引错误。
你之前推测的“没有先将所有数据合并为单个簇”不是核心原因,初始化时全量数据本身就是初始单个簇,问题出在拆分后的结果同步逻辑。
修复代码
修复后完全符合二分K-means逻辑,可直接运行:
X = rand(1482,74); nCluster = 12; % 初始化:第一次将全量数据拆为2个簇 global_idx = kmeans(X,2); k_current = 2; % 预分配质心、簇内平方和存储 global_C = zeros(nCluster, size(X,2)); global_sumd = zeros(nCluster,1); % 填充初始2个簇的质心和SSE for i = 1:k_current cluster_sample = X(global_idx==i,:); global_C(i,:) = mean(cluster_sample,1); global_sumd(i) = sum(pdist2(cluster_sample, global_C(i,:)).^2); end % 逐轮拆分直到达到目标簇数 for pp = 3:nCluster % 找到当前SSE最大的簇(即最需要拆分的簇) [~, split_target_id] = max(global_sumd(1:k_current)); % 取出待拆分簇的所有样本 split_samples = X(global_idx == split_target_id, :); % 对目标簇做2分聚类 [sub_idx, sub_C, sub_sumd] = kmeans(split_samples, 2); % 更新全局聚类结果:将被拆分的簇替换为第一个子簇 global_C(split_target_id,:) = sub_C(1,:); global_sumd(split_target_id) = sub_sumd(1); % 第二个子簇作为新的簇追加到全局结果中 new_cluster_id = k_current + 1; global_C(new_cluster_id,:) = sub_C(2,:); global_sumd(new_cluster_id) = sub_sumd(2); % 更新全局样本标签:原属于待拆分簇的样本,按子聚类结果分配标签 target_sample_pos = find(global_idx == split_target_id); global_idx(target_sample_pos(sub_idx==2)) = new_cluster_id; % 当前总簇数+1 k_current = k_current + 1; end % 最终输出结果:idx为样本聚类标签,C为质心,sumd为各簇SSE [idx, C, sumd] = deal(global_idx, global_C(1:k_current,:), global_sumd(1:k_current));
关键修复点说明
- 全程单独维护全局维度的
global_idx/global_C/global_sumd变量,所有索引操作始终和原数据集X的维度匹配,从根源避免逻辑索引长度不匹配导致的越界问题 - 严格按照二分K-means的标准流程更新聚类结果:每轮仅拆分SSE最大的簇,拆分后同步更新全局标签、质心、簇内平方和,总簇数逐轮递增直到达到设定值
- 修复了原代码直接用小簇聚类结果覆盖全量结果的逻辑错误,聚类结果符合二分K-means的输出要求
内容的提问来源于stack exchange,提问作者Emanuele Gandolfi
相关产品推荐
相关产品推荐

