精华内容
下载资源
问答
  • 关联分析算法

    千次阅读 2014-10-16 11:14:33
    关联分析算法
    关联分析算法
        关联分析算法的应用非常广泛,它可以在大规模数据集中找出一组有关联的数据。例如:商品分析中,我们可以分析出哪些商品之间有购买的关联,也就是买了其中一个商品之后,顾客就很有可能买另外一个商品。
        频繁项集是指那些经常出现在一起的物品集合,那么如何评价这里的频繁程度呢?我们用支持度和可信度(置信度)来评价。一个项集的支持度指数据集中包含该项集的记录所占的比例,置信度为一个关联规则中这个关联成立的概率。举例来说:

    从图中可以看出:
    • 项集{豆奶}的支持度为4/5,项集{豆奶,尿布}的支持度为3/5,项集{尿布,葡萄酒}的支持度为3/5,项集{尿布}的支持度为4/5, 这样看来一个项集支持度的计算方法一目了然;
    • 关联规则{尿布->葡萄酒}的可信度等于:支持度({尿布,葡萄酒})/支持度({尿布})=3/4。

        但是,当物品的数据量增大的时候,使用上述遍历的方法是可以找到所有的可信度较高的关联规则,但是需要遍历的次数也是非常庞大的。此时出现了Apriori算法。
       需要注意的是,Apriori算法的作用只是发现一个数据集中哪些项集是频繁的。关联分析的目标处理发现频繁项集之外,还需要从它们中间获得关联规则。不过对于关联分析而言,发现频繁项集是主要的工作,之后的关联规则则计算每个规则的可信度即可。
        Apriori算法的原理:如果某个项集是频繁的,那么它的所有子集也是频繁的;如果某个项集不是频繁的,那么它的所有子集也是非频繁的。利用这样的原理,我们便可以大幅度减少计算项集的个数。因为如果能推断出该项集不是频繁的,那么就没有必要计算其支持度和可信度了。《机器学习实战》中给出了一个很好的图示来解释Apriori的作用:

        Apriori算法是发现频繁项集的一种方法。该算法的输入参数有两个:数据集和最小支持度。最小支持度一定要有,因为大于最小支持度的项集才能被认为是频繁项集。
         Apriori算法的过程:首先,我们会生成所有单个物品的项集列表,接着扫描交易记录来查看哪些项集满足最小支持度的要求,哪些不满足最小支持度的集合会被去掉,对剩下来的集合进行组合以生成包含两个元素的项集。接下来,再重新扫描交易记录,去掉不满足要求的项集。重复该过程直到生成了一个包含所有元素的项集。
        在找到了数据集中所有的频繁项集之后,我们需要从这些频繁项集中发现关联规则。就一个频繁项集中就可以产生好多个规则,所以如何减小需要计算规则的数量也是很重要的。这里我们可以借鉴Apriori的思想,如果某条规则不满足最小可信度的要求,那么该规则的所有子集也不会满足最小可信度的要求。
        比如,在频繁项集{0, 1, 2, 3}中,我们发现0,1,2->3规则不满足最小支持度的要求,那么我们就可以知道1,2->0,3, 01->23, 02->13, 0->123, 1->023, 2->013都不是关联的规则了。这样就减小了很多规则的判断。

        
        




    展开全文
  • 资源中包含apriori关联分析算法的Python代码,python的版本为3.6,使用pycharm平台运行即可。
  • 邓聚龙提出的灰色关联分析算法的实现过程。可以在此基础上进行二次开发。
  • 数据挖掘十大算法(四):Apriori(关联分析算法

    万次阅读 多人点赞 2018-08-29 21:38:50
    同样的该算法也是在一堆数据集中寻找数据之间的某种关联,这里主要介绍的是叫做Apriori的‘一个先验’算法,通过该算法我们可以对数据集做关联分析——在大规模的数据中寻找有趣关系的任务,本文主要介绍使用Apriori...

    终于到了机器学习实战的第十一章了,这也是继K-均值后的第二个无监督学习算法了。同样的该算法也是在一堆数据集中寻找数据之间的某种关联,这里主要介绍的是叫做Apriori‘一个先验’算法,通过该算法我们可以对数据集做关联分析——在大规模的数据中寻找有趣关系的任务,本文主要介绍使用Apriori算法发现数据的(频繁项集、关联规则)。

    这些关系可以有两种形式:频繁项集、关联规则

            频繁项集:经常出现在一块的物品的集合

            关联规则:暗示两种物品之间可能存在很强的关系

    一个具体的例子:

    频繁项集是指那些经常出现在一起的物品,例如上图的{葡萄酒、尿布、豆奶},从上面的数据集中也可以找到尿布->葡萄酒的关联规则,这意味着有人买了尿布,那很有可能他也会购买葡萄酒。那如何定义和表示频繁项集和关联规则呢?这里引入支持度和可信度(置信度)。

    支持度:一个项集的支持度被定义为数据集中包含该项集的记录所占的比例,上图中,豆奶的支持度为4/5,(豆奶、尿布)为3/5。支持度是针对项集来说的,因此可以定义一个最小支持度,只保留最小支持度的项集。

    可信度(置信度):针对如{尿布}->{葡萄酒}这样的关联规则来定义的。计算为 支持度{尿布,葡萄酒}/支持度{尿布},其中{尿布,葡萄酒}的支持度为3/5,{尿布}的支持度为4/5,所以“尿布->葡萄酒”的可行度为3/4=0.75,这意味着尿布的记录中,我们的规则有75%都适用。

    有了可以量化的计算方式,我们却还不能立刻运算,这是因为如果我们直接运算所有的数据,运算量极其的大,很难实现,这里说明一下,假设我们只有 4 种商品:商品0,商品1,商品 2,商品3. 那么如何得可能被一起购买的商品的组合?

    上图显示了物品之间所有可能的组合,从上往下一个集合是 Ø,表示不包含任何物品的空集,物品集合之间的连线表明两个或者更多集合可以组合形成一个更大的集合。我们的目标是找到经常在一起购买的物品集合。这里使用集合的支持度来度量其出现的频率。一个集合出现的支持度是指有多少比例的交易记录包含该集合。例如,对于上图,要计算 0,3 的支持度,直接的想法是遍历每条记录,统计包含有 0 和 3 的记录的数量,使用该数量除以总记录数,就可以得到支持度。而这只是针对单个集合 0,3. 要获得每种可能集合的支持度就需要多次重复上述过程。对于上图,虽然仅有4中物品,也需要遍历数据15次。随着物品数目的增加,遍历次数会急剧增加,对于包含 N 种物品的数据集共有 2^N−1 种项集组合。为了降低计算时间,研究人员发现了 Apriori 原理,可以帮我们减少感兴趣的频繁项集的数目。

    Apriori 的原理:如果某个项集是频繁项集,那么它所有的子集也是频繁的。即如果 {0,1} 是频繁的,那么 {0}, {1} 也一定是频繁的。

    这个原理直观上没有什么用,但是反过来看就有用了,也就是说如果一个项集是非频繁的,那么它的所有超集也是非频繁的。如下图所示:

    频繁项集:

    主要步骤:

        首先会生成所有单个物品的项集列表
        扫描交易记录来查看哪些项集满足最小支持度要求,那些不满足最小支持度的集合会被去掉
        对剩下的集合进行组合以生成包含两个元素的项集
        接下来重新扫描交易记录,去掉不满足最小支持度的项集,重复进行直到所有项集都被去掉

    代码(代码中有详细注释):

    from numpy import *
    
    # 构造数据
    def loadDataSet():
        return [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]
    
    # 将所有元素转换为frozenset型字典,存放到列表中
    def createC1(dataSet):
        C1 = []
        for transaction in dataSet:
            for item in transaction:
                if not [item] in C1:
                    C1.append([item])
        C1.sort()
        # 使用frozenset是为了后面可以将这些值作为字典的键
        return list(map(frozenset, C1))  # frozenset一种不可变的集合,set可变集合
    
    # 过滤掉不符合支持度的集合
    # 返回 频繁项集列表retList 所有元素的支持度字典
    def scanD(D, Ck, minSupport):
        ssCnt = {}
        for tid in D:
            for can in Ck:
                if can.issubset(tid):   # 判断can是否是tid的《子集》 (这里使用子集的方式来判断两者的关系)
                    if can not in ssCnt:    # 统计该值在整个记录中满足子集的次数(以字典的形式记录,frozenset为键)
                        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 # 排除不符合支持度元素后的元素 每个元素支持度
    
    # 生成所有可以组合的集合
    # 频繁项集列表Lk 项集元素个数k  [frozenset({2, 3}), frozenset({3, 5})] -> [frozenset({2, 3, 5})]
    def aprioriGen(Lk, k):
        retList = []
        lenLk = len(Lk)
        for i in range(lenLk): # 两层循环比较Lk中的每个元素与其它元素
            for j in range(i+1, lenLk):
                L1 = list(Lk[i])[:k-2]  # 将集合转为list后取值
                L2 = list(Lk[j])[:k-2]
                L1.sort(); L2.sort()        # 这里说明一下:该函数每次比较两个list的前k-2个元素,如果相同则求并集得到k个元素的集合
                if L1==L2:
                    retList.append(Lk[i] | Lk[j]) # 求并集
        return retList  # 返回频繁项集列表Ck
    
    # 封装所有步骤的函数
    # 返回 所有满足大于阈值的组合 集合支持度列表
    def apriori(dataSet, minSupport = 0.5):
        D = list(map(set, dataSet)) # 转换列表记录为字典  [{1, 3, 4}, {2, 3, 5}, {1, 2, 3, 5}, {2, 5}]
        C1 = createC1(dataSet)      # 将每个元素转会为frozenset字典    [frozenset({1}), frozenset({2}), frozenset({3}), frozenset({4}), frozenset({5})]
        L1, supportData = scanD(D, C1, minSupport)  # 过滤数据
        L = [L1]
        k = 2
        while (len(L[k-2]) > 0):    # 若仍有满足支持度的集合则继续做关联分析
            Ck = aprioriGen(L[k-2], k)  # Ck候选频繁项集
            Lk, supK = scanD(D, Ck, minSupport) # Lk频繁项集
            supportData.update(supK)    # 更新字典(把新出现的集合:支持度加入到supportData中)
            L.append(Lk)
            k += 1  # 每次新组合的元素都只增加了一个,所以k也+1(k表示元素个数)
        return L, supportData
    
    dataSet = loadDataSet()
    L,suppData = apriori(dataSet)
    print(L)
    print(suppData)

    返回频繁项集与支持度

    上面代码获取数据的频繁项集,下面通过其他函数来获得关联规则。

    关联规则:

    # 获取关联规则的封装函数
    def generateRules(L, supportData, minConf=0.7):  # supportData 是一个字典
        bigRuleList = []
        for i in range(1, len(L)):  # 从为2个元素的集合开始
            for freqSet in L[i]:
                # 只包含单个元素的集合列表
                H1 = [frozenset([item]) for item in freqSet]    # frozenset({2, 3}) 转换为 [frozenset({2}), frozenset({3})]
                # 如果集合元素大于2个,则需要处理才能获得规则
                if (i > 1):
                    rulesFromConseq(freqSet, H1, supportData, bigRuleList, minConf) # 集合元素 集合拆分后的列表 。。。
                else:
                    calcConf(freqSet, H1, supportData, bigRuleList, minConf)
        return bigRuleList
    
    # 对规则进行评估 获得满足最小可信度的关联规则
    def calcConf(freqSet, H, supportData, brl, minConf=0.7):
        prunedH = []  # 创建一个新的列表去返回
        for conseq in H:
            conf = supportData[freqSet]/supportData[freqSet-conseq]  # 计算置信度
            if conf >= minConf:
                print(freqSet-conseq,'-->',conseq,'conf:',conf)
                brl.append((freqSet-conseq, conseq, conf))
                prunedH.append(conseq)
        return prunedH
    
    # 生成候选规则集合
    def rulesFromConseq(freqSet, H, supportData, brl, minConf=0.7):
        m = len(H[0])
        if (len(freqSet) > (m + 1)): # 尝试进一步合并
            Hmp1 = aprioriGen(H, m+1) # 将单个集合元素两两合并
            Hmp1 = calcConf(freqSet, Hmp1, supportData, brl, minConf)
            if (len(Hmp1) > 1):    #need at least two sets to merge
                rulesFromConseq(freqSet, Hmp1, supportData, brl, minConf)
    
    dataSet = loadDataSet()
    L,suppData = apriori(dataSet,minSupport=0.5)
    rules = generateRules(L,suppData,minConf=0.7)
    # rules = generateRules(L,suppData,minConf=0.5)
    print(rules)

    返回关联规则:

    上面的函数稍微有点复杂,因为使用的数据结构有点多,可能会搞混,所以下面说明一下函数意义。(由于我个人叙述可能不太清楚,所以这里引用作者的原话我觉得更好理解一点,稍微有点详细):

    以上便是引用作者对这三个函数的详细描述,在函数中的具体代码,我也有相关的注释,慢慢来应该能够理解的。

    下面对一个毒蘑菇的例子进行运算,检查一下在实际数据中的反应:

    第一个特征表示有毒或者可以使用。如果有毒则为2,可以食用为1。下一个特征蘑菇形状,有3-8六种可能,下面我们找出毒蘑菇中存在的公共特征:

    mushDatSet = [line.split() for line in open('mushroom.dat').readlines()]
    L,suppData = apriori(mushDatSet,minSupport=0.3)
    print(L)
    for item in L[1]:   # 只查看两个元素的集合
        if(item.intersection('2')): # intersection交集(选出毒蘑菇)
            print(item)

    输出了频繁项集和与毒蘑菇相关的特征:

    以上为Apriori算法构建模型的全部内容,该算法不仅适用于零售行业,同样适用于相同技术的其他行业,如网站流量分析以及医药行业等。

     

    参考书籍:《机器学习实战》

    展开全文
  • Apriori算法--关联分析算法(一)

    万次阅读 多人点赞 2017-10-16 15:49:49
    在实际生产生活我们经常会遇到一些“关联分析”(Association Analyse)的任务。举几个实际例子。1.人们的购物清单里面的各个商品没有什么关联呢?就像下面这个购物清单写的那样子,右边是各个顾客所买的东西。 ...

    在实际生产生活我们经常会遇到一些“关联分析”(Association Analyse)的任务。举几个实际例子。

    1.人们的购物清单里面的各个商品有没有什么关联呢?就像下面这个购物清单写的那样子,右边是各个顾客所买的东西。

    这里写图片描述

    有的时候我们想问,顾客购买商品的时候会不会多个商品组合起来买呢?顾客会不会倾向于豆奶和尿布这两样商品一起买?我们怎么从一份购物清单里面发现这种往往会一起出现的商品组合呢?


    2.现在几乎人人都有自己的PC,都会在自己的电脑上安装自己喜欢的软件。现在给出不同工作领域的用户的软件列表,我们能不能发现同种身份的人一般都会按照那些共性的软件呢?这样或许我们就可以给用户推荐他所在领域的受欢迎的软件。
    这里写图片描述

    能不能通过计算得到学生群体的共性软件呢?


    3.总结疾病的特征。给我们一些疾病的特征,我们如何从这些数据总结出某种疾病的普遍特征呢?比如,给一些患流行性感冒的病人的生理特征数据,我们如何从这些数据发现患流行性感冒的普遍症状呢?

    以上这些问题都是关系分析的问题,这些问题希望在数据集中发现其中蕴含的关系,企图发现里面存在的频繁出现的组合(比如学生会经常按照那些软件)或者项与项之间的关系(比如一般安装微信的人也会顺带安装QQ)。发现频繁出现的组合叫做发现频繁项集(frequent item set),而找出项与项之间的相关关系叫做关联规则学习(association rule analyse)

    这里写图片描述


    #如何量化?
    我们如何衡量一个组合是不是频繁出现的呢?频繁是中文含义就是出现的次数多,那么频繁的衡量标准肯定和出现的频数有关。如何计算某个组合的频数?例如:

    这里写图片描述

    那么{豆奶,尿布}的频数就是3,因为这个组合出现在第2,3,4条样本出现过。

    但是,我们也知道频数这个指标是和样本数量的有关的。假如我们规定频数大于5的组合就是频繁的。那这样子假如某个组合在10条随机数据集中的频数为1,这个组合是不频繁的;但是在100条随机数据集中频数为10,该组合变的频繁了。这就会导致频繁性的判断不稳定。因此实际上我们使用频率这个指标。

    实际上一个组合A的频率又叫组合A在这个数据集T上的支持度(support degree),意思就是组合A在数据集T上出现的概率。

    那么我们如何定义关联规则可信呢?已知一个人已经买了豆奶,那么他有多大概率也买尿布嘞?这个就要使用到条件概率了。

    这里写图片描述

    这个条件概率的直观解释就是:在所有出现豆奶的样本里,有多少个还出现了尿布。如果这个条件概率特别大,那么我们可以认为**“买了 豆奶 一般也会买 尿布 ”**这条规则是可信任的。规则 “买了 豆奶 一般也会买 尿布” 记作:豆奶——>尿布。但是这条关联规则不具备自反性。也就是说 豆奶——>尿布,并不能推出 尿布——>豆奶,本质上是因为他们的条件概率都不同:
    这里写图片描述

    直观上的理解也是一样的。比如 人们一般上完厕所就会洗手,规则:上厕所——>洗手 是可信的;但是并不意味着 洗了手就一定是在上厕所,因为也可能是吃了饭再洗手。

    同样的,在关联分析中,与某条规则相对应的条件概率也有另外一个名称:置信度

    规则A->B的置信度计算公式为:
    这里写图片描述

    有了这两个量化指标,那我们就可以在一个数据集上寻找频繁项集和关联规则啦。
    最原始的做法就是,生成所有可能的组合方式,然后我们枚举计算这些所有的组合方式的支持度(频率),那些达到支持度指标的就是我们想到找到的频繁项集啦。这种枚举法当然可以解决问题,但是我们想也想的到这个复杂度特别高!

    比如上面购物的例子中基础元素共有6个,这6个元素可以一个一个组合,也可以两个两个组合,也可以三个三个来•••那么这6个基本元素组合起来就一共有:
    这里写图片描述种可能的组合方式。如此,我们需要计算63种组合出现的频率,每次计算需要遍历整个数据集。emmmmm…这个时间复杂度O(2^N)要GG。那么一个自然的思路就是剪枝。

    #使用Apriori 原理进行剪枝

    Apriori原理特别简单!有一些公理化概率论基础都会轻松理解

    设A,B是两个事件,则

    这里写图片描述

    积事件的概率小于等于各个因子的概率。直观的解释就是A和B同时发生的概率当然要小于等于他们单独分别发生的概率。

    这里写图片描述

    ok.我们来使用这个性质对上面寻找频繁项集的过程进行剪枝。

    这里写图片描述

    上图显示了基础元素集为{0,1,2,3}时,所有可能的组合。这实际显示了一种生成所有组合的层次化的方法:先一一组合,然后再二二组合,再三三组合•••每一层的组合都可以在上一层的基础上进行。具体方法为:

    设第i层是所有含i个元素的组合,每个组合都有i+1个不同的元素。现在需要生成所有含i+1个元素的组合。

    i+1个元素的组合就是每个组合含有i+1个不同的元素;那么只要在原来第i层的基础上进行两两合并,生成含且只含i+1个元素的组合。

    为了让第i层两个组合CA,CB组合后生成只含i+1个元素,需要CA,CB有且只有一个元素不同。否则合并后的组合将不只i个元素。

    所以我们可以让所有组合按基础元素升序的方式排列,比较CA,CB前i-1个元素.如果CA和CB的前i-1个元素相同的话,CA和CB就只有第i个元素不同了(如01和02),这样合并后才能只含有i+1个元素。如果CA和CB的前i-1个元素不等,那至少CA与CB会有两个元素不一致(如01 和23 组合生成0123 就包含4个基本元素)。 (此方法存在问题,感谢@weixin_39799208指正)
    正确的做法应该是对CA和CB内的各元素做交集,看交集内的元素个数是否为i-1。

    现在 我们假设{23}组合的支持度为P({23}),它小于容许的最小支持度p’,即P(23) < p’,此时{23}这种组合就是不频繁的了。

    由图可知,{23}参与了组合{023}和{123}的生成,那么:

    这里写图片描述
    这里写图片描述

    #Apriori的实现代码:

    __author__ = 'jmh081701'
    import  numpy as np
    
    def loadDataset():
        return [{1,3,4},{2,3,5},{1,2,3,5},{2,5}]
    def createC1(dataset,minsupport=0.6):
        C1=[]
        for t in dataset:
            for s in t:
                if({s} in C1):
                    continue
                else:
                    C1.append({s})
        C1.sort()
        return map(frozenset,C1)
    
    def scan(dataset,minisupport=0.6,Ck=None):
        rst=[]
        cutset=[]
        supportData={}
        for c in Ck:
            for t in dataset:
                if c.issubset(t):
                    if c in supportData:
                        supportData[c]+=1
                    else:
                        supportData[c]=1
        lenD=float(len(dataset))
    
        for key in supportData:
            supportData[key]=supportData[key]/lenD
            if(supportData[key]>=minisupport):
                rst.append(key)
            else:
                cutset.append(key)
        return rst,supportData,cutset
    
    def genCj(Ck,k,Cutset={}):
    	#2019年04.10 此实现有问题,应该是取l1,l2交集然后判断交集元素个数是否符合要求。
        lenCk=len(Ck)
        Cj=set()
        for i in  range(lenCk):
            for j in range(i+1,lenCk):
                l1=list(Ck[i])[:k-1]
                l2=list(Ck[j])[:k-1]
                l1.sort()
                l2.sort()
                if(l1==l2):
                    t=Ck[i]|Ck[j]
                    f=0
                    for each in Cutset:
                        if set(each).issubset(t):
                            f=1
                            break
                    if(f==0):
                        Cj.add(t)
        return Cj
        
    def apriori(dataset,minisupport=0.6):
        #from number i layer frequent item set generate i+1 th frequent item set.
        C1=createC1(dataset)
        Ck=C1
        k=1
        supportData={}
        CutSet=[]
        rstC=[]
        while Ck!=set():
            rst,support,cutset=scan(dataset,minisupport,Ck)
            rstC.append([rst])
            supportData.update(support)
            CutSet.append(cutset)
            Cj=genCj(rst,k,CutSet)
            k+=1
            Ck=Cj
    
        return rstC,supportData
    data=loadDataset()
    rstC,supportData=apriori(data)
    print(rstC)
    print(supportData)
    

    运行结果:

    [[[frozenset({3}), frozenset({2}), frozenset({5})]], [[frozenset({2, 5})]]]
    {frozenset({1}): 0.5, frozenset({3}): 0.75, frozenset({4}): 0.25, frozenset({2}): 0.75, frozenset({5}): 0.75, frozenset({2, 3}): 0.5, frozenset({3, 5}): 0.5, frozenset({2, 5}): 0.75}
    

    #代码解释

    def loadDataset():
        return [{1,3,4},{2,3,5},{1,2,3,5},{2,5}]
    

    该函数用于生成数据集。输入数据集是一个list of set.列表里面的每一个元素都是集合。在关联分析中,需要将原始数据转化为这种数据形式。尤其是每个样本的特征向量其实是一个无序的集合。

    def createC1(dataset,minsupport=0.6):
        C1=[]
        for t in dataset:
            for s in t:
                if({s} in C1):
                    continue
                else:
                    C1.append({s})
        C1.sort()
        return map(frozenset,C1)
    

    该函数遍历整个数据集,将各个基础元素抽离出来。注意最后的map{frozenset,C1}

    map(func, seq1[, seq2,…]) 
    第一个参数接受一个函数名,后面的参数接受一个或多个可迭代的序列,返回的是一个集合。 Python函数编程中的map()函数是将func作用于seq中的每一个元素,并将所有的调用的结果作为一个list返回。
    

    map(frozenset,C1)其实就是将C1的每一个元素都转化为frozenset类型。这么做是为了让元素组合能够做字典的key.

    def scan(dataset,minisupport=0.6,Ck=None):
        rst=[]
        cutset=[]
        supportData={}
        for c in Ck:
            for t in dataset:
                if c.issubset(t):
                    if c in supportData:
                        supportData[c]+=1
                    else:
                        supportData[c]=1
        lenD=float(len(dataset))
    
        for key in supportData:
            supportData[key]=supportData[key]/lenD
            if(supportData[key]>=minisupport):
                rst.append(key)
            else:
                cutset.append(key)
        return rst,supportData,cutset
    

    上述代码在计算各个组合的频率。
    对于Ck里面的每一个组合c,遍历整个数据集,看这个c在数据集中出现了多少次。按照定义,c是t的子集说明 c在t出现了。

    rst是满足Ck内所有满足最小支持度要求的组合;同时supportData返回了Ck内所有组合的支持度,supportData是一个字典,key是基本元素的组合,而value是这个组合出现的频率。cutset用于返回Ck内那些被剪枝的组合。

    def genCj(Ck,k,Cutset={}):
        lenCk=len(Ck)
        Cj=set()
        for i in  range(lenCk):
            for j in range(i+1,lenCk):
                l1=list(Ck[i])[:k-1]
                l2=list(Ck[j])[:k-1]
                l1.sort()
                l2.sort()
                if(l1==l2):
                    t=Ck[i]|Ck[j]
                    f=0
                    for each in Cutset:
                        if set(each).issubset(t):
                            f=1
                            break
                    if(f==0):
                        Cj.add(t)
        return Cj
    

    genCj用于输入只含k个元素的若干组合Ck,以及已确定被剪枝的组合列表Cutset,输出含k+1个元素的所有可能的组合Cj。注意要先把前k-1个元素提取出来,然后排序,比较、如果相等后t不含有cutset的元素 再把合并后的加入。

    def apriori(dataset,minisupport=0.6):
        #from number i layer frequent item set generate i+1 th frequent item set.
        C1=createC1(dataset)
        Ck=C1
        k=1
        supportData={}
        CutSet=[]
        rstC=[]
        while Ck!=set():
            rst,support,cutset=scan(dataset,minisupport,Ck)
            rstC.append([rst])
            supportData.update(support)
            CutSet.append(cutset)
            Cj=genCj(rst,k,CutSet)
            k+=1
            Ck=Cj
    
        return rstC,supportData
    

    当第k层一直不空的时候,不断寻找新的组合。

    注意:关联分析的输入数据集中,每个样本的特征向量是一个集合,是无序的、确定的、互斥的。

    展开全文
  • Apriori(关联分析算法

    千次阅读 2020-06-29 08:53:53
    同样的该算法也是在一堆数据集中寻找数据之间的某种关联,这里主要介绍的是叫做Apriori的‘一个先验’算法,通过该算法我们可以对数据集做关联分析——在大规模的数据中寻找有趣关系的任务,本文主要介绍使用Apriori...

    终于到了机器学习实战的第十一章了,这也是继K-均值后的第二个无监督学习算法了。同样的该算法也是在一堆数据集中寻找数据之间的某种关联,这里主要介绍的是叫做Apriori的‘一个先验’算法,通过该算法我们可以对数据集做关联分析——在大规模的数据中寻找有趣关系的任务,本文主要介绍使用Apriori算法发现数据的(频繁项集、关联规则)。

    这些关系可以有两种形式:频繁项集、关联规则。

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

    一个具体的例子:

    频繁项集是指那些经常出现在一起的物品,例如上图的{葡萄酒、尿布、豆奶},从上面的数据集中也可以找到尿布->葡萄酒的关联规则,这意味着有人买了尿布,那很有可能他也会购买葡萄酒。那如何定义和表示频繁项集和关联规则呢?这里引入支持度和可信度(置信度)。

    支持度:一个项集的支持度被定义为数据集中包含该项集的记录所占的比例,上图中,豆奶的支持度为4/5,(豆奶、尿布)为3/5。支持度是针对项集来说的,因此可以定义一个最小支持度,只保留最小支持度的项集。

    可信度(置信度):针对如{尿布}->{葡萄酒}这样的关联规则来定义的。计算为 支持度{尿布,葡萄酒}/支持度{尿布},其中{尿布,葡萄酒}的支持度为3/5,{尿布}的支持度为4/5,所以“尿布->葡萄酒”的可行度为3/4=0.75,这意味着尿布的记录中,我们的规则有75%都适用。

    有了可以量化的计算方式,我们却还不能立刻运算,这是因为如果我们直接运算所有的数据,运算量极其的大,很难实现,这里说明一下,假设我们只有 4 种商品:商品0,商品1,商品 2,商品3. 那么如何得可能被一起购买的商品的组合?

    上图显示了物品之间所有可能的组合,从上往下一个集合是 Ø,表示不包含任何物品的空集,物品集合之间的连线表明两个或者更多集合可以组合形成一个更大的集合。我们的目标是找到经常在一起购买的物品集合。这里使用集合的支持度来度量其出现的频率。一个集合出现的支持度是指有多少比例的交易记录包含该集合。例如,对于上图,要计算 0,3 的支持度,直接的想法是遍历每条记录,统计包含有 0 和 3 的记录的数量,使用该数量除以总记录数,就可以得到支持度。而这只是针对单个集合 0,3. 要获得每种可能集合的支持度就需要多次重复上述过程。对于上图,虽然仅有4中物品,也需要遍历数据15次。随着物品数目的增加,遍历次数会急剧增加,对于包含 N 种物品的数据集共有 2^N−1 种项集组合。为了降低计算时间,研究人员发现了 Apriori 原理,可以帮我们减少感兴趣的频繁项集的数目。

    Apriori 的原理:如果某个项集是频繁项集,那么它所有的子集也是频繁的。即如果 {0,1} 是频繁的,那么 {0}, {1} 也一定是频繁的。

    这个原理直观上没有什么用,但是反过来看就有用了,也就是说如果一个项集是非频繁的,那么它的所有超集也是非频繁的。如下图所示:

    频繁项集:
    主要步骤:

    首先会生成所有单个物品的项集列表
    扫描交易记录来查看哪些项集满足最小支持度要求,那些不满足最小支持度的集合会被去掉
    对剩下的集合进行组合以生成包含两个元素的项集
    接下来重新扫描交易记录,去掉不满足最小支持度的项集,重复进行直到所有项集都被去掉
    

    代码(代码中有详细注释):

    from numpy import *

    构造数据

    def loadDataSet():
    return [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]

    将所有元素转换为frozenset型字典,存放到列表中

    def createC1(dataSet):
    C1 = []
    for transaction in dataSet:
    for item in transaction:
    if not [item] in C1:
    C1.append([item])
    C1.sort()
    # 使用frozenset是为了后面可以将这些值作为字典的键
    return list(map(frozenset, C1)) # frozenset一种不可变的集合,set可变集合

    过滤掉不符合支持度的集合

    返回 频繁项集列表retList 所有元素的支持度字典

    def scanD(D, Ck, minSupport):
    ssCnt = {}
    for tid in D:
    for can in Ck:
    if can.issubset(tid): # 判断can是否是tid的《子集》 (这里使用子集的方式来判断两者的关系)
    if can not in ssCnt: # 统计该值在整个记录中满足子集的次数(以字典的形式记录,frozenset为键)
    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 # 排除不符合支持度元素后的元素 每个元素支持度

    生成所有可以组合的集合

    频繁项集列表Lk 项集元素个数k [frozenset({2, 3}), frozenset({3, 5})] -> [frozenset({2, 3, 5})]

    def aprioriGen(Lk, k):
    retList = []
    lenLk = len(Lk)
    for i in range(lenLk): # 两层循环比较Lk中的每个元素与其它元素
    for j in range(i+1, lenLk):
    L1 = list(Lk[i])[:k-2] # 将集合转为list后取值
    L2 = list(Lk[j])[:k-2]
    L1.sort(); L2.sort() # 这里说明一下:该函数每次比较两个list的前k-2个元素,如果相同则求并集得到k个元素的集合
    if L1==L2:
    retList.append(Lk[i] | Lk[j]) # 求并集
    return retList # 返回频繁项集列表Ck

    封装所有步骤的函数

    返回 所有满足大于阈值的组合 集合支持度列表

    def apriori(dataSet, minSupport = 0.5):
    D = list(map(set, dataSet)) # 转换列表记录为字典 [{1, 3, 4}, {2, 3, 5}, {1, 2, 3, 5}, {2, 5}]
    C1 = createC1(dataSet) # 将每个元素转会为frozenset字典 [frozenset({1}), frozenset({2}), frozenset({3}), frozenset({4}), frozenset({5})]
    L1, supportData = scanD(D, C1, minSupport) # 过滤数据
    L = [L1]
    k = 2
    while (len(L[k-2]) > 0): # 若仍有满足支持度的集合则继续做关联分析
    Ck = aprioriGen(L[k-2], k) # Ck候选频繁项集
    Lk, supK = scanD(D, Ck, minSupport) # Lk频繁项集
    supportData.update(supK) # 更新字典(把新出现的集合:支持度加入到supportData中)
    L.append(Lk)
    k += 1 # 每次新组合的元素都只增加了一个,所以k也+1(k表示元素个数)
    return L, supportData

    dataSet = loadDataSet()
    L,suppData = apriori(dataSet)
    print(L)
    print(suppData)
    返回频繁项集与支持度

    上面代码获取数据的频繁项集,下面通过其他函数来获得关联规则。

    关联规则:

    获取关联规则的封装函数

    def generateRules(L, supportData, minConf=0.7): # supportData 是一个字典
    bigRuleList = []
    for i in range(1, len(L)): # 从为2个元素的集合开始
    for freqSet in L[i]:
    # 只包含单个元素的集合列表
    H1 = [frozenset([item]) for item in freqSet] # frozenset({2, 3}) 转换为 [frozenset({2}), frozenset({3})]
    # 如果集合元素大于2个,则需要处理才能获得规则
    if (i > 1):
    rulesFromConseq(freqSet, H1, supportData, bigRuleList, minConf) # 集合元素 集合拆分后的列表 。。。
    else:
    calcConf(freqSet, H1, supportData, bigRuleList, minConf)
    return bigRuleList

    对规则进行评估 获得满足最小可信度的关联规则

    def calcConf(freqSet, H, supportData, brl, minConf=0.7):
    prunedH = [] # 创建一个新的列表去返回
    for conseq in H:
    conf = supportData[freqSet]/supportData[freqSet-conseq] # 计算置信度
    if conf >= minConf:
    print(freqSet-conseq,’–>’,conseq,‘conf:’,conf)
    brl.append((freqSet-conseq, conseq, conf))
    prunedH.append(conseq)
    return prunedH

    生成候选规则集合

    def rulesFromConseq(freqSet, H, supportData, brl, minConf=0.7):
    m = len(H[0])
    if (len(freqSet) > (m + 1)): # 尝试进一步合并
    Hmp1 = aprioriGen(H, m+1) # 将单个集合元素两两合并
    Hmp1 = calcConf(freqSet, Hmp1, supportData, brl, minConf)
    if (len(Hmp1) > 1): #need at least two sets to merge
    rulesFromConseq(freqSet, Hmp1, supportData, brl, minConf)

    dataSet = loadDataSet()
    L,suppData = apriori(dataSet,minSupport=0.5)
    rules = generateRules(L,suppData,minConf=0.7)

    rules = generateRules(L,suppData,minConf=0.5)

    print(rules)
    返回关联规则:

    上面的函数稍微有点复杂,因为使用的数据结构有点多,可能会搞混,所以下面说明一下函数意义。(由于我个人叙述可能不太清楚,所以这里引用作者的原话我觉得更好理解一点,稍微有点详细):

    以上便是引用作者对这三个函数的详细描述,在函数中的具体代码,我也有相关的注释,慢慢来应该能够理解的。

    下面对一个毒蘑菇的例子进行运算,检查一下在实际数据中的反应:

    第一个特征表示有毒或者可以使用。如果有毒则为2,可以食用为1。下一个特征蘑菇形状,有3-8六种可能,下面我们找出毒蘑菇中存在的公共特征:

    mushDatSet = [line.split() for line in open(‘mushroom.dat’).readlines()]
    L,suppData = apriori(mushDatSet,minSupport=0.3)
    print(L)
    for item in L[1]: # 只查看两个元素的集合
    if(item.intersection(‘2’)): # intersection交集(选出毒蘑菇)
    print(item)
    输出了频繁项集和与毒蘑菇相关的特征:

    以上为Apriori算法构建模型的全部内容,该算法不仅适用于零售行业,同样适用于相同技术的其他行业,如网站流量分析以及医药行业等。

    参考书籍:《机器学习实战》

    展开全文
  • 一个实例带你搞懂Apriori关联分析算法

    千次阅读 多人点赞 2020-05-31 16:13:01
    关联分析算法 关联分析是一种在大规模数据集中寻找有趣关系的任务。这些关系可以两种形式:频繁项集或者关联规则。 附算法分析以及详细代码示例
  • 处理分类属性,处理连续属性,基于离散化的方法,非离散化方法,概率分层,序列模式及例子等
  • 一、关联分析的基本概念 关联分析(Association Analysis):在大规模数据集中寻找有趣的关系。 频繁项集(Frequent Item Sets):经常出现在一块的物品的集合。 关联规则(Association Rules):暗示两个物品...
  • Python --深入浅出Apriori关联分析算法(一) 这次呢,我们会在上次的基础上,讲讲如何分析物品的关联规则得出关联结果,以及给出用apyori这个库运行得出关联结果的代码。 一. 基础知识 上次我们介绍了几个关联分析...
  • 云安全管理平台关联分析算法研究与实现,王一涵,马兆丰,针对当前网络安全信息分析过程中出现的安全描述片面性等缺陷,提出了基于树规则的关联分析算法。在云安全管理平台中,利用基于概
  • 基于FPGA的暂态信号可定制精细化实时时频关联分析算法.pdf
  • 关联分析及常用的apriori算法和fp-growth算法做了较为详细的分析和改进。是本人自己结合资料整理而来
  • 你也能看懂的:灰色关联分析算法

    千次阅读 2020-02-11 16:54:09
    灰色关联分析是指对一个系统发展变化态势的定量描述和比较的方法,其基本思想是通过确定参考数据列和若干个比较数据列的几何形状相似程度来判断其联系是否紧密,它反映了曲线间的关联程度。 通常可以运用此方法来...
  • 数据关联规则分析算法

    千次阅读 2018-01-29 18:33:14
    数据关联规则(Associaton Rules,AR)是...1、基于Apriori算法关联分析 Apriori算法是关联规则分析中较为典型的频繁项集算法。 原理步骤: (1)对数据中每一项数据进行频率次数统计; (2)构成候选项集C1,计
  • 1.什么是关联分析? 从大规模数据集中寻找物品间的隐含关系被称作关联分析(association analysis)或者关联规则学习(association rule learning)。 2.关联分析中的关系 频繁项集(frequent item sets)是经常...
  • 基于舆情事件的词汇关联分析,既是面向网络舆情的情报研究中的一项关键技术,也是保证和提高网络舆情分析质量的一个重要途径。文章研究基于词跨度的关键词获取算法,对候选关键词进行权重计算。研究计算词汇之间的...
  • 关联分析之Apriori算法

    千次阅读 2017-11-08 14:03:41
    本文demo源码、实验数据:传送门引言如题,关联分析这个词语对于初学者而言或许比较陌生。但是我若将关联分析换成另一个短语“尿布与啤酒”大家就会很熟悉了。据报道,美国中西部的一家连锁店发现,男人们会在周四...
  • 关联分析:FP-Growth算法
  • 算法通过应用程序实现,在输入文本中输入数据集,应用窗口读入数据设置阈值即可运行生成结果。
  • 5 关联分析基本概念与算法.pptx
  • 关联分析学习算法篇Apriori

    千次阅读 2018-09-02 22:19:02
    早些时候写过关于购物篮分析的文章,其中提到了C5.0和Apriori算法,没有仔细说说这算法的含义,昨天写了一下关联分析的理论部分,今天说说关联分析算法之一的Apriori算法,很多时候大家都说,数据分析师更多的是会用...
  • 提出了一种新的用于星敏感器的多星关联分析算法,此算法经过复杂的分析,比较,可以确定出图象中有用星点的外接矩形,从而为下一步的矩心计算做好准备。与传统关联性算法相比,这种算法只需要对图象做一次扫描,...
  • 关联分析——Apriori算法

    千次阅读 2015-10-09 16:37:17
    关联分析:百度百科定义:又称关联挖掘,就是在交易数据、关系数据或其他信息载体中,查找存在于项目集合或对象集合之间的频繁模式、关联、相关性或因果结构。或者说,关联分析是发现交易数据库中不同商品(项)之间...
  • 数据挖掘常用算法 1 分类 在数据挖掘的发展过程中,由于数据...机器学习方法分为决策树、基于范例学习、规则归纳与遗传算法等:统计方法细分为回归分析、时间序列分析、关联分析、聚类分析、模糊集、粗糙集、探索..
  • 关联分析的Apriori算法 in Python

    千次阅读 2016-02-22 20:37:14
    关联分析的Apriori算法 in Python
  • 分布式系统模糊航迹关联算法分析.pdf 可进行算法分析

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 196,728
精华内容 78,691
关键字:

关联分析算法有哪些