当前位置: 首页 > news >正文

关联规则挖掘3:Eclat算法——等价类转换(Equivalence Class Transformation)

目录

​Eclat 算法思想​

​常见面试题与回答​

​1. Eclat 与 Apriori、FP-Growth 的区别?​​

​2. Eclat 如何计算项集的支持度?​​

​3. Eclat 的优缺点?​​

​4. 如何优化 Eclat 的性能?​​

​5. Eclat 的适用场景?​​

​关键点总结​

​详细计算过程示例​

​Step 1: 构建垂直数据格式(倒排索引)​​

​Step 2: 深度优先搜索(DFS)生成频繁项集​

​2.1 处理以 {A} 开头的项集​

​2.2 处理以 {B} 开头的项集​

​2.3 处理以 {C} 开头的项集​

​2.4 处理以 {E} 开头的项集​

​Step 3: 生成所有频繁项集​

​Step 4: 生成关联规则​

​关键点总结​

Python代码

面试题

一、基础概念题

1. 请简要阐述 Eclat 算法的核心思想是什么?

2. Eclat 算法与 Apriori 算法最根本的区别是什么?

二、深入原理题

3. 请描述 Eclat 算法的基本步骤。

4. Eclat 算法的优点和缺点分别是什么?

三、对比与应用题

5. 在什么场景下,Eclat 算法会比 Apriori 和 FP-Growth 更适用?

6. 如何优化 Eclat 算法中 TID 列表的交集操作?

四、实战代码题(如果面试岗位偏重工程)

7. 如果让你实现 Eclat 算法,你会如何设计核心数据结构?


参考:Python数据挖掘实战:微课版 - 9.4 Eclat算法 - 王磊 邱江涛 - 微信读书

Eclat 算法思想

Eclat(Equivalence Class Clustering and bottom-up Lattice Traversal)是一种基于垂直数据格式频繁项集挖掘算法,与 Apriori(水平格式)和 FP-Growth(前缀树)不同。其核心思想是:

  1. 倒排索引(垂直数据格式)​​:

    • 每个项(item)​存储其出现的事务ID列表(TID-list)​,如:

      A: [T1, T3]  
      B: [T2, T3, T4]  
      C: [T1, T2, T3]
    • 通过交集运算计算项集的支持度(如 A ∩ C = [T1, T3],支持度=2)。

  2. 深度优先搜索(DFS)​​:

    • 从单一项开始,逐步扩展生成更大的频繁项集(如 A → A+B → A+B+C)。

    • 利用等价类(Equivalence Class)​思想:共享相同前缀的项集可分组处理(如所有以 A开头的项集)。

  3. 支持度计算优化​:

    • 通过TID-list的交集直接计算支持度,无需扫描原始数据集。


常见面试题与回答

1. Eclat 与 Apriori、FP-Growth 的区别?​
  • 数据格式​:

    • Apriori/FP-Growth:水平格式(事务列表)。

    • Eclat:垂直格式(项→TID列表)。

  • 搜索策略​:

    • Apriori:广度优先(BFS),逐层生成候选项集。

    • FP-Growth:前缀树压缩+条件模式基。

    • Eclat:深度优先(DFS)+ 倒排索引。

  • 优势​:Eclat 适合稠密数据集(TID-list 交集计算快),Apriori 适合稀疏数据,FP-Growth 适合大数据集。

2. Eclat 如何计算项集的支持度?​
  • ​:通过 TID-list 的交集。例如 A: [1,3]B: [2,3]的交集是 [3],则 {A,B}的支持度为 1。

3. Eclat 的优缺点?​
  • 优点​:

    • 无需重复扫描数据库(依赖内存中的 TID-list)。

    • 适合高支持度项集和稠密数据

  • 缺点​:

    • TID-list 存储开销大(事务多时内存消耗高)。

    • 不直接生成关联规则(需额外步骤)。

4. 如何优化 Eclat 的性能?​
  • 使用差分集(Diffset)​​:存储 TID-list 的差集而非全集(减少内存)。

  • 按支持度升序排序项:优先处理稀有项,减少后续交集计算量。

  • 并行化:将项集分组并行处理。

5. Eclat 的适用场景?​
  • 数据集较小或中等规模(内存足够存储 TID-list)。

  • 需要快速挖掘高支持度项集(如电商高频商品组合)。

  • 不适用于超大规模数据(TID-list 内存爆炸)。


关键点总结

  • 核心思想​:垂直数据格式 + TID-list 交集 + 深度优先搜索。

  • 面试亮点​:对比 Apriori/FP-Growth,解释 TID-list 的优化原理。

  • 实际应用​:适合内存充足、需快速迭代的场景(如实时推荐系统)。


详细计算过程示例

我们以下面的数据集为例,逐步演示 Eclat 算法的执行流程:

事务数据集​(TID: Transaction ID):

T1: A, C, D  
T2: B, C, E  
T3: A, B, C, E  
T4: B, E

参数设置​:

  • 最小支持度(min_support)= 2

  • 最小置信度(min_confidence)= 0.5

  • 最小提升度(min_lift)= 1


Step 1: 构建垂直数据格式(倒排索引)​

扫描数据集,记录每个项出现的 TID-list:

A: [T1, T3]  
B: [T2, T3, T4]  
C: [T1, T2, T3]  
D: [T1]  
E: [T2, T3, T4]
  • 过滤非频繁项:D的支持度=1 < min_support,移除。

  • 剩余频繁 1-项集:

    {A}: [T1, T3], sup=2  
    {B}: [T2, T3, T4], sup=3  
    {C}: [T1, T2, T3], sup=3  
    {E}: [T2, T3, T4], sup=3

Step 2: 深度优先搜索(DFS)生成频繁项集

2.1 处理以 {A} 开头的项集
  • 扩展 {A}​​:

    • 与后续项 B组合:{A,B}的 TID-list = [T1,3] ∩ [T2,3,4] = [T3], sup=1 < 2 → 丢弃。

    • C组合:{A,C}的 TID-list = [T1,3] ∩ [T1,2,3] = [T1,3], sup=2 ≥ 2 → 保留。

    • E组合:{A,E}的 TID-list = [T1,3] ∩ [T2,3,4] = [T3], sup=1 < 2 → 丢弃。

  • 扩展 {A,C}​​:

    • 与后续项 B组合:{A,B,C}的 TID-list = [T1,3] ∩ [T2,3,4] ∩ [T1,2,3] = [T3], sup=1 < 2 → 丢弃。

    • E组合:{A,C,E}的 TID-list = [T1,3] ∩ [T2,3,4] ∩ [T2,3,4] = [T3], sup=1 < 2 → 丢弃。

  • 结果​:以 A开头的频繁项集为 {A}, {A,C}

2.2 处理以 {B} 开头的项集
  • 扩展 {B}​​:

    • C组合:{B,C}的 TID-list = [T2,3,4] ∩ [T1,2,3] = [T2,3], sup=2 ≥ 2 → 保留。

    • E组合:{B,E}的 TID-list = [T2,3,4] ∩ [T2,3,4] = [T2,3,4], sup=3 ≥ 2 → 保留。

  • 扩展 {B,C}​​:

    • E组合:{B,C,E}的 TID-list = [T2,3] ∩ [T2,3,4] = [T2,3], sup=2 ≥ 2 → 保留。

  • 扩展 {B,E}​​:

    • 已无更高阶项集可扩展。

  • 结果​:以 B开头的频繁项集为 {B}, {B,C}, {B,E}, {B,C,E}

2.3 处理以 {C} 开头的项集
  • 扩展 {C}​​:

    • E组合:{C,E}的 TID-list = [T1,2,3] ∩ [T2,3,4] = [T2,3], sup=2 ≥ 2 → 保留。

  • 扩展 {C,E}​​:

    • 已无更高阶项集可扩展。

  • 结果​:以 C开头的频繁项集为 {C}, {C,E}

2.4 处理以 {E} 开头的项集
  • 无更高阶项集可扩展。


Step 3: 生成所有频繁项集

合并所有 DFS 路径的结果:

1-项集: {A}, {B}, {C}, {E}  
2-项集: {A,C}, {B,C}, {B,E}, {C,E}  
3-项集: {B,C,E}

Step 4: 生成关联规则

{B,C,E}为例(sup=2):

  1. 规则 {B,C} → {E}​​:

    • 置信度 = sup({B,C,E}) / sup({B,C}) = 2/2 = 1.0

    • 提升度 = 1.0 / (sup({E})/总事务数) = 1.0 / (3/4) ≈ 1.33

    • 满足条件 → 保留。

  2. 规则 {B,E} → {C}​​:

    • 置信度 = 2/3 ≈ 0.67

    • 提升度 = 0.67 / (3/4) ≈ 0.89

    • 提升度 < min_lift → 丢弃。

其他规则类似计算,最终输出:

A --> C, support=0.50, confidence=1.00, lift=1.33  
C --> A, support=0.50, confidence=0.67, lift=1.33  
B --> E, support=0.75, confidence=1.00, lift=1.33  
E --> B, support=0.75, confidence=1.00, lift=1.33  
B,C --> E, support=0.50, confidence=1.00, lift=1.33  
B,E --> C, support=0.50, confidence=0.67, lift=0.89 (丢弃)  
C,E --> B, support=0.50, confidence=1.00, lift=1.33  
... (其他规则类似)

关键点总结

  1. 垂直格式优势​:TID-list 直接支持快速交集运算,无需扫描原始数据。

  2. DFS 路径​:按 A→B→C→E的顺序递归生成项集,避免冗余计算。

  3. 剪枝策略​:{A,B}非频繁,则所有包含 {A,B}的更高阶项集(如 {A,B,C})均被剪枝。

通过逐步追踪 TID-list 的交集和 DFS 路径,可以清晰理解 Eclat 的执行逻辑!

Python代码

class Eclat:   def __init__(self, min_support=3, min_confidence=0.6, min_lift=1):self.min_support = min_supportself.min_confidence = min_confidenceself.min_lift = min_liftdef invert(self, data):invert_data = {}fq_item = []sup = []for i in range(len(data)):for item in data[i]:if invert_data.get(item) is not None:invert_data[item].append(i)else:invert_data[item] = [i]for item in invert_data.keys():if len(invert_data[item]) >= self.min_support:fq_item.append([item])sup.append(invert_data[item])fq_item = list(map(frozenset, fq_item))return fq_item, supdef getIntersection(self, fq_item, sup):sub_fq_item = []sub_sup = []k = len(fq_item[0]) + 1for i in range(len(fq_item)):for j in range(i+1, len(fq_item)):L1 = list(fq_item[i])[:k-2]L2 = list(fq_item[j])[:k-2]if L1 == L2:intersection = list(set(sup[i]).intersection(set(sup[j])))if len(intersection) >= self.min_support:sub_fq_item.append(fq_item[i] | fq_item[j])sub_sup.append(intersection)return sub_fq_item, sub_supdef findFrequentItem(self, fq_item, sup, fq_set, sup_set):fq_set.append(fq_item)sup_set.append(sup)while len(fq_item) >= 2:fq_item, sup = self.getIntersection(fq_item, sup)if len(fq_item) > 0:fq_set.append(fq_item)sup_set.append(sup)else:breakdef generateRules(self, fq_set, rules, len_data):for fq_item in fq_set:if len(fq_item) > 1:self.getRules(fq_item, fq_item, fq_set, rules, len_data)def removeItem(self, current_item, item):tempSet = []for elem in current_item:if elem != item:tempSet.append(elem)tempFrozenSet = frozenset(tempSet)return tempFrozenSetdef getRules(self, fq_item, cur_item, fq_set, rules, len_data):for item in cur_item:subset = self.removeItem(cur_item, item)if subset in fq_set:  # 确保子集在频繁项集中confidence = fq_set[fq_item] / fq_set[subset]supp = fq_set[fq_item] / len_datalift = confidence / (fq_set[frozenset([item])] / len_data)if confidence >= self.min_confidence and lift >= self.min_lift:flag = Falsefor rule in rules:if (rule[0] == subset) and (rule[1] == fq_item - subset):flag = Trueif not flag:rules.append((subset, fq_item - subset, supp, confidence, lift))if len(subset) >= 2:self.getRules(fq_item, subset, fq_set, rules, len_data)def fit(self, data, display=True):frequent_item, support = self.invert(data)frequent_set = []support_set = []len_data = len(data)self.findFrequentItem(frequent_item, support, frequent_set, support_set)data_dict = {}for i in range(len(frequent_set)):for j in range(len(frequent_set[i])):data_dict[frequent_set[i][j]] = len(support_set[i][j])rules = []self.generateRules(data_dict, rules, len_data)if display:           print("Association Rules:")for rule in rules:print(f"{list(rule[0])} --> {list(rule[1])}, support={rule[2]:.3f}, confidence={rule[3]:.3f}, lift={rule[4]:.3f}")print("发现的规则数量:", len(rules))return frequent_set, rules# 测试数据
itemSetList = [['A', 'C', 'D'],['B', 'C', 'E'],['A', 'B', 'C', 'E'],['B', 'E']]et = Eclat(min_support=2, min_confidence=0.5, min_lift=1)
et.fit(itemSetList, True)

面试题

一、基础概念题

1. 请简要阐述 Eclat 算法的核心思想是什么?

答案:Eclat 算法的核心思想是基于垂直数据格式使用交集运算来支持度

  • 垂直数据格式:它不像 Apriori 那样记录每个事务包含了哪些项,而是记录每个项出现在哪些事务中(即事务ID列表,简称TID列表)。例如,项 A 的 TID 列表是 {1, 3, 4}

  • 交集求支持度:要计算一个项集 {A, B} 的支持度,不需要扫描整个数据库,只需对项 A 的 TID 列表和项 B 的 TID 列表求交集。交集的大小就是这个项集的支持度计数。例如,TID(A) ∩ TID(B) = {1, 3},则 support({A,B}) = 2

  • 深度优先搜索:Eclat 通常采用深度优先的策略来遍历项集空间,这有助于减少内存中对中间结果的存储开销。

2. Eclat 算法与 Apriori 算法最根本的区别是什么?

答案:最根本的区别在于它们使用的数据格式支持度计算方式

  • 数据格式:Apriori 使用水平数据格式(Horizontal Format),即 事务ID -> {物品列表}。而 Eclat 使用垂直数据格式(Vertical Format),即 物品 -> {事务ID列表}

  • 支持度计算:Apriori 在生成候选集后,需要通过扫描整个数据库来统计每个候选集的支持度。这是一个非常耗时的过程。Eclat 则通过简单的集合交集操作来计算支持度,避免了反复扫描原始数据库,效率更高。


二、深入原理题

3. 请描述 Eclat 算法的基本步骤。

答案:

  1. 数据转换:首先将水平格式的数据库转换为垂直格式,为每个1项集(单个项)建立其 TID 列表。

  2. 剪枝:根据最小支持度阈值,找出所有频繁1项集 (L1)

  3. 递归扩展(深度优先搜索):对于每一个频繁k项集 X,将其与排在它后面的其他频繁k项集 Y 进行如下操作:

    • 连接:生成候选 k+1 项集 Z = X ∪ Y

    • 计算支持度:通过计算 X 和 Y 的 TID 列表的交集,得到 Z 的 TID 列表。交集的大小即为 Z 的支持度计数。

    • 剪枝:如果 Z 的支持度大于等于最小支持度,则将其加入到频繁 k+1 项集列表中。

  4. 重复:以新生成的频繁项集为起点,递归地重复步骤3,直到无法生成新的频繁项集为止。

4. Eclat 算法的优点和缺点分别是什么?

答案:

  • 优点

    1. 高效的支持度计算:利用集合交集操作,避免了多次扫描原始数据库,尤其在支持度阈值较低、数据集密度较高时表现优异。

    2. 深度优先搜索:内存占用相对较小,因为它不需要同时保存大量的候选集(与 Apriori 的广度优先相比)。

    3. 无需候选集生成:在递归过程中直接通过交集产生下一个项集,避免了 Apriori 中复杂的候选生成步骤。

  • 缺点

    1. TID 列表开销:如果项集很长或数据库非常庞大,TID 列表本身会消耗大量内存。对于超大规模数据集,这可能成为瓶颈。

    2. 交集操作成本:当两个很长的 TID 列表进行交集运算时,虽然比扫描数据库快,但本身也是一个计算密集型操作。

    3. 对稀疏数据集不友好:在非常稀疏的数据集中,TID 列表会很短,但其优势可能不如 FP-Growth 等算法明显。


三、对比与应用题

5. 在什么场景下,Eclat 算法会比 Apriori 和 FP-Growth 更适用?

答案:
Eclat 算法在以下场景中可能更具优势:

  • 内存充足但数据库庞大:当数据库太大,反复扫描(如 Apriori)的成本极高时,Eclat 的一次转换、多次交集的方式会更高效。

  • 密集型数据集:数据集中存在大量频繁模式时,Eclat 的垂直格式和交集操作能充分发挥其优势。

  • 支持度阈值设置较低:低支持度意味着会挖掘出更长的频繁项集,Eclat 的深度优先搜索和基于交集的支持度计算在这种场景下扩展性更好。

对比总结

  • vs Apriori:在绝大多数情况下,Eclat 都优于 Apriori,因为它解决了 Apriori 候选集生成和多次扫描数据库两大瓶颈。

  • vs FP-Growth:这是一个更有意义的对比。FP-Growth 通过构建紧凑的 FP-tree 来压缩数据库,通常性能最佳且更稳定。但在某些特定类型的数据集(如非常稠密的数据)上,Eclat 可能能与之一战。FP-Growth 通常是更通用的首选。

6. 如何优化 Eclat 算法中 TID 列表的交集操作?

答案:
有多种优化策略可以显著提升交集操作的效率:

  1. 使用位图(Bitmap):将 TID 列表用位图来表示。每个位代表一个事务,如果项在该事务中出现,则对应位设置为1。求交集就变成了非常快速的按位与(BITWISE-AND) 操作,这在现代计算机上效率极高。

  2. 使用差分编码:如果 TID 是连续的数字,可以存储事务ID的差值而不是原始值,这样可以减少存储空间。

  3. 列表排序与二分查找:保证所有 TID 列表是有序的。在求两个有序列表的交集时,可以使用双指针法在线性时间内完成,效率很高。

  4. 倒排索引:这本身就是 Eclat 的基础,但可以进一步优化索引结构。


四、实战代码题(如果面试岗位偏重工程)

7. 如果让你实现 Eclat 算法,你会如何设计核心数据结构?

答案:我会设计一个以项集为键(Key),以其对应的 TID 列表为值(Value)的映射(Map)或字典(Dictionary)作为核心数据结构。

  • 初始状态Map<String, List<Integer>>,键是单个项(如 "A"),值是这个项出现的所有事务ID的列表 [1, 2, 5]

  • 递归过程:在生成 k+1 项集时,新的键是 k 项集的字符串连接(如 "AB"),新的值是两个父 k 项集 TID 列表的交集结果。

伪代码思路:

def eclat(prefix, items, min_sup):while items:i, tid_list_i = items.pop(0)new_prefix = prefix + i # 例如 prefix="A", i="B" -> new_prefix="AB"# 记录频繁项集frequent_sets.append((new_prefix, len(tid_list_i))) new_items = []for j, tid_list_j in items:# 关键操作:求交集intersection = tid_list_i ∩ tid_list_j if len(intersection) >= min_sup:new_items.append( (j, intersection) )# 深度优先递归eclat(new_prefix, new_items, min_sup) 

http://www.lryc.cn/news/626830.html

相关文章:

  • Simulink实现RELS递推最小二乘算法
  • 【机器学习】什么是损失景观(Loss Landscape)?
  • 漏扫 js 里面包含一些敏感内容 利用二进制加密 保持原始内容不变 又能过漏扫
  • 亚马逊蓝海掘金:以需供比为锚点的精准选品策略
  • 高压柜无线测温:给智能化配电室装上“智能体温监测仪”
  • Leetcode 深度优先搜索 (11)
  • C语言---分隔符、常量、注释、标识符、关键字、空格
  • 笔试——Day44
  • 域名加白怎么做
  • 实战:本地大模型+function Calling,获取北京天气
  • 保姆级Debezium抽取SQL Server同步kafka
  • JSON::Value 功能详解:从三目运算符到高级用法
  • Pytest项目_day20(log日志)
  • PyTorch API 2
  • GPT-5 上线风波深度复盘:从口碑两极到策略调整,OpenAI 的变与不变
  • C++开发/Qt开发:单例模式介绍与应用
  • 拓扑排序判断环 P1347 排序题解
  • 第二十七天:游戏组队问题
  • 跨平台 RTSP/RTMP 播放器工程化实践:低延迟与高稳定性的挑战与突破
  • Redisson最新版本(3.50.0左右)启动时提示Netty的某些类找不到
  • pip 安装常见错误及实例化解决办法大全
  • Tomcat部署与HTTP协议详解
  • 凸问题-非凸问题-非凸模型
  • 第十四届“中国软件杯”大赛晋级现场总决赛名单公布
  • PyTorch API 6
  • 单片机通信协议核心关系梳理笔记(UART/USART/232/485/SPI/12C/LIN/BLE/WIFI)
  • Spring Boot 3.4.x 性能优化实战:用 Undertow 替换 Tomcat 全指南​
  • JavaScript 性能优化实战:从原理到落地的完整指南
  • 【OneAI】使用Rust构建的轻量AI网关
  • 【Axure高保真原型】拖拉拽画圆