关联分析——Apriori算法以及Python实现

Aprior算法是比较经典的关联规则挖掘算法。

核心思想

核心就是先验原理,即频繁项集的子集必定是频繁项集。反之,若子集非频繁,则超集必定非频繁。

算法简介

基本概念

购物篮事务(transaction):一位顾客一次购买商品的记录就是一条事务。
项集(itemset):商品的集合。
频繁项集:集合内商品数量大于阈值的项集。
关联规则:形如 X ⟶ Y X \longrightarrow Y XY X , Y X, Y X,Y均为频繁项集。
支持度(support) X , Y X, Y X,Y同时出现的事务数与总事务数的比值。
置信度(confidence) X , Y X, Y X,Y同时出现的事务数与 X X X出现的事务数的比值。其意义就是 X X X出现后,多大的几率 Y Y Y会出现。
提升度(lift): 置信度除以规则后件Y的支持度(引入这个指标的原因是置信度忽视了规则后件带来的影响,也就是说置信度很高可能仅仅是因为规则后件支持度很高造成的,该规则可能没有实际意义)。

获取候选K频繁项集

通常采取合并K-1频繁项集的方法来获得K频繁项集。
1.合并:由于频繁项集是有序的,所以若两个K-1频繁项集的前K-2个相同,则考虑合并。
2.剪枝:合并后。只能确定原来的两个K-1项集是频繁的。还需要根据先验原理,检验K项集是否频繁。即逐个判定该K项集的子K-1项集是否频繁。

产生规则

一个K频繁项可以产生多个规则。同样,需要根据先验原理,去除置信度低于阈值的规则。(频繁项集产生的规则必定满足支持度,故无需考虑支持度)

  1. 初始化候选规则,即规则前件含有K-1个项
  2. 依次计算候选规则的置信度,大于阈值则存储规则,反之抛弃。
  3. 根据上一轮规则集合,合并前件产生新一轮的候选规则, 转步骤2。直到候选规则为空。

算法流程

-Input:购物篮事务数据集
-Output: 频繁项集及支持度,规则及置信度
-Step1:初始化频繁1项集
-Step2: 根据频繁K-1项集产生候选频繁K项集,逐个计算支持度,产生频繁K项集。转步骤2,直到出现候选项集为空
-Step3:依次根据每个频繁项集产生规则

代码

"""
Apriori关联分析算法
核心思想:先验原理
"""
from collections import Counter, defaultdict


class Apriori:
    def __init__(self, minsup, minconf):
        self.minsup = minsup
        self.minconf = minconf
        self.data = None
        self.N = None  # 购物篮数据的总数
        self.D = None  # 频繁项集的最大项个数
        self.fre_list = []  # 频繁项集,[[[],[]],[[],[]]]
        self.sup_list = []  # 存储每个频繁项的支持度
        self.fre_dict = defaultdict(lambda: 0)  # 键为频繁项集的tuple,值为支持度
        self.rules_dict = defaultdict(lambda: 0)  # 规则,键为规则前件和规则后件的tuple, 值为置信度

    def init_param(self, data):
        # 根据传入的数据初始化参数
        self.data = sorted(data)
        self.N = len(data)
        self.D = 0

        item_counter = Counter()
        for itemset in data:
            if len(itemset) > self.D:
                self.D = len(itemset)
            item_counter += Counter(itemset)
        itemset = sorted(item_counter)  # 保证有序
        c1 = []
        sup_c1 = []
        for item in itemset:
            sup = item_counter[item] / self.N
            if sup > self.minsup:
                c1.append([item])
                sup_c1.append(sup)

        self.fre_list.append(c1)
        self.sup_list.append(sup_c1)
        return

    def apriori_fre_itemset(self):
        # 使用Apriori算法获取频繁项集
        for i in range(1, self.D):  # 逐渐增加频繁项大小
            ck_1 = self.fre_list[i - 1]
            if len(ck_1) < 2:  # 若k-1频繁项集不足两个,则跳出循环
                break
            cand_ck_set = self.ck_itemset(i, ck_1)

            sup_ck = []
            ck = []
            for item in cand_ck_set:  # 计算ck的支持度
                sup = self.cal_sup(item)
                if sup > self.minsup:
                    ck.append(item)
                    sup_ck.append(sup)

            if len(ck) > 0:
                self.fre_list.append(ck)
                self.sup_list.append(sup_ck)

        for ck, sup_ck in zip(self.fre_list, self.sup_list):
            for itemset, sup in zip(ck, sup_ck):
                self.fre_dict[tuple(itemset)] = sup

        return

    def ck_itemset(self, ind, ck_1):
        # 根据k-1频繁项集产生k频繁项集, 产生候选然后减枝, 返回频繁项的list
        cand_ck_set = []
        for i in range(len(ck_1)):  # 合并两个k-1频繁项集
            cand_ck = ck_1[i]
            for j in range(i + 1, len(ck_1)):
                if ck_1[i][:ind - 1] == ck_1[j][:ind - 1]:  # 若前k-2项相同则合并
                    cand_ck.append(ck_1[j][-1])  # 合并形成频繁k项
                    if self.prune(cand_ck, ck_1):  # 检查其他k-1项集是否为频繁项集,进而减枝
                        cand_ck_set.append(cand_ck.copy())
                    cand_ck.pop()
        return cand_ck_set

    def prune(self, cand_ck_item, ck_1):
        # 根据k-1频繁项集来对k频繁项是否频繁
        for item in cand_ck_item[:-2]:
            sub_item = cand_ck_item.copy()
            sub_item.remove(item)
            if sub_item not in ck_1:
                return False
        return True

    def cal_sup(self, item):
        # 支持度计数
        s = set(item)
        sup = 0
        for t in self.data:
            if s.issubset(t):
                sup += 1
        return sup / self.N

    def cal_conf(self, sxy, X):
        # 计算置信度, sxy为产生规则的频繁项集的支持度, X为规则前件
        return sxy / self.fre_dict[tuple(X)]

    def gen_rules(self):
        # 从频繁项集中提取规则
        for i in range(1, len(self.fre_list)):
            for ind, itemset in enumerate(self.fre_list[i]):
                cand_rules = []  # 由该频繁项集产生的规则的list, 记录规则前件
                sxy = self.sup_list[i][ind]
                for item in itemset:  # 初始化后件为1个项的规则
                    X = itemset.copy()
                    X.remove(item)
                    cand_rules.append(X)

                while len(cand_rules) > 0:
                    itemset_rules = []
                    for X in cand_rules:
                        conf = self.cal_conf(sxy, X)
                        if conf > self.minconf:
                            itemset_rules.append(X)
                            Y = list(set(itemset) - set(X))
                            Y = sorted(Y)
                            self.rules_dict[(tuple(X), tuple(Y))] = conf
                    cand_rules = self.apriori_rules(itemset_rules)
        return

    def apriori_rules(self, itemset_rules):
        # 根据先验原理产生候选规则
        cand_rules = []
        for i in range(len(itemset_rules)):
            for j in range(i + 1, len(itemset_rules)):
                X = list(set(itemset_rules[i]) & set(itemset_rules[j]))  # 合并生成新的规则前件
                X = sorted(X)
                if X in cand_rules or len(X) < 1:  # 若该规则前件已经产生或者为空则跳过
                    continue
                cand_rules.append(X)
        return cand_rules

    def fit(self, data):
        self.init_param(data)
        self.apriori_fre_itemset()
        self.gen_rules()
        return


if __name__ == '__main__':
    data = [['l1', 'l2', 'l5'], ['l2', 'l4'], ['l2', 'l3'],
            ['l1', 'l2', 'l4'], ['l1', 'l3'], ['l2', 'l3'],
            ['l1', 'l3'], ['l1', 'l2', 'l3', 'l5'], ['l1', 'l2', 'l3']]

    AP = Apriori(minsup=0.2, minconf=0.6)
    AP.fit(data)
    print(AP.rules_dict)

参考资料

http://f.dataguru.cn/thread-535049-1-1.html
我的GitHub
注:如有不当之处,请指正。

### 使用 `mlxtend` 库实现 Apriori 算法 Apriori 是一种用于频繁项集挖掘和关联规则学习的经典算法。以下是关于如何使用 Python 的 `mlxtend` 库来实现 Apriori 算法的具体方法。 #### 安装依赖库 为了运行 Apriori 算法,首先需要安装 `mlxtend` 和其他必要的数据处理库: ```bash pip install mlxtend pandas numpy ``` #### 数据准备 假设我们有一个交易记录的数据集,每条记录表示一次购买的商品列表。可以将其转换为适合 Apriori 输入的格式——一个二进制矩阵,其中每一列代表一项商品,而每一行则对应一条购物篮记录。 ```python import pandas as pd data = [['Milk', 'Onion', 'Nutmeg', 'Kidney Beans', 'Eggs'], ['Dill', 'Onion', 'Nutmeg', 'Kidney Beans', 'Yogurt'], ['Milk', 'Apple', 'Kidney Beans', 'Eggs'], ['Milk', 'Unicorn', 'Corn', 'Kidney Beans', 'Yogurt'], ['Corn', 'Onion', 'Onion', 'Kidney Beans', 'Ice cream', 'Eggs']] df = pd.DataFrame(data, columns=['Item1', 'Item2', 'Item3', 'Item4', 'Item5']) one_hot_encoded_df = df.stack().str.get_dummies().groupby(level=0).sum() print(one_hot_encoded_df.head()) ``` 上述代码片段展示了如何将原始事务数据转化为适合输入的形式[^4]。 #### 实现 Apriori 算法 利用 `mlxtend.frequent_patterns.apriori()` 函数计算频繁项集,并设置最小支持度阈值参数 `min_support` 来筛选符合条件的结果。 ```python from mlxtend.frequent_patterns import apriori frequent_itemsets = apriori(one_hot_encoded_df, min_support=0.6, use_colnames=True) print(frequent_itemsets) ``` 这里调用了 `apriori` 方法并指定了最低支持率作为过滤条件之一[^5]。 #### 关联规则生成 一旦获得了频繁项集之后,就可以进一步应用 `association_rules` 函数来自动生成关联规则。 ```python from mlxtend.frequent_patterns import association_rules rules = association_rules(frequent_itemsets, metric="confidence", min_threshold=0.7) print(rules[['antecedents', 'consequents', 'support', 'confidence']]) ``` 此部分演示了基于前面得到的频繁项目集合构建关联规则的过程[^6]。 ### 注意事项 - 支持度(Support)、置信度(Confidence)以及提升度(Lift)是用来评估关联规则质量的重要指标。 - 调整 `min_support` 或者 `min_threshold` 参数会影响最终发现的有效模式数量及其显著程度。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值