Apriori算法:关联分析

Apriori算法: 关联分析

Apriori算法概览

什么是关联分析?
找出大规模数据集中寻找物品间的隐含关系

Apriori算法: 创建函数频繁项集高效发现的函数,从而从频繁项集中抽取关联规则

  • Apriori算法的优缺点
    优点: 易编码实现
    缺点: 在数据集上较慢
    使用数据类型: 数值型或者标称型

关联分析关键词:

  • 频繁项集: 经常一起出现
  • 关联规则: 暗示两种物品之间可能存在很强的关系

如何量化频繁项集?频繁项集是指那些经常出现在一起的物品

答:引入: 支持度和可信度—

  • 支持度:数据集中包含该项集的记录所占的比例
  • 可信度或置信度: 针对一条关联规则定义来进行定义的
    例如:某个集合或某个元素集合—>推导出另一个元素
    假设:定义一条关联规则 {豆奶 莴笋} —> {莴笋} 意味着: 购买豆奶的同时,购买莴笋的概率也大 但是反之不成立 —-在逻辑上称为 前件–>后件
    可信度规则量化: support(p|H) / supprot(P)

Apriori算法–频繁项集

Apriori算法是发现频繁项集的一种方法
Apriori算法的两个参数分别为最小支持度和数据集

算法思路:
step1: 首先生成单个物品的项集列表
step2: 接着扫描交易记录来查看哪些项集满足最小支持度要求 将那些不满足最小支持度的项集会被去掉
step3: 然后对剩下来的集合进行组合以生成包含两个元素的项集, 重新扫描交易记录,去掉不满足最小支持度的项集
step4: 该过程重复进行直到所有项集都被去掉

伪代码
    当集合中的个数大于0时
        构建一个k项组成的候选项集
        检查数据以确认每个项集都是频繁的
        保留频繁项集并构建k+1项组成的候选项集列表
    返回 满足支持度的所有频繁项集与其支持(字典形式) 以及 满足支持度的所有频繁项集(列表形式)

具体实现

def load_data():
    """
    加载数据集
    :return:
    """

    return [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]


def single_set(data_set):
    """
    生成单个物品的频繁项集
    :param data_set:
    :return:
    """
    single_list = list()
    for i in data_set:
        for j in i:
            if [j] not in single_list:
                single_list.append([j])
    single_list.sort()
    return map(frozenset, single_list)


def calc_support(data_set, single_list, limit_support=0.5):
    """
    计算项集的支持度 去掉不满足最小支持度的项集
    :param data_set: 数据集
    :param single_list: 单个项集'物品'
    :param limit_support: 最小支持度
    :return
        frequent_to_rate_dict
        frequent_list
    """
    frequent_to_rate_dict = dict()
    frequent_list = []
    m = len(data_set)
    for i in single_list:
        # print(i)
        count = 0
        for j in data_set:
            # print(j)
            if i.issubset(j):
                count += 1
        # print('count', count)
        # print('divide count m', count/m)
        if (count/m) >= limit_support:
            frequent_to_rate_dict[i] = count/m
            frequent_list.append(i)
    # print('frequent_to_rate_dict', frequent_to_rate_dict)
    # print('frequent_list', frequent_list)
    return frequent_to_rate_dict, frequent_list


def build_items(support_list, k):
    """
    构建一个k项的候选项集
    :param support_list: 频繁项集
    :param k: k个项
    :return:
        candidate_list 候选项集
    """

    range_list = len(support_list)
    # print('range_list', range_list)
    candidate_list = list()
    # print('support_list', support_list)
    # print('xxxxx', support_list[0])
    for i in range(range_list):
        # print('i', i)
        for j in range(i+1, range_list):
            if type(support_list[i]).__name__ == 'frozenset' and type(support_list[j]).__name__ == 'frozenset':
                # print('support_list[i]', support_list[i])
                # print('support_list[j]', support_list[j])
                union_set = support_list[i] | (support_list[j])   # | 并集
                # print('union_set', union_set, len(set(union_set)))
                if union_set not in candidate_list and len(union_set) == k:
                    candidate_list.append(union_set)
                    # print('candidate_list', candidate_list)
        # print('result candidate list', candidate_list)
    return candidate_list


def apriori(data_set, min_support=0.5):
    """
    Apriori 算法---频繁项集
        检查数据以确认每个项集都是频繁的
        保留频繁项集并构建k+1项组成的候选项集的列表
    :param data_set: 数据集
    :param min_support: 最小支持度
    :return:
        frequent_to_rate_dict   满足支持度的所有频繁项集与其支持度
        frequent_list           满足支持度的所有频繁项集
    """
    base_list = single_set(data_set)
    frequent_to_rate_dict, frequent_list = calc_support(data_set, base_list, min_support)
    frequent_lists = [frequent_list]
    k = 2
    # print('frequent_lists[k-2]', frequent_lists[k-2])
    while len(frequent_lists[-1]) > 0:
        candidate_list = build_items(frequent_lists[-1], k)
        frequent_to_rate_dict1, frequent_list1 = calc_support(data_set, candidate_list, min_support)
        # print('frequent_to_rate_dict1', frequent_to_rate_dict1)
        # print('frequent_list1', frequent_list1)
        frequent_to_rate_dict.update(frequent_to_rate_dict1)
        if len(frequent_list1) == 0:
            break
        frequent_lists.append(frequent_list1)
        k += 1
    return frequent_to_rate_dict, frequent_lists

Apriori算法–关联规则

关联规则:support(p|H) / supprot(P)

目前已知: 频繁项集与 频繁项集对应的支持度

求关联规则
关联规则— 多个物品对少个物品之间关系的描述
因此分情况讨论:
(1)当频繁项集中元素len=2
{2个物品}与{1个物品}之间的关联规则
可以直接计算置信度(可信度)
(2)当频繁项集中元素len>2
{3个物品}与{1个物品}
{3个物品}与{2个物品}
因此,此时需要不断递归出候选项集
再计算置信度(可信度)

Apriori算法–关联规则 算法实现

def generate_rules(frequent_to_rate_dict, frequent_lists, min_conf=0.7):
    """
    关联规则生成函数
    :param frequent_to_rate_dict:  满足支持度的所有频繁项集与其支持度
    :param frequent_lists:   满足支持度的所有频繁项集
    :param min_conf:  最小可信度设置
    :return:
        rule_lists   关联规则列表
    """
    rule_lists = list()
    for i in range(1, len(frequent_lists)):
        for frequent_set in frequent_lists[i]:
            print('frequent_set', frequent_set)
            items = [frozenset([i]) for i in frequent_set]      # 从频繁项集中拆解出单个的项
            print('items', items)
            if i > 1:
                rules_from_consequent(frequent_set, items, frequent_to_rate_dict, rule_lists, min_conf)
            else:
                calc_conf(frequent_set, items, frequent_to_rate_dict, rule_lists, min_conf)
    print('rule_lists func', rule_lists)
    return rule_lists


def calc_conf(frequent_set, items, frequent_to_rate_dict, rule_lists, min_conf):
    """
    可信度计算
    :param frequent_set:   频繁项集中的元素
    :param items:          频繁项集中的元素的集合
    :param frequent_to_rate_dict:   所有元素的支持度字典
    :param rule_lists:    关联规则列表的空数组
    :param min_conf:       最小可信度
    :return:
        conf_list 记录 可信度大于阈值的集合
    """
    conf_list = list()
    for conseq in items:
        # print('conseq', conseq, 'frequent_set', frequent_set)
        conf = frequent_to_rate_dict[frequent_set] / frequent_to_rate_dict[conseq]
        # print('conf', conf)
        if conf >= min_conf:
            print('frequent_set', frequent_set, '>>>>', 'conseq', conseq, conf)
            print('conf', conf)
            rule_lists.append((frequent_set, conseq, conf))
            conf_list.append(conseq)
    return conf_list


def rules_from_consequent(frequent_set, items, frequent_to_rate_dict, rule_lists, min_conf=0.7):
    """
    生成候选规则集合
    :param frequent_set:      频繁项集中的元素
    :param items:              频繁项集中的元素的集合
    :param frequent_to_rate_dict: 所有元素的支持度的字典
    :param rule_lists: 关联规则列表的数组
    :param min_conf: 最小可信度
    """
    m = len(items[0])
    # print('m', m)
    # print('len(frequent_set)', len(frequent_set))
    if len(frequent_set) > (m + 1):
        hmp1 = build_items(items, m+1)
        print('hmp1', hmp1)
        hmp1 = calc_conf(frequent_set, hmp1, frequent_to_rate_dict, rule_lists, min_conf)
        if len(hmp1) > 1:
            print('应该继续迭代')
            rules_from_consequent(frequent_set, hmp1, frequent_to_rate_dict, rule_lists, min_conf)


def main():
    data_set = load_data()
    # single_list = single_set(data_set)
    # print('single list', single_list)
    # for i in single_list:
    #     print(i, type(i))
    #     if i.issubset([1, 2, 3]):
    #         print('True')
    #     print('False')
    # frequent_to_rate_dict, frequent_list = calc_support(data_set, single_list)

    # candidate_list = build_items(frequent_list, k=2)
    # print('候选集项', candidate_list)
    frequent_to_rate_dict, frequent_list = apriori(data_set, min_support=0.5)   # 至此找出了频繁项集
    print('frequent_to_rate_dict', frequent_to_rate_dict, 'length', len(frequent_to_rate_dict))
    print('frequent_list', frequent_list)

    rule_list = generate_rules(frequent_to_rate_dict, frequent_list, min_conf=0.7)
    print('rule_list', rule_list)


if __name__ == '__main__':
    main()

Apriori算法 概念以及解释

  • 项与项集: 设 itemsetitem1,item2,...,itemm,,itemk(k=1,2,...m)(itemset),kk i t e m s e t i t e m 1 , i t e m 2 , . . . , i t e m m 是 所 有 项 的 集 合 , 其 中 , i t e m k ( k = 1 , 2 , . . . m ) 成 为 项 。 项 的 集 合 称 为 项 集 ( i t e m s e t ) , 包 含 k 个 项 的 项 集 称 为 k 项 集
  • 事务与事务集:一个事务T是一个项集,它是itemset的一个子集,每个事务均与一个唯一标识符号Tid相联系,不同的事务一起组成了事务集D,构成了关联规则发现的事务数据库
  • 关联规则:关联规则是形如A=>B的蕴含式,其中A、B均为itemset的子集且均不为空集,而A交B为空
  • 支持度:数据集中包含该项集的记录所占的比例
    实质上: support(A=>B)=P(AB) s u p p o r t ( A => B ) = P ( A ∪ B )
    其中 P(AB)AB(AB),P(AorB),AB P ( A ∪ B ) 表 示 事 务 包 含 集 合 A 和 B 的 并 ( 即 包 含 A 和 B 中 的 每 个 项 ) 的 概 率 , 注 意 P ( A o r B ) 区 别 , 后 者 表 示 事 务 包 含 A 或 B 的 概 率
  • 置信度: 实质上就是事件A发生时,B发生的概率
    confidence(A=>B)=P(B|A)=support(AB)support(A) c o n f i d e n c e ( A => B ) = P ( B | A ) = s u p p o r t ( A ∪ B ) s u p p o r t ( A )
  • 频繁项集: I(I),I 如 果 项 集 I 的 相 对 支 持 度 满 足 事 先 定 义 好 的 最 小 支 持 度 阈 值 ( 即 I 的 出 现 频 度 大 于 相 应 的 最 小 出 现 频 度 ) , 则 I 是 频 繁 项 集
  • 强关联规则:满足最小支持度和最小置信度的关联规则,即待挖掘的关联规则

  • 剪枝策略:预先剪枝 —- 对不满足最小支持度的项集不予考虑,直接删除

参考文献
《机器学习实战》
《数据挖掘:概念与技术》

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值