关联规则(Association Rules)

1 前言

关联规则反映一个事物与其他事物之间的相互依存性和关联性,是数据挖掘的一个重要技术,用于从大量数据中挖掘出有价值的数据项之间的相关关系。 本篇的Apriori算法主要是基于频繁集的关联分析。其主要目的就是为了寻找强关联规则。

常见的购物篮分析

通过观察顾客放人其购物篮中的不同商品之间的联系,分析顾客的购买习惯,了解哪些商品频繁地被顾客同时购买,这种关联的发现可以帮助零售商制定营销策略。

2 频繁项集评估标准

常用的频繁项集的评估标准有支持度,置信度和提升度三个

  • 支持度:几个关联的数据在数据集中出现的次数占总数据集的比重

  • 置信度:一个数据出现后,另一个数据出现的概率,或者说数据的条件概率。

  • 提升度:表示含有Y的条件下,同时含有X的概率,与X总体发生的概率之比

Apriori算法----发现频繁项集的一种方法
原理:

  • 如果一个项集是频繁项集,则它的所有子集都是频繁项集
  • 如果一个集合不是频繁项集,则它的所有父集(超集)都不是频繁项集

关联分析的目标:

  • 发现频繁项集:发现满足最小支持度的所有项集
  • 发现关联规则:从频繁项集中提取所有高置信度的规则
     

3 Apriori算法采用了迭代的方法

  1. 先搜索出候选1项集及对应的支持度,剪枝去掉低于支持度的1项集,得到频繁1项集。
  2. 对剩下的频繁1项集进行连接,得到候选的频繁2项集,筛选去掉低于支持度的候选频繁2项集,得到真正的频繁二项集,
  3. 以此类推,迭代下去,直到无法找到频繁k+1项集为止,对应的频繁k项集的集合即为算法的输出结果

下图来自博客:https://www.cnblogs.com/pinard/p/6293298.html

算法流程
 输入:数据集合D,支持度阈值αα

 输出:最大的频繁k项集

    1)扫描整个数据集,得到所有出现过的数据,作为候选频繁1项集。k=1,频繁0项集为空集。

    2)挖掘频繁k项集

      a) 扫描数据计算候选频繁k项集的支持度

      b) 去除候选频繁k项集中支持度低于阈值的数据集,得到频繁k项集。如果得到的频繁k项集为空,则直接返回频繁k-1项集的集合作为算法结果,算法结束。如果得到的频繁k项集只有一项,则直接返回频繁k项集的集合作为算法结果,算法结束。

      c) 基于频繁k项集,连接生成候选频繁k+1项集。

    3) 令k=k+1,转入步骤2。
 

4 python 实现

 

class Apriori:
    def __init__(self, minSupport, minConfidence):
        # 最小支持度
        self.minSupport = minSupport
        # 最小置信度
        self.minConfidence = minConfidence
        self.data = self.loadData()

    # 加载数据集
    def loadData(self):
        return [[1, 5], [2, 3, 4], [2, 3, 4, 5], [2, 3]]

    # 生成项集C1,不包含项集中每个元素出现的次数
    def createC1(self, data):
        C1 = list()  # C1为大小为1的项的集合
        for items in data:  # 遍历数据集
            for item in items:
                if [item] not in C1:
                    C1.append([item])
        # map函数表示遍历C1中的每一个元素执行forzenset
        # frozenset表示“冰冻”的集合,即不可改变
        return list(map(frozenset, sorted(C1)))

    # 该函数用于从候选项集Ck生成Lk,Lk表示满足最低支持度的元素集合
    def scanD(self, Ck):
        # Data表示数据列表的列表 [set([]), set([]), set([]), set([])]
        Data = list(map(set, self.data))
        CkCount = {}
        # 统计Ck项集中每个元素出现的次数
        for items in Data:
            for one in Ck:
                # issubset:表示如果集合one中的每一元素都在items中则返回true
                if one.issubset(items):
                    CkCount.setdefault(one, 0)
                    CkCount[one] += 1
        numItems = len(list(Data))  # 数据条数
        Lk = []  # 初始化符合支持度的项集
        supportData = {}  # 初始化所有符合条件的项集及对应的支持度
        for key in CkCount:
            # 计算每个项集的支持度,如果满足条件则把该项集加入到Lk列表中
            support = CkCount[key] * 1.0 / numItems
            if support >= self.minSupport:
                Lk.insert(0, key)
            # 构建支持的项集的字典
            supportData[key] = support
        return Lk, supportData

    # generateNewCk的输人参数为频繁项集列表Lk与项集元素个数k,输出为Ck
    def generateNewCk(self, Lk, k):
        nextLk = []
        lenLk = len(Lk)
        # 若两个项集的长度为k-1,则必须前k-2项相同才可连接,即求并集,所以[:k-2]的实际作用为取列表的前k-1个元素
        for i in range(lenLk):
            for j in range(i + 1, lenLk):
                # 前k-2项相同时合并两个集合
                L1 = list(Lk[i])[: k - 2]
                L2 = list(Lk[j])[: k - 2]
                if sorted(L1) == sorted(L2):
                    nextLk.append(Lk[i] | Lk[j])
        return nextLk

    # 生成频繁项集
    def gengrateLK(self):
        # 构建候选项集C1
        C1 = self.createC1(self.data)
        L1, supportData = self.scanD(C1)
        L = [L1]
        k = 2
        while len(L[k - 2]) > 0:
            # 组合项集Lk中的元素,声新的候选项集Ck
            Ck = self.generateNewCk(L[k - 2], k)
            Lk, supK = self.scanD(Ck)
            supportData.update(supK)
            L.append(Lk)
            k += 1
        return L, supportData

    # 生成关联规则
    def generateRules(self, L, supportData):
        ruleResult = []  # 最终记录的关联规则结果
        for i in range(1, len(L)):
            for ck in L[i]:
                Cks = [frozenset([item]) for item in ck]
                # 频繁项集中有三个及以上元素的集合
                self.rulesOfMore(ck, Cks, supportData, ruleResult)
        return ruleResult

    # 频繁项集只有两个元素
    def rulesOfTwo(self, ck, Cks, supportData, ruleResult):
        prunedH = []
        for oneCk in Cks:
            # 计算置信度
            conf = supportData[ck] / supportData[ck - oneCk]
            if conf >= self.minConfidence:
                print(ck - oneCk, "-->", oneCk, "Confidence is:", conf)
                ruleResult.append((ck - oneCk, oneCk, conf))
                prunedH.append(oneCk)
        return prunedH

    # 频繁项集中有三个及以上元素的集合,递归生成关联规则
    def rulesOfMore(self, ck, Cks, supportData, ruleResult):
        m = len(Cks[0])
        while len(ck) > m:
            Cks = self.rulesOfTwo(ck, Cks, supportData, ruleResult)
            if len(Cks) > 1:
                Cks = self.generateNewCk(Cks, m + 1)
                m += 1
            else:
                break


if __name__ == "__main__":
    apriori = Apriori(minSupport=0.5, minConfidence=0.6)
    L, supportData = apriori.gengrateLK()
    for one in L:
        print("项数为 %s 的频繁项集:" % (L.index(one) + 1), one)
    print("supportData:", supportData)
    print("minConf=0.6时:")
    rules = apriori.generateRules(L, supportData)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值