Skip to content

Apriori

Apriori 算法是一种经典的关联规则挖掘算法,用于发现数据集中项集之间的频繁模式和关联规则。它由 Agrawal 和 Srikant 在 1994 年提出,广泛应用于市场分析、推荐系统等领域。如果某个项集是频繁的,‌那么它的所有子集也是频繁的。‌这一原理有助于避免项集数目的指数增长,‌从而在合理时间内计算出频繁项集。‌

可结合树模型,深度分析随机森林

基本概念

1. 项集(Itemset)

项集是数据集中的一组项(items)。例如,在超市购物篮数据中,项集可以是 {牛奶, 面包, 黄油}。

2. 支持度(Support)

支持度是项集在数据集中出现的频率。支持度定义为包含该项集的事务数与总事务数的比值。

$$ \text{Support}(X) = \frac{\text{Number of transactions containing } X}{\text{Total number of transactions}} $$

3. 频繁项集(Frequent Itemset)

频繁项集是指支持度大于或等于某个最小支持度阈值(min_support)的项集。

4. 关联规则(Association Rule)

关联规则是形如 ( X \rightarrow Y ) 的规则,其中 ( X ) 和 ( Y ) 是项集,且 ( X \cap Y = \emptyset )。

5. 置信度(Confidence)

置信度是关联规则 ( X \rightarrow Y ) 的度量,表示在包含 ( X ) 的事务中,同时包含 ( Y ) 的事务的比例。

$$ \text{Confidence}(X \rightarrow Y) = \frac{\text{Support}(X \cup Y)}{\text{Support}(X)} $$

6. 提升度(Lift)

提升度是关联规则 ( X \rightarrow Y ) 的另一个度量,表示包含 ( X ) 的事务中同时包含 ( Y ) 的概率与 ( Y ) 的总体概率的比值。

$$ \text{Lift}(X \rightarrow Y) = \frac{\text{Confidence}(X \rightarrow Y)}{\text{Support}(Y)} $$

Apriori 算法步骤

Apriori 算法主要包含以下步骤:

1. 生成候选项集(Candidate Itemsets)

从单个项开始,生成所有可能的项集。

2. 计算支持度

计算每个候选项集的支持度,并筛选出频繁项集。

3. 生成关联规则

从频繁项集中生成关联规则,并计算其置信度和提升度。

4. 筛选关联规则

根据最小置信度阈值(min_confidence)筛选出有效的关联规则。

算法流程

  1. 初始化:生成所有单个项的项集,并计算其支持度。
  2. 迭代生成频繁项集
  3. 从频繁 ( k-1 ) 项集生成候选 ( k ) 项集。
  4. 计算候选 ( k ) 项集的支持度。
  5. 筛选出频繁 ( k ) 项集。
  6. 生成关联规则
  7. 从频繁项集中生成关联规则。
  8. 计算每个关联规则的置信度和提升度。
  9. 筛选出有效的关联规则。

示例

假设我们有以下购物篮数据:

事务ID 项集
1 {牛奶, 面包}
2 {牛奶, 黄油}
3 {面包, 黄油}
4 {牛奶, 面包, 黄油}

1. 生成候选项集

  • 单个项集:{牛奶}, {面包}, {黄油}
  • 二个项集:{牛奶, 面包}, {牛奶, 黄油}, {面包, 黄油}
  • 三个项集:{牛奶, 面包, 黄油}

2. 计算支持度

  • 支持度({牛奶}) = 3/4
  • 支持度({面包}) = 3/4
  • 支持度({黄油}) = 3/4
  • 支持度({牛奶, 面包}) = 2/4
  • 支持度({牛奶, 黄油}) = 2/4
  • 支持度({面包, 黄油}) = 2/4
  • 支持度({牛奶, 面包, 黄油}) = 1/4

假设最小支持度阈值为 0.5,则频繁项集为: - {牛奶}, {面包}, {黄油}, {牛奶, 面包}, {牛奶, 黄油}, {面包, 黄油}

3. 生成关联规则

  • 从频繁项集中生成关联规则,并计算置信度和提升度。

例如: - 规则:{牛奶} → {面包} - 置信度 = 支持度({牛奶, 面包}) / 支持度({牛奶}) = (2/4) / (3/4) = 2/3 - 提升度 = 置信度 / 支持度({面包}) = (2/3) / (3/4) = 8/9

4. 筛选关联规则

根据最小置信度阈值筛选出有效的关联规则(置信度越大越好)。

提升度

1. 评估规则的相关性

提升度可以帮助我们判断关联规则 ( X \rightarrow Y ) 是否具有实际意义,即 ( X ) 和 ( Y ) 之间是否存在真正的关联关系,而不仅仅是偶然的共现。

2. 区分偶然性和必然性

提升度的值可以帮助我们区分规则的偶然性和必然性:

  • 提升度 = 1:表示 ( X ) 和 ( Y ) 之间没有关联,即 ( X ) 和 ( Y ) 的出现是独立的。
  • 提升度 > 1:表示 ( X ) 和 ( Y ) 之间存在正向关联,即 ( X ) 的出现增加了 ( Y ) 出现的概率。
  • 提升度 < 1:表示 ( X ) 和 ( Y ) 之间存在负向关联,即 ( X ) 的出现减少了 ( Y ) 出现的概率。

3. 选择有效的关联规则

在实际应用中,我们通常会选择提升度大于 1 的关联规则,因为这些规则表明 ( X ) 和 ( Y ) 之间存在有意义的关联关系。提升度越大,关联规则的相关性越强。

总结

Apriori 算法通过迭代生成候选项集和计算支持度,有效地挖掘数据集中的频繁项集和关联规则。它利用了频繁项集的先验性质(Apriori 性质),即一个项集是频繁的,则其所有子集也是频繁的。这大大减少了计算量,提高了算法的效率。希望这个详解对你有所帮助!如果你有任何问题或需要进一步的帮助,请随时告诉我。

from itertools import combinations

class Apriori:
    def __init__(self, min_support, min_confidence,load_data=None):
        self.min_support = min_support
        self.min_confidence = min_confidence
        self.frequent_itemsets = {}
        self.rules = []
        if(load_data):self.load_data=load_data

    def load_data(self):
        # 示例数据集
        data = [
            ['牛奶', '面包', '黄油'],
            ['牛奶', '面包', '尿布', '啤酒'],
            ['牛奶', '尿布', '啤酒', '可乐'],
            ['面包', '黄油', '尿布', '啤酒'],
            ['面包', '尿布', '啤酒']
        ]
        return data

    def create_candidates(self, data, k):
        candidates = set()
        for transaction in data:
            for item in transaction:
                candidates.add(frozenset([item]))
        return [frozenset(item) for item in candidates]

    def filter_candidates(self, data, candidates):
        item_count = {}
        for transaction in data:
            for candidate in candidates:
                if candidate.issubset(transaction):
                    if candidate not in item_count:
                        item_count[candidate] = 1
                    else:
                        item_count[candidate] += 1

        num_transactions = len(data)
        frequent_items = {item: count / num_transactions for item, count in item_count.items() if count / num_transactions >= self.min_support}
        return frequent_items

    def generate_frequent_itemsets(self, data, max_length=3):
        k = 1
        candidates = self.create_candidates(data, k)

        while candidates and k <= max_length:
            frequent_items = self.filter_candidates(data, candidates)
            self.frequent_itemsets.update(frequent_items)

            k += 1
            candidates = [frozenset(comb) for comb in combinations(set().union(*frequent_items.keys()), k)]

    def generate_rules(self):
        for itemset in self.frequent_itemsets:
            if len(itemset) > 1:
                for i in range(1, len(itemset)):
                    for subset in combinations(itemset, i):
                        antecedent = frozenset(subset)
                        consequent = itemset - antecedent
                        confidence = self.frequent_itemsets[itemset] / self.frequent_itemsets[antecedent]
                        if confidence >= self.min_confidence:
                            self.rules.append((antecedent, consequent, confidence))

    def run(self):
        data = self.load_data()
        self.generate_frequent_itemsets(data)
        self.generate_rules()

    def print_results(self):
        print("Frequent Itemsets:")
        for itemset, support in self.frequent_itemsets.items():
            print(f"{set(itemset)}: {support:.2f}")

        print("\nAssociation Rules:")
        for antecedent, consequent, confidence in self.rules:
            print(f"{set(antecedent)} => {set(consequent)}: {confidence:.2f}")

apriori = Apriori(min_support=0.6, min_confidence=0.7)
apriori.run()
apriori.print_results()