基于Apriori关联规则算法实现购物篮分析

技术

Apriori关联规则算法是一种经典的数据挖掘方法,用于发现数据集中项之间的关联规则。其主要作用在于发现数据中频繁出现的项集以及它们之间的关联关系,从而揭示数据中的隐藏模式和规律, 具体来说Apriori算法可以帮助:

  • 发现频繁项集: Apriori算法能够识别数据集中频繁出现的项集,即经常一起出现的物品组合。这有助于商家了解哪些商品常常一起被购买,为交叉销售和推荐系统提供支持
  • 生成关联规则: 通过识别频繁项集,Apriori算法可以生成关联规则,例如:“如果顾客购买了商品 A 和商品 B,则他们也可能会购买商品 C”。这些规则可以指导商家设计促销活动和优化产品布局
  • 提供决策支持:

基于Apriori算法生成的关联规则,商家可以做出更加明智的决策,如调整产品定价、改进促销策略、优化库存管理等

1. Apriori算法原理

Apriori算法的数学推导涉及到频繁项集、支持度、置信度等概念,以及算法的核心步骤:生成候选项集和筛选频繁项集。下面将简要介绍Apriori算法的数学推导过程:

频繁项集: 在一个数据集中,如果一个项集的支持度大于或等于预先设定的最小支持度阈值,则称该项集为频繁项集。支持度可以用以下公式表示:

其中, 是一个项集, 表示包含项集 的交易数量,总交易数是指数据集中总的交易数量

关联规则: 关联规则是指在频繁项集的基础上,生成的条件格式为 的规则,其中 和 都是项集,关联规则的置信度表示在购买项集 的情况下,也购买 项集的概率,可以用以下公式表示:

Lift值: 用于衡量关联规则中的两个项集之间的相关性,它的计算公式为:

其中, 和 分别表示关联规则的前项和后项

Lift值的含义如下:

  • 如果 Lift 值等于 1,表示前项和后项之间没有关联,购买一个项不影响购买另一个项
  • 如果 Lift 值大于 1,表示前项和后项之间有正相关性,这意味着在观察到前项的情况下,购买后项的概率比在整个数据集中的平均水平要高
  • 如果 Lift 值小于 1,表示前项和后项之间有负相关性,这意味着在观察到前项的情况下,购买后项的概率比在整个数据集中的平均水平要低

因此,Lift 值可用于衡量关联规则的有用性和意义

Apriori算法的核心思想是利用Apriori原理来减少搜索空间,即如果一个项集是频繁的,则它的所有子集也必须是频繁的。这意味着如果一个项集 不频繁,那么它的超集 也不会是频繁的

2. Apriori算法步骤

  • 初始化: 生成频繁1项集(单个物品)
  • 生成候选项集: 根据频繁 项集生成候选 项集
  • 筛选频繁项集: 计算候选项集的支持度,保留支持度大于等于最小支持度的项集作为频繁项集
  • 生成关联规则: 根据频繁项集生成关联规则,并计算置信度
  • 输出结果: 输出频繁项集和关联规则

3. 代码实现

3.1 数据解读


          
import numpy as np
          
import pandas as pd
          
import numpy as np
          

          
data = pd.read_csv(open('GoodsOrder.csv'))
          
data
      

picture.image

数据集包含两列:id和Goods,每一行表示一个交易,id是交易的标识符,Goods列则是交易中所购买的商品

3.2 数据转换


          
data['Goods'] = data['Goods'].apply(lambda x: ','+x) 
          
data = data.groupby('id').sum().reset_index() # 根据id列对Goods列合并,并使用','将商品名称隔开
          
data['Goods'] = data['Goods'].apply(lambda x:[x[1:]])
          
data_list = list(data['Goods'])
          
data_translation = []
          
for i in data_list:
          
    p = i[0].split(',')
          
    data_translation.append(p)
          
data_translation # 分割商品名为每个元素
      

picture.image

对原始数据进行预处理,以便将其转换为适合用于Apriori算法的数据格式,每一个列表为一个订单所购买的商品合集

3.3 Apriori算法实现


          
def createC1(dataSet):
          
    # 构建初始候选项集列表
          
    C1 = []
          
    for transaction in dataSet:
          
        for item in transaction:
          
            if not [item] in C1:
          
                C1.append([item])
          
    # 对候选项集列表进行排序
          
    C1.sort()
          
    return list(map(frozenset, C1))
          

          
def scanD(D, Ck, minSupport):
          
    # 创建一个空字典,用于存储每个候选项集的支持度计数
          
    ssCnt = {}
          
    # 遍历数据集中的每条交易记录
          
    for tid in D:
          
        # 遍历候选项集列表
          
        for can in Ck:
          
            # 如果候选项集是交易记录的子集,则增加它的计数
          
            if can.issubset(tid):
          
                if not can in ssCnt:
          
                    ssCnt[can] = 1
          
                else:
          
                    ssCnt[can] += 1
          
    numItems = float(len(D))
          
    retList = []
          
    supportData = {}
          
    # 计算支持度并筛选满足最小支持度要求的候选项集
          
    for key in ssCnt:
          
        support = ssCnt[key]/numItems
          
        if support >= minSupport:
          
            retList.insert(0, key)
          
            supportData[key] = support
          
    return retList, supportData
          

          
def aprioriGen(Lk, k):
          
    # 生成候选项集
          
    retList = []
          
    lenLk = len(Lk)
          
    for i in range(lenLk):
          
        for j in range(i+1, lenLk):
          
            L1 = list(Lk[i])[:k-2]
          
            L2 = list(Lk[j])[:k-2]
          
            L1.sort()
          
            L2.sort()
          
            if L1 == L2:
          
                retList.append(Lk[i] | Lk[j])
          
    return retList
          

          
def apriori(dataSet, minSupport=0.02):
          
    # Apriori算法主函数
          
    C1 = createC1(dataSet)
          
    D = list(map(set, dataSet))
          
    L1, supportData = scanD(D, C1, minSupport)
          
    L = [L1]
          
    k = 2
          
    while (len(L[k-2]) > 0):
          
        Ck = aprioriGen(L[k-2], k)
          
        Lk, supK = scanD(D, Ck, minSupport)
          
        supportData.update(supK)
          
        L.append(Lk)
          
        k += 1
          
    del L[-1]
          
    return L, supportData
          

          
def getSubset(fromList, toList):
          
    # 递归地寻找fromList的所有子集并添加到toList中
          
    for i in range(len(fromList)):
          
        t = [fromList[i]]
          
        tt = frozenset(set(fromList)-set(t))
          
        if not tt in toList:
          
            toList.append(tt)
          
            tt = list(tt)
          
            if len(tt) > 1:
          
                getSubset(tt, toList)
          
    return toList
          

          
def calcConf(freqSet, H, supportData, ruleList, minConf=0.7):
          
    # 计算关联规则的置信度
          
    prunedH = []
          
    for conseq in H:
          
        conf = supportData[freqSet]/supportData[freqSet-conseq]
          
        lift = supportData[freqSet]/(supportData[conseq]*supportData[freqSet-conseq])
          
        if conf >= minConf and lift > 1:
          
            print(freqSet - conseq, '-->', conseq, '支持度:', round(supportData[freqSet], 6), '置信度:', round(conf, 6), 'lift值:', round(lift, 6))
          
            ruleList.append((freqSet-conseq, conseq, conf))
          
            prunedH.append(conseq)
          
    return prunedH
          

          
def rulesFromConseq(freqSet, H, supportData, ruleList, minConf=0.7):
          
    m = len(H[0])
          
    if len(freqSet) > (m + 1):
          
        Hmp1 = aprioriGen(H, m+1)
          
        Hmp1 = calcConf(freqSet, Hmp1, supportData, ruleList, minConf)
          
        if len(Hmp1) > 1:
          
            rulesFromConseq(freqSet, Hmp1, supportData, ruleList, minConf)
          

          
def generateRules(L, supportData, minConf=0.7):
          
    # 生成关联规则
          
    bigRuleList = []
          
    for i in range(1, len(L)):
          
        for freqSet in L[i]:
          
            H1 = [frozenset([item]) for item in freqSet]
          
            if i > 1:
          
                rulesFromConseq(freqSet, H1, supportData, bigRuleList, minConf)
          
            else:
          
                calcConf(freqSet, H1, supportData, bigRuleList, minConf)
          
    return bigRuleList
          

          
if __name__ == '__main__':
          
    dataSet = data_translation
          
    # 使用Apriori算法得到频繁项集和支持度数据
          
    L, supportData = apriori(dataSet, minSupport=0.02)
          
    # 生成关联规则
          
    rules = generateRules(L, supportData, minConf=0.35)
      

picture.image

在这里, minSupport 和 minConf 两个参数,它们分别代表着最小支持度和最小置信度阈值

minSupport : 指在 Apriori 算法中用来确定频繁项集的阈值,支持度衡量的是某个项集在所有事务中出现的频率,最小支持度就是设定的一个阈值,只有当项集的支持度不低于这个阈值时,才会被认为是频繁项集。在代码中,minSupport=0.02 表示最小支持度为 0.02,即项集在所有事务中至少出现的频率为 2%

minConf : 用来确定关联规则的阈值,它代表着最小置信度,置信度是指关联规则的可靠程度,即在条件出现的情况下,结论出现的概率,最小置信度就是设定的一个阈值,只有当关联规则的置信度不低于这个阈值时,才会被认为是强关联规则。在代码中,minConf=0.35 表示最小置信度为 0.35,即关联规则的置信度至少为 35%

这两个参数的作用是控制算法的输出,通过调整它们可以获得不同阈值下的频繁项集和关联规则,以满足具体的分析需求

3.4 Apriori输出解读

以下面输出为列:frozenset({'仁果类水果'}) --> frozenset({'全脂牛奶'}) 支持度: 0.030097 置信度: 0.397849 lift值: 1.557043

在所有交易中,有约3.01%的交易同时购买了"仁果类水果"和"全脂牛奶",而在购买了"仁果类水果"的交易中,约有39.79%的顾客也购买了"全脂牛奶",且购买了"仁果类水果"对购买"全脂牛奶"的提升效果约为1.56倍

4. 往期推荐

特征工程——数据转换

LightGBM模型房价预测实现

密度聚类DBSCAN详解附Python代码

ARIMA模型进阶——具有季节性的SARIMAX模型实现

基于VMD分解的VMD-LSTM时间序列预测模型实现,大力提升预测精度!

可解释性机器学习库Shapash——鸢尾花XGBoost分类解释实现

如果你对类似于这样的文章感兴趣。

欢迎关注、点赞、转发~

0
0
0
0
关于作者

文章

0

获赞

0

收藏

0

相关资源
字节跳动 EB 级湖仓一体分析服务 LAS 的实践与展望
火山引擎湖仓一体分析服务 LAS 是面向湖仓一体架构的 Serverless 数据处理分析服务,提供一站式的海量数据存储计算和交互分析能力,完全兼容 Spark、Presto、Flink 生态,在字节跳动内部有着广泛的应用。本次演讲将介绍 LAS 在字节跳动内部的发展历程和大规模应用实践,同时介绍 LAS 在火山引擎上的发展规划。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论