关联分析/频繁项集挖掘:Apriori算法

简介

Apriori是一种流行的算法,用于在关联规则学习中提取频繁项集。Apriori算法被设计用于对包含交易的数据库进行操作,例如商店客户的购买。如果项目集满足用户指定的支持阈值,则该项目集被视为“频繁”。例如,如果支持度阈值设置为0.5(50%),则频繁项目集被定义为在数据库中所有事务的至少50%中一起发生的项目集合

定义

支持度(support):support(A=>B) = P(A∪B),表示A和B同时出现的概率。
置信度(confidence):confidence(A=>B)=support(A∪B) / support(A),表示A和B同时出现的概率占A出现概率的比值。
频繁项集:在项集中频繁出现并满足最小支持度阈值的集合,例如{牛奶,面包}、{手机,手机壳}等。
强关联规则:满足最小支持度和最小置信度的关联规则。

算法步骤

  1. 从记录中计算所有的候选1项集,并计算频繁1项集及支持度。
  2. 由频繁1项集生成k项候选集,并由k项候选集计算k项频繁集。
  3. 用k项频繁集生成所有关联规则,计算生成规则置信度,筛选符合最小置信度的关联规则

频繁项挖掘

任一频繁项的所有非空子集也必须是频繁的。也就是当生成k项候选集的时候,如果候选集中的元素不在k-1项频繁集中,则该元素一定不是频繁集,这个时候不需要计算支持度,直接去除即可。
比如说我们有0,1,2,3组成的集合,下面是其所有的项集组合:
在这里插入图片描述
从1项集开始计算k项集的支持度,在2项集候选集中当我们计算出{0,1}集合是非频繁的,那么它的所有子集都是非频繁的,即2项集{0,1,2}和{0,1,3}也是非频繁的,它们的子集{0,1,2,3}同样是非频繁的,对于非频繁集我们就不需要去计算支持度。
在这里插入图片描述
当找出所有的频繁后需要从频繁集中挖掘所有的关联规则,假设频繁项集{0,1,2,3},下图表示其生成的所有关联规则,对于阴影部分的低可信度的规则,它们的子集同样也会是低可信度的。
在这里插入图片描述

Python实现

  1. 数据集
data = [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]
  1. 创建初始候选集
    这里使用frozenset不可变集合是为了后续计算支持度字典是将集合作为键
def apriori(data_set):
    # 候选项1项集
    c1 = set()
    for items in data_set:
        for item in items:
            item_set = frozenset([item])
            c1.add(item_set)

结果:{frozenset({2}), frozenset({3}), frozenset({1}), frozenset({5}), frozenset({4})}

  1. 从候选项集中选出频繁项集
    如下图所以我们需要从初始的候选项集中计算k项频繁项集,所以这里封装函数用于每次计算频繁项集及支持度,当候选项集中集合中的每个元素都存在事务记录集合中是计数并保存到字典中,计算支持度后输出频繁项集和支持度
def generate_freq_supports(data_set, item_set, min_support):
    freq_set = set()  # 保存频繁项集元素
    item_count = {}  # 保存元素频次,用于计算支持度
    supports = {}  # 保存支持度

    # 如果项集中元素在数据集中则计数
    for record in data_set:
        for item in item_set:
            if item.issubset(record):
                if item not in item_count:
                    item_count[item] = 1
                else:
                    item_count[item] += 1

    data_len = float(len(data_set))

    # 计算项集支持度
    for item in item_count:
        if (item_count[item] / data_len) >= min_support:
            freq_set.add(item)
            supports[item] = item_count[item] / data_len

    return freq_set, supports
  1. 生成新组合
    由初始候选集会生成{1,2,3,5}的频繁项集,后续需要生成新的候选项集Ck
def generate_new_combinations(freq_set, k):
    new_combinations = set()  # 保存新组合
    sets_len = len(freq_set)  # 集合含有元素个数,用于遍历求得组合
    freq_set_list = list(freq_set)  # 集合转为列表用于索引

    for i in range(sets_len):
        for j in range(i + 1, sets_len):
            l1 = list(freq_set_list[i])
            l2 = list(freq_set_list[j])
            l1.sort()
            l2.sort()

            # 项集若有相同的父集则合并项集
            if l1[0:k-2] == l2[0:k-2]:
                freq_item = freq_set_list[i] | freq_set_list[j]
                new_combinations.add(freq_item)

    return new_combinations

在这里插入图片描述

  1. 循环生成候选集频繁集
def apriori(data_set, min_support, max_len=None):
    max_items = 2  # 初始项集元素个数
    freq_sets = []  # 保存所有频繁项集
    supports = {}  # 保存所有支持度

    # 候选项1项集
    c1 = set()
    for items in data_set:
        for item in items:
            item_set = frozenset([item])
            c1.add(item_set)

    # 频繁项1项集及其支持度
    l1, support1 = generate_freq_supports(data_set, c1, min_support)

    freq_sets.append(l1)
    supports.update(support1)

    if max_len is None:
        max_len = float('inf')

    while max_items and max_items <= max_len:
        ci = generate_new_combinations(freq_sets[-1], max_items)  # 生成候选集
        li, support = generate_freq_supports(data_set, ci, min_support)  # 生成频繁项集和支持度

        # 如果有频繁项集则进入下个循环
        if li:
            freq_sets.append(li)
            supports.update(support)
            max_items += 1
        else:
            max_items = 0

    return freq_sets, supports
  1. 生成关联规则
def association_rules(freq_sets, supports, min_conf):
    rules = []
    max_len = len(freq_sets)

    # 生成关联规则,筛选符合规则的频繁集计算置信度,满足最小置信度的关联规则添加到列表
    for k in range(max_len - 1):
        for freq_set in freq_sets[k]:
            for sub_set in freq_sets[k + 1]:
                if freq_set.issubset(sub_set):
                    conf = supports[sub_set] / supports[freq_set]
                    rule = (freq_set, sub_set - freq_set, conf)
                    if conf >= min_conf:
                        rules.append(rule)
    return rules
  1. 主程序
if __name__ == '__main__':
    data = [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]

    L, support_data = apriori(data, min_support=0.5)
    association_rules = association_rules(L, support_data, min_conf=0.7)

结果:
L:
在这里插入图片描述
support_data:
在这里插入图片描述
association_rules:
在这里插入图片描述

从频繁集中挖掘关联规则

关联规则来源于每一轮迭代中产生的频繁项集
在这里插入图片描述
关联规则的搜索一样可以遵循频繁项集的层次迭代搜索方法,即按照频繁项集的层次结构,进行逐层搜索

如果{0,1,2}➞{3}是一条低可信度规则,那么所有其他以3作为后件(箭头右部包含3)的规则均为低可信度的。即如果某条规则并不满足最小可信度要求,那么该规则的所有子集也不会满足最小可信度要求。

反之,如果{0,1,3}->{2},则说明{2}这个频繁项作为后件,可以进入到下一轮的迭代层次搜索中,继续和本轮得到的规则列表的右部进行组合。直到搜索一停止为止
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值