首页 / 资讯中心 / 文章详情

FP-Growth关联规则挖掘MATLAB实战:从FP-Tree到稳定规则集

FP-Growth关联规则挖掘MATLAB实战:从FP-Tree到稳定规则集 ★ FEATURED ARTICLE
简介这份资源是面向数据挖掘初学者与MATLAB使用者的FP-Growth关联规则挖掘实现包聚焦交易数据中的频繁项集发现与规则提取。包内共8个文件以7个.m脚本和1个.mat数据集为主脚本分别承担主流程调度、FP树构建、幂集与子集计算、规则展示及树结构可视化等职责mydata数据集用于直接运行演示压缩包约5KB轻量易读。已有191人学习关注。读者可借此理解FP-Growth通过构建FP树减少数据扫描次数的核心思路掌握支持度阈值设定、条件模式基生成与递归挖掘的完整流程并可将代码作为基础扩展到市场篮子分析、网络行为分析等实际场景适合作为关联规则挖掘的入门实践与二次开发起点。1. 从一份 FP-Growth 关联规则挖掘压缩包说起它到底能跑出什么结果如果你手上有一批事务型数据——比如超市小票、用户行为日志、故障工单里的配件组合——想找出「买了 A 的人大概率也会买 B」这类规则那这份FP-Growth Assiciation Rule Mining.rar就是冲这个场景来的。它是一份 MATLAB 实现的关联规则挖掘资源包核心算法是 FP-Growth配套的还有从频繁项集到关联规则的完整流程。很多人第一次接触关联规则是从 Apriori 开始的但 Apriori 每轮都要扫全表数据量一上来就慢得让人想砸键盘FP-Growth 用一棵 FP-Tree 把数据集压缩进内存只需扫两遍数据库就能挖出频繁项集这就是它值得单独拆一份的原因。这份资源适合两类人一类是课程设计或毕设要做关联规则、但不想从零手写树的同学另一类是手里有真实交易数据、想快速验证规则有效性的从业者。下面我按「它是什么 → 怎么跑起来 → 参数怎么调 → 坑在哪」的顺序把这份包拆开讲透。2. FP-Tree 构建与频繁项集挖掘MATLAB 里那棵树是怎么长出来的2.1 为什么是 FP-Growth 而不是 Apriori先把选型理由说清楚不然调参的时候你都不知道自己在调什么。Apriori 的核心是「逐层生成候选集 反复扫描数据库验证支持度」假设有 1 万条事务、每条平均 10 个项候选集规模会随项数组合爆炸扫描次数等于最大频繁项集长度I/O 开销是它的死穴。FP-Growth 换了个思路第一遍扫描统计每个项的支持度丢掉低于最小支持度的项第二遍扫描把剩下的事务按支持度降序插入一棵前缀树也就是 FP-Tree。相同前缀的路径会共享节点数据集被压缩成树结构之后挖掘频繁项集只需要在这棵树上递归构造条件模式基不再碰原始数据库。这份 MATLAB 资源包的价值就在于它把这套流程完整落地了从数据读入、支持度统计、FP-Tree 节点结构定义到递归挖掘和规则生成是一条能直接跑的链路。你拿到手不用去纠结「树节点怎么存孩子指针」这种实现细节重点放在数据格式和参数上就行。2.2 数据准备事务数据的两种常见组织方式跑之前先看你的数据长什么样。关联规则挖掘的输入是事务集合每条事务是一个项集。MATLAB 里常见两种组织方式一种是元胞数组每个 cell 存一条事务的项名另一种是稀疏矩阵或 0/1 矩阵行是事务、列是项。这份包一般按元胞数组或字符矩阵读入具体看你拿到的脚本入口。假设你有一个transactions.mat里面变量trans是 1×N 的 cell每个元素是字符串数组% 载入事务数据trans 为 1xN cell每个 cell 是一条事务的项列表 load(transactions.mat); % 变量名按你实际文件改 % 检查前三条事务确认格式没问题 for i 1:3 disp(trans{i}); end % 统计事务总数和不同项的数量心里有个底 numTrans numel(trans); allItems unique([trans{:}]); fprintf(事务数: %d, 不同项数: %d\n, numTrans, numel(allItems));这段代码做三件事载入数据、抽样打印确认每条事务是字符串数组而不是嵌套 cell、统计规模。unique([trans{:}])把所有事务拼接后去重得到项的全集这个数字直接决定后面 FP-Tree 的宽度。如果这里报错说维度不一致八成是某些事务存成了数值、某些存成了字符串得先统一类型。2.3 最小支持度与最小置信度两个必须一起定的参数FP-Growth 挖掘频繁项集只受一个参数控制——最小支持度minSup。它有两种给法绝对计数或相对比例。相对比例更通用比如minSup 0.01表示出现频率低于 1% 的项集直接不要。这个值定高了规则太少定低了树爆炸、内存吃紧。规则生成阶段再加一个最小置信度minConf比如 0.6 表示「A 出现时 B 也出现的条件概率」至少 60% 才保留。这两个参数是联动的minSup决定频繁项集的规模minConf决定从这些项集里筛出多少条规则。% 设定最小支持度相对比例和最小置信度 minSup 0.02; % 2%数据量大就往上调规则太少就往下调 minConf 0.6; % 60%先跑一版看规则数量再微调 % 调用 FP-Growth 主函数函数名以你包内实际为准 % 常见签名: [freqItemsets, rules] fpgrowth(trans, minSup, minConf); [freqItemsets, rules] fpgrowth(trans, minSup, minConf); % 输出频繁项集数量和规则数量判断参数是否合理 fprintf(频繁项集数: %d\n, numel(freqItemsets)); fprintf(关联规则数: %d\n, numel(rules));参数说明minSup从 0.05 开始试比较稳规则太少就降到 0.02、0.01minConf一般从 0.5 到 0.7 之间起步。跑完先看两个数量频繁项集几百条、规则几十到几百条是正常区间。如果频繁项集上万说明minSup太低树没剪干净如果规则数为 0要么minConf太高要么minSup太高导致根本没有频繁项集。2.4 从频繁项集到关联规则支持度、置信度、提升度频繁项集只是「哪些项经常一起出现」关联规则才是「A → B」这种可解释的形式。一条规则的质量看三个指标支持度是 A 和 B 同时出现的比例置信度是 A 出现时 B 出现的条件概率提升度是置信度除以 B 自身的支持度——提升度大于 1 才说明 A 对 B 有正向拉动等于 1 就是独立没关系。% 遍历规则打印支持度、置信度、提升度 for i 1:numel(rules) r rules{i}; % 字段名以你包内结构为准常见为 antecedent/consequent/support/confidence/lift fprintf(%s %s | sup%.3f conf%.3f lift%.3f\n, ... strjoin(r.antecedent, ,), strjoin(r.consequent, ,), ... r.support, r.confidence, r.lift); end这里最容易翻车的是字段名对不上。不同实现里规则结构体可能叫antecedent/consequent也可能叫items/predicted跑之前先disp(rules{1})看一眼真实字段。提升度这个指标一定要看光看置信度高就下结论是新手常犯的错——如果 B 本身就是高频项A→B 的置信度天然就高但提升度可能接近 1这种规则没有实际价值。3. 把压缩包跑通从解压到出规则的操作链路3.1 解压后的目录结构与入口脚本定位拿到.rar先解压MATLAB 资源包通常包含几个部分主算法函数文件、示例数据、一个 demo 或 main 脚本、可能还有说明文档。你要找的是那个能直接运行的入口脚本一般叫main.m、demo.m或test_fpgrowth.m。别一上来就改算法文件先跑通 demo 看输出长什么样。% 把包目录加入 MATLAB 搜索路径避免函数找不到 addpath(genpath(pwd)); % 在解压后的根目录执行 % 确认关键函数可见 which fpgrowth % 应返回函数所在路径 % 运行入口脚本 main; % 或 demo / test_fpgrowth按实际文件名addpath(genpath(pwd))把当前目录及所有子目录加进路径这样跨文件夹调用函数不会报 undefined。which fpgrowth是确认函数能被找到的最快方式返回空就说明路径没加对或者函数名和你想的不一样。3.2 用自带数据跑第一版结果先别急着换自己的数据用包内示例数据跑一遍确认整条链路是通的。示例数据一般规模小、项数少跑起来快输出也容易看懂。% 载入示例数据文件名以包内实际为准 load(sample_data.mat); % 用默认参数跑一版 minSup 0.1; minConf 0.5; [freqItemsets, rules] fpgrowth(trans, minSup, minConf); % 打印前 5 条规则看看长什么样 for i 1:min(5, numel(rules)) disp(rules{i}); end这一步的目的是建立「正常输出」的基准。记住示例数据在默认参数下的频繁项集数和规则数换成自己数据后如果数量级差太多就知道是数据问题还是参数问题。示例跑不通后面全是白搭所以这一步别跳。3.3 换成自己的数据格式对齐是第一步自己的数据往包里塞最常见的失败就是格式不匹配。包内函数期望的是元胞数组你给的是表格或矩阵直接报错。转换逻辑不复杂但要注意每一条事务的项必须是同一类型。% 假设原始数据是 N x M 的 0/1 矩阵行是事务、列是项 % 转成 cell 数组每个 cell 存该事务中值为 1 的项名 itemNames arrayfun((x) sprintf(item%d, x), 1:size(data,2), UniformOutput, false); trans cell(size(data,1), 1); for i 1:size(data,1) trans{i} itemNames(data(i,:) 1); end % 过滤掉空事务空 cell 会让树构建出问题 trans trans(~cellfun(isempty, trans)); fprintf(有效事务数: %d\n, numel(trans));data(i,:) 1找出该事务包含的项映射成项名。空事务必须过滤否则插入 FP-Tree 时会出现空路径轻则结果异常重则报错。如果你的原始数据是长表格式每行一条「事务ID, 项名」记录那就先用unique和accumarray或分组聚合把它转成事务级 cell这一步没有捷径数据清洗的活省不掉。3.4 结果导出与规则排序跑出规则后一般要导出成表格方便排序和筛选。按提升度降序排是最实用的看法提升度高的规则才是真正有洞察的。% 把规则整理成表格并按提升度降序排列 nRules numel(rules); ante cell(nRules,1); cons cell(nRules,1); sup zeros(nRules,1); conf zeros(nRules,1); lift zeros(nRules,1); for i 1:nRules ante{i} strjoin(rules{i}.antecedent, ,); cons{i} strjoin(rules{i}.consequent, ,); sup(i) rules{i}.support; conf(i) rules{i}.confidence; lift(i) rules{i}.lift; end T table(ante, cons, sup, conf, lift, VariableNames, {前件,后件,支持度,置信度,提升度}); T sortrows(T, 提升度, descend); writetable(T, association_rules.csv); disp(T(1:min(10,height(T)), :));导出 CSV 的好处是可以丢进 Excel 或 BI 工具继续分析。排序后重点看提升度前 10 条这些是数据里最值得关注的组合。支持度和置信度作为辅助过滤比如你只关心支持度大于 0.05 的规则在表格里筛一下就行。4. 避坑与排查跑 FP-Growth 时最容易翻车的五个地方4.1 现象函数报 undefined明明文件就在那原因MATLAB 只搜索当前工作目录和已加入路径的目录解压后的子文件夹不会自动进路径。解决在包根目录执行addpath(genpath(pwd))再用which 函数名确认。如果which返回空检查函数文件名和调用名大小写是否一致MATLAB 在 Linux 下区分大小写。4.2 现象频繁项集数量爆炸内存直接拉满原因minSup设得太低大量低频项进入 FP-Tree树的分支数失控。解决先把minSup往上调一个数量级试跑比如从 0.01 调到 0.1看频繁项集数量是否回到合理区间再逐步往下找平衡点。数据项数超过几千时minSup低于 0.01 基本不可行。4.3 现象规则数为 0但频繁项集明明有一堆原因minConf设得太高或者频繁项集里全是单项集无法构成「A → B」的规则。解决先把minConf降到 0.3 看有没有规则出来如果有再逐步往上调。同时检查频繁项集里两项及以上的占比如果几乎全是单项集说明minSup还是偏高把长项集都剪掉了。4.4 现象提升度算出来是 Inf 或 NaN原因后件的支持度为 0 导致除零或者规则结构里支持度字段没正确赋值。解决检查规则生成阶段是否过滤了后件支持度为 0 的规则正常实现应该在计算提升度前就排除掉。如果是字段读取错误disp(rules{1})看结构体真实字段名别照着记忆里的名字硬写。4.5 现象换了自己的数据后结果完全不合理原因数据格式没对齐比如事务里混入了数值和字符串或者项名里有空格、逗号导致strjoin后无法区分。解决统一项类型为字符串项名里避免分隔符转换后用disp(trans{1:3})肉眼确认每条事务的项列表干净。数据清洗占整个流程七成时间这不是夸张。5. 进阶技巧用多组参数扫描找到稳定的规则集单组参数跑出来的规则有偶然性minSup稍微一动结果就变这种规则拿去做决策是不踏实的。我一般会做参数扫描固定minConf让minSup从高到低走几个档位观察规则数量和提升度分布怎么变。真正稳定的规则会在多个支持度档位下都出现那些只在某一档冒出来的大概率是噪声。% 参数扫描固定 minConf遍历多个 minSup minConf 0.6; supList [0.1, 0.05, 0.03, 0.02, 0.01]; resultSummary zeros(numel(supList), 3); for k 1:numel(supList) [fi, rl] fpgrowth(trans, supList(k), minConf); resultSummary(k,:) [supList(k), numel(fi), numel(rl)]; fprintf(minSup%.3f | 频繁项集%d | 规则%d\n, supList(k), numel(fi), numel(rl)); end % 找出规则数量开始急剧上升的拐点那个 minSup 附近通常最合适看resultSummary的第三列规则数随minSup下降会先缓增后暴增暴增点说明大量低频噪声项开始生成规则拐点前那一档就是比较稳的选择。这个方法比拍脑袋定参数靠谱得多。另一个技巧是交叉验证规则的稳定性把数据随机分成两半各自跑一遍取两边都出现的规则作为稳定规则集。实现上就是加一层随机抽样和规则匹配匹配键用「前件后件」字符串拼接。% 数据分半取两边都出现的规则作为稳定规则 idx randperm(numel(trans)); half1 trans(idx(1:floor(end/2))); half2 trans(idx(floor(end/2)1:end)); [~, r1] fpgrowth(half1, 0.03, 0.6); [~, r2] fpgrowth(half2, 0.03, 0.6); key1 cellfun((r) [strjoin(r.antecedent,,) strjoin(r.consequent,,)], r1, UniformOutput, false); key2 cellfun((r) [strjoin(r.antecedent,,) strjoin(r.consequent,,)], r2, UniformOutput, false); stableKeys intersect(key1, key2); fprintf(稳定规则数: %d / 单边规则数: %d, %d\n, numel(stableKeys), numel(key1), numel(key2));intersect取两边都有的规则键稳定规则数占单边的比例越高说明规则越可靠。这个比例低于三成的话要么数据量不够要么minSup太低引入了太多偶然组合。从那以后我每次跑关联规则都强制先做一遍参数扫描加数据分半验证两组都活下来的规则才拿去汇报。这份 MATLAB 资源包把 FP-Tree 和规则生成的核心逻辑都封装好了你要做的就是把数据格式对齐、参数扫一遍、稳定性验一遍剩下的就是解读规则背后的业务含义了。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站