ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

模糊聚类分析从原理到实践:FCM与MATLAB工具箱全解析

模糊聚类分析从原理到实践:FCM与MATLAB工具箱全解析 简介面向需要做模糊聚类分析的MATLAB研究者与工程师这套工具集以经典的模糊C均值FCM算法为核心同时提供GK、K-medoid等聚类实现以及隶属度矩阵、聚类有效性指数、参数调节和可视化等配套功能可帮助用户快速搭建从数据预处理到聚类结果评估的完整分析链路。压缩包共48个文件以40个M函数文件为主包含聚类算法、主成分分析、标准化与多种演示脚本另有PDF说明文档、示例数据mat/wk1和若干说明文本总体积仅2.01MB调用起来非常轻量。已有1506人学习。下载后既能运行现成聚类样例也能借助有效性评估与投影工具完成聚类数选择、质量度量及二维/三维可视化对图像分割、模式识别、用户分群等实际场景具有很好的参考价值也方便在MATLAB环境中二次开发和算法自定义。1. 聚类分析工具箱 FuzzyClusteringToolbox 到底解决了什么问题聚类分析里最容易被忽略的是一个样本并不总该被逼着只属于某个类。K-means 把每个点硬性划给最近的聚类中心落在两堆中间的边界样本被强行推到一侧后续统计也跟着走样。FuzzyClusteringToolbox 是 MATLAB 生态里的聚类分析工具箱核心思路是用隶属度矩阵把属于哪一类换成每一类是几分像把类间重叠保留下来。图像分割、客户分群、基因表达数据探索里它比硬聚类多一层可解释信息边界样本和重叠区域能直接看见。下面顺着 FCM 讲到 GK、GG 变体从原理到调用代码、参数设置和排错把 MATLAB 聚类分析工具箱的常见套路一次讲清。2. 聚类分析工具箱的核心从隶属度矩阵理解 FCM2.1 硬聚类与模糊聚类的本质区别K-means 这类硬聚类算法内部维护一个划分矩阵 U第 j 个样本对第 i 个聚类的隶属度 u_ij 只取 0 或 1。每个样本必须把全部权重投给某一个中心即使它恰好躺在两个中心的中间。这种二值决策在数据分离度好的时候没有大问题一旦类别之间存在天然重叠硬划分就会制造人为边界类间距离被高估。模糊聚类把 u_ij 放宽成 [0,1] 里的连续实数保留一个约束对每个样本 j所有聚类上的隶属度之和等于 1。数学上这就是一个单纯形约束物理含义是样本的总量被按比例分配到各个类别上。重叠区里的点隶属度可能是 0.42 和 0.58而不是 0 和 1这个 0.42 携带的信息在客户分群、医学图像分割里很有用可以直接当作归属强度使用。FuzzyClusteringToolbox 里所有算法的输出都围绕这个模糊划分矩阵展开所以先把这个矩阵定义清楚后面看每个函数返回什么才不会懵。2.2 FCM 的目标函数与迭代逻辑FCMFuzzy C-Means模糊C均值是这套工具箱的基本款。它要最小化的目标函数如下J_m sum_i sum_j (u_ij^m) * ||x_j - v_i||^2目标函数里每一对 (i,j) 的损失是距离平方乘以隶属度的 m 次方。m 是模糊指数控制隶属度在迭代中的模糊程度后面单独讲。对这个式子做拉格朗日求解可以得到两个迭代公式给定聚类中心算隶属度给定隶属度算中心。聚类中心的更新只依赖隶属度和样本本身v_i sum_j (u_ij^m * x_j) / sum_j (u_ij^m)隶属度更新则依赖所有聚类中心的相对距离u_ij 1 / sum_k ( ||x_j - v_i|| / ||x_j - v_k|| )^(2/(m-1))整个 FCM 是一个交替最小化的迭代过程随机初始化隶属度矩阵 U或者先初始化聚类中心 V用当前 U 按公式计算新的 V用新的 V 按公式更新 U比较两轮之间的目标函数值变化小于容差就停止。FuzzyClusteringToolbox 的 fcm 函数默认就是这么迭代的它返回的 objFcn 就是你在命令行能看到的每一轮 J 值。如果发现目标函数在收敛前跳来跳去多半是初始 U 给得太差而不是算法本身有问题。2.3 FuzzyClusteringToolbox 的算法家族与适用边界工具箱里不止 FCM 一个算法。我一般会根据数据形状选函数算法全称原型假设适用场景FCMFuzzy C-Means球形簇、尺寸接近基础分群、图像像素聚类GKGustafson-Kessel椭球形簇被旋转压缩的高维特征GGGath-Geva异方差、密度不一存在大小差异很大的簇FCM 用的是普通欧氏距离所有簇共享同一个球状原型假设。数据每个类近似圆形时它又快又稳但遇到长条形、被压扁的簇它会用一个球去包一个椭圆边界切得很难看。GK 为每个簇独立估计一个协方差矩阵用马氏距离代替欧氏距离能拟合不同方向的椭球。GG 在 GK 基础上再加入先验概率项对密度差异明显的簇更友好代价是对初始值更敏感。选型时我会先做主成分分析或直接画二维投影投影后簇边缘是圆的就用 FCM明显有轴向拉长的直接上 GK簇大小差一个数量级以上再试 GG。它们共享同一套调用规范换算法只改函数名这也就是工具箱比单独脚本方便的地方。3. 在 MATLAB 里装好工具箱并跑通第一个 FCM 样例3.1 下载、路径配置与版本兼容FuzzyClusteringToolbox 通常是第三方发布的纯 MATLAB 实现没有编译产物所以安装本质上是把一组 .m 文件放进 MATLAB 搜索路径。常见的坑有两个一是只解压不配置路径直接运行报未定义函数二是和 MATLAB 官方 Fuzzy Logic Toolbox 自带的 fcm 重名路径顺序不对时调用了错误的版本。安装步骤从 MathWorks File Exchange 或项目主页下载 zip 压缩包并解压在 MATLAB 命令行执行 addpath(genpath(解压后的根目录路径))执行 savepath 保存设置运行 which fcm、which gk 确认指向的是你解压的那个目录。addpath 只加指定目录genpath 会递归把子目录全部加入两者配合才能加载完整工具箱。savepath 没有提示的话一般就是成功但要注意换电脑或换 MATLAB 版本时路径失效需要重新配置。这类第三方工具箱通常按一个算法一个 .m 文件组织名称大致如下文件/函数作用fcm模糊C均值主函数gkGustafson-Kessel 椭球形簇算法ggGath-Geva 算法3.2 生成带重叠的二维测试数据为了验证聚类分析工具箱的效果最好有一份能看到重叠的数据。手工构造两份高斯分布再在两簇之间撒一些边界点rng(42); % 固定随机种子保证结果可复现 n1 150; n2 150; X [mvnrnd([0 0], 0.5*eye(2), n1); % 第一簇中心 [0 0] mvnrnd([2 2], 0.5*eye(2), n2)]; % 第二簇中心 [2 2] X [X; randn(40,2)*0.8 [1 1]]; % 在两簇之间撒 40 个边界点这段数据是两个标准差 0.5、中心距约 2.8 的高斯簇按三西格马估算边界已有大量重叠再加 40 个夹在两簇中间的点专门制造模糊归属的情况。rng 的作用是让随机数可复现否则每次跑实验边界点位置都不同调参数时很难判断结果是参数引起的还是数据引起的。mvnrnd 是 MATLAB 生成多元正态分布的标准函数第一个参数是均值向量第二个是协方差矩阵第三个是样本数。3.3 最小可运行代码与返回结构配好路径、数据也造好了直接调工具箱的 fcm 函数options [2 100 1e-5 1]; % [模糊指数m, 最大迭代次数, 容差, 是否显示] [center, U, objFcn] fcm(X, 2, options); [~, label] max(U, [], 1); % 把隶属度矩阵转成硬标签 gscatter(X(:,1), X(:,2), label); hold on; plot(center(:,1), center(:,2), kx, MarkerSize, 12, LineWidth, 2);这是 FuzzyClusteringToolbox 里 FCM 最常见的调用格式返回三个值center 是 c×d 的聚类中心矩阵U 是 c×n 的隶属度矩阵objFcn 是每次迭代的目标函数值历史。options 里第一个数字是模糊指数 m2第二个是最大迭代 100 次第三个是收敛容差 1e-5最后的 1 表示在命令行实时打印目标函数调试时开着批量跑建议改成 0。max(U,[],1) 会取每个样本隶属度最大的那一行拿到最终的硬聚类标签。gscatter 按标签着色黑色叉号画出聚类中心。如果数据分布和直观感受一致说明调用成功如果出现一整类是空的多半是初始化或数据标准化的问题后面的排错部分会讲。4. 参数怎么调聚类数 c、模糊指数 m 和终止条件的实战设置4.1 聚类数 c领域经验先行有效性指标兜底FCM 需要预先给定 c它不会自己学习。c 的经验上限常取 sqrt(n)下限是 2。在客户分群、图像分割这类场景里我建议先看业务标签域一个客户池分 3 组业务上有解释就不要为了凑指标分成 7 组。SPSS 里做聚类分析时也是先跑层次聚类看谱系图再用 K-means 精修这个思路可以拿过来复用。指标可以被用作兜底常用的聚类有效性指标指标做法方向划分系数 PC(1/n)ΣΣ u_ij^2越大越好分类熵 CE-(1/n)ΣΣ u_ij log u_ij越小越好Xie-Beni XB紧致度 / 分离度越小越好这些指标直接基于隶属度矩阵计算不需要额外知道真实标签正好和 FuzzyClusteringToolbox 的输出互补。把 c 从 2 扫到 maxC分别记录三个指标。注意 PC 随 c 增大整体有下降趋势CE 随 c 增大有上升趋势不能只看全局最优要看曲线拐点再配合 XB 这类带分离项的指标交叉验证。4.2 模糊指数 m行为变化比默认值重要m 是 FCM 特有的参数决定了隶属度分布的锐利程度。当 m 趋近 1 时隶属度更新公式里的指数变得很大u 会迅速逼近 0 或 1整个算法几乎变成 K-means当 m 过大比如 4 以上所有样本对每个簇的隶属度都趋近 1/c划分失去意义。文献里最常用的是 m2可接受区间一般取 [1.5, 2.5]。用一小段循环可以直观看到 m 的影响for m 1.2:0.3:3.0 opt [m 100 1e-5 0]; [~, U, ~] fcm(X, 2, opt); fprintf(m%.1f 平均最大隶属度%.3f\n, m, mean(max(U, [], 1))); end代码里只改了 options 的第一个位置每轮用同一个数据 X 调用 fcm然后统计每个样本最大隶属度的平均值。这个值越接近 1说明每个样本都被某个簇强烈主导分界锐利越接近 0.5说明大量样本夹在两簇之间。如果数据集本身重叠很大m2 时这个均值可能在 0.7 左右这不是 bug而是数据属性。此时可以考虑把 m 降到 1.5 左右让类别边界更清晰但代价是模糊聚类的软归属优势变少需要根据下游任务取舍。m 还有一个容易被忽略的作用m 变大后目标函数地形更平滑迭代收敛变慢FCM 更容易跑满 maxiter。调参时如果发现迭代次数总撞上限第一步不是增大迭代次数而是检查 m 是不是设得过大。4.3 初始化与终止条件两个默认参数的坑options 四个位置的完整含义需要再抠一遍第一个是 m第二个是最大迭代次数第三个是相邻两轮目标函数差值的绝对值下限第四个是显示开关。工具箱里实现不一有的把第三个当成目标函数变化率失败时看 objFcn 是否持续不降即可。初始化是 FCM 最大的坑。随机初始化 U 会把算法带到不同的局部最优解尤其在簇重叠、维度高的数据上两次运行可能给出完全不同的聚类中心。常见做法是把同一组参数跑 5 到 10 次记录每次最终的 objFcn 值取最小那次的 center 和 Urng(1); bestJ inf; for r 1:8 [c_tmp, U_tmp, objFcn] fcm(Xn, 3, options); if objFcn(end) bestJ bestJ objFcn(end); center c_tmp; U U_tmp; end end这里用循环控制重复次数每次重新随机初始化但外层固定了 rng(1)保证实验可复现。比较时用 objFcn(end)它是最后一次迭代的目标函数值越小代表收敛到的解越好。聚类分析工具箱没有内置多次取最优的统一接口时自己写这一小段比换初始化方式更稳定。终止条件在时间敏感任务里值得调整。容差 1e-5 是平衡值放到 1e-3 会少迭代很多轮但中心位置可能还没稳定收紧到 1e-7 以上在数据量超过十万时会有明显等待。大样本场景我一般把最大迭代限制在 200容差 1e-4 起步先看 objFcn 曲线的尾部是否平坦再决定是否加严。5. 从隶属度矩阵到硬标签FCM 输出解读与高频排错5.1 先看懂 U、center 和 objFcn 分别写了什么实际项目中容易让人停下的不是报错而是没报错但不知道结果对不对。fcm 返回的三个变量里center 每行是一个聚类中心维度等于原始数据的特征数U 的每一列是同一个样本在全部 c 个簇上的隶属度列和为 1objFcn 是长度等于实际迭代次数的列向量。诊断聚类结果是否可用的第一步是看隶属度分布conf max(U, [], 1); % 每个样本对最终簇的最大隶属度 histogram(conf, 20); title(每个样本的最大隶属度分布);如果直方图大量集中在 0.4~0.7说明很多样本在两个簇之间摇摆当前 c 或 m 没有把数据结构带出来如果集中在 0.9 以上划分清晰但也要担心是不是 m 设得太接近 1导致模糊聚类失去软归属的意义。实际操作中我会把这个分布保存下来和业务标签对一下低置信区的样本单独看。5.2 从隶属度矩阵导出硬标签和边界样本聚类分析任务的交付物往往需要每个样本属于哪一类用 max 就能把 U 压成硬标签。但软输出还多给了一个东西置信度。两分类里某个样本的隶属度为 [0.51 0.49] 和 [0.95 0.05]硬标签都是第一类业务含义却完全不同。下面的代码可以把边界样本挑出来[hardLabel, conf] max(U, [], 1); boundaryIdx find(conf 0.6); % 归属强度不足 0.6 的样本 mine mean(U(:, boundaryIdx), 2); % 它们在每个簇上的平均隶属度hardLabel 是每个样本的最终类别编号conf 是对应置信度。boundaryIdx 筛选出置信度低于 0.6 的样本这些样本在后续建模里往往值得单独处理要么重新采集特征要么在标注时交给人工确认而不是跟着二值标签走。mean 计算这些边界样本在 c 个簇上的平均隶属度能看出它们是两簇分不清还是三簇都有份。5.3 排错表四个最常见的模糊聚类问题把 FuzzyClusteringToolbox 用起来之后下面几个问题出现频率最高现象直接原因处理输出出现 NaN数据含有 NaN/Inf或某列方差为 0先 fillmissing再 zscore 标准化去掉常量列某个簇没有样本随机初始化进入局部最优多次初始化取 objFcn 最小的解多次运行结果差异很大隶属度初始化没有固定随机种子外层固定 rng并比较目标函数值设置 m1 报错更新公式分母出现 1/(m-1)除零m 保持大于 1建议从 1.5 起还要补一个数据层面的坑FCM 的距离计算对特征尺度敏感。特征一个量纲是身高一个量纲是收入欧氏距离基本被收入主导。聚类分析工具箱不会自动标准化数据所以数据进工具箱之前先做一次 zscore 是常规操作先标准化再聚类这一点在 SPSS 聚类分析里同样成立。Xn (X - mean(X, 1)) ./ std(X, 0, 1); % 逐列零均值单位方差std(X,0,1) 中第二个参数 0 表示计算标准差时除以 n-1也就是样本标准差第三个参数 1 表示沿列方向操作每一列各自标准化。对含零方差列的数据要谨慎全零列会在标准化时出现除零因此标准化的前提是先检查每列的方差。6. 用 Xie-Beni 指标自动扫描聚类数 c6.1 在工具箱输出上直接算 XB 指标Xie-Beni 指标衡量类内紧致、类间分离分子是所有样本到所属中心的模糊加权距离总和分母是最近两个聚类中心距离的平方乘以样本数。FuzzyClusteringToolbox 跑完一次 fcm 后center、U 和 objFcn 都在工作区XB 只需要用这三样东西算不需要重新迭代。function xb xiebeni(X, U, V, m) d pdist2(V, X); % 聚类中心到每个样本的距离 num sum(sum((U .^ m) .* (d .^ 2), 2), 1); sep min(pdist(V)); % 最近两个中心的距离 xb num / (size(X, 1) * sep^2); endpdist2(V, X) 得到 c×n 的距离矩阵元素 d(i,j) 是第 i 个中心到第 j 个样本的欧氏距离。U.^m 再乘 d.^2 得到每个样本在每个簇上的模糊损失连加两次得到分子。pdist(V) 计算聚类中心两两距离min 取最小的一对sep 越小说明有两个中心挤在一起XB 会变大。分母乘的 size(X,1) 是样本数把样本量对指标的影响消掉。6.2 扫描 c 并自动挑选最优簇数有了这个函数就把 c 从 2 扫到上限每个 c 跑一次 fcm记录 XB 值options [2 100 1e-5 0]; cRange 2:8; xbVal zeros(size(cRange)); for t 1:numel(cRange) c cRange(t); [V, U, objFcn] fcm(Xn, c, options); xbVal(t) xiebeni(Xn, U, V, options(1)); fprintf(c%d, XB%.4f\n, c, xbVal(t)); end [~, bestC] min(xbVal);这段代码里 options 的第一个位置是 m它和 xiebeni 函数里的 m 要一致否则分子计算出来和聚类过程不匹配。min 直接取最小的 c 作为推荐值但在真实任务里不要机械看最小值XB 随 c 增加经常出现先降后升再降的多段曲线此时选第一个明显拐点比选全局最小更符合业务直觉。把这段循环封装成一个文件后每次拿到新数据只需要改 Xn 和 cRange 两个量聚类数选择这一步就不再靠人工拍脑袋反复折腾。本文还有配套的精品资源点击获取
返回列表