• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
jacklee404
Never Stop!
博客园    首页    新随笔    联系   管理    订阅  订阅
推荐算法- Apriori(先验算法)

推荐算法- Apriori(先验算法)

先验算法属于关联规则学习的经典算法之一, 被设计用来寻找交易数据的潜在关系。

关联规则的定义:

\[I = \{I_1, I_2, \dots , I_n\} \\ 对于任意的 X \subset I, Y \subset I, 若 X \rightarrow Y(X \cap Y = \emptyset) \\ 则我们找到了一条关联规则 \]

其实就是找出类似 \(\{奶油, 面包\} \rightarrow \{饮料\}\) 的这种关系

关于蕴含关系如何获得的,这里我们需要两个评估的参数 置信度 和 支持度

支持度 support

定义:

\[Support(X\rightarrow Y) = \mid X \cup Y \mid / |S| \]

其中S为全集,显然该参数表示了元素 \(X\) 和 \(Y\) 相关性成正比,及交集在全集中所占的比例。

性质:

交换律:Support(X\rightarrow Y) = Support(Y\rightarrow X)$

置信度 cofidence

定义:

\[Confidence(X \rightarrow Y) = \mid X \cup Y \mid / |X| \]

置信度表示了在\(X\)集合中 \(Y\) 所占的比例, 表示了 \(X\) 对 \(Y\) 的 包含性。

Apriori算法过程

知道上述两个评价参数后,我们现在要做的是设定一个最小置信度和最小支持度, 找出满足大于等于评价参数的数据。

首先我们思考一下朴素的做法, 如果单纯的求出组合,那么仅仅求组合的复杂度在 \(O(2^N)\), 而交易数据通常很大,我们需要找到更优的算法。

这里我们可以根据最小置信度满足交换律,先计算满足最小置信度的集合。

分离计算(满足最小支持度)

由于支持度满足交换律,因此我们设满足任意子集大于最小置信度的集合为频繁项集。

对于满足要求的 \(\{X, Y\}\) 我们称为二阶频繁项集, 同理依次往后类推。

显然频繁项集满足如下性质:

  1. 任意频繁项集的子集都是频繁项集
  2. 任意非频繁项集的超集都不是频繁项集

那么我们利用性质1, 可以从低阶的频繁项集产生高阶的项集, 通过得到这些项集。

利用性质2, 我们利用低一阶的项集去筛掉一定不符合频繁项集的项。

Python 实现

"""
    Initial Data
"""


def create_data():
    dataset = [['Milk', 'Onion', 'Nutmeg', 'Kidney Beans', 'Eggs', 'Yogurt'],
               ['Dill', 'Onion', 'Nutmeg', 'Kidney Beans', 'Eggs', 'Yogurt'],
               ['Milk', 'Apple', 'Kidney Beans', 'Eggs'],
               ['Milk', 'Unicorn', 'Corn', 'Kidney Beans', 'Yogurt'],
               ['Corn', 'Onion', 'Onion', 'Kidney Beans', 'Ice cream', 'Eggs']]
    return dataset


def createK1(dataset):
    C1 = set()

    for t in dataset:
        for item in t:
            C1.add(frozenset([item]))

    return C1


"""
    Drop the data not fit with the theory
"""


def isApriori(Lksub1, Ck):
    for item in Ck:
        subset1 = Ck - frozenset([item])
        if subset1 not in Lksub1:
            return False
    return True


"""
    Generate Lk by Ck
"""


def generateLkbyCk(dataset, Ck, min_support, support_data):
    item_count = {}
    Lk = set()

    for item in Ck:
        for t in dataset:
            if item.issubset(t):
                item_count[item] = item_count.get(item, 0) + 1

    for item in item_count:
        if item_count[item] / len(dataset) >= min_support:
            Lk.add(item)
            support_data[item] = item_count[item] / len(dataset)

    return Lk


"""
    Generate Ck
"""


def createK(Lksub1, k):
    L1 = list(Lksub1)
    Ck = set()

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

            if l1[:k - 2] == l2[:k - 2]:
                set1 = L1[i] | L1[j]
                if isApriori(Lksub1, set1):
                    Ck.add(set1)
    return Ck


def main():
    min_support = 0.5
    support_data = {}
    L = []
    K = 5
    dataset = create_data()
    C1 = createK1(dataset)
    L1 = generateLkbyCk(dataset, C1, min_support, support_data)
    Lksub1 = L1.copy()
    L.append(Lksub1)

    for k in range(2, K + 1):
        Ck = createK(Lksub1, k)
        Lk = generateLkbyCk(dataset, Ck, min_support, support_data)
        Lksub1 = Lk.copy()
        L.append(Lksub1)

    print(L[2])


if __name__ == '__main__':
    main()
posted on 2023-12-11 19:13  Jack404  阅读(109)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3