Apriori 算法关联分析--机器学习

守給你的承諾、 提交于 2019-12-20 19:04:39

前言:

          这种算法在实际应用中还是非常广泛,目标是找到一起出现的物品。比如男生去吃饭,推荐完菜肴后,关联推荐一下对应的酒水。女生去吃饭,推荐一下对应的果汁。 也经常用于流量分析,以及医药行业。

          算法实际应用中,需要灵活应用。比如某个事件出现的概率极其低,频繁项关联就会关联不到。

但是在某个时间点,或者特定事件组合中出现概率极其高。

    

 

目录:

  1.       算法简介
  2.       频繁项集生成
  3.       关联规则生成
  4.       投票中规则发现

一  算法简介

        apriori”, 拉丁语来自于以前。基本概念

         1.1 频繁项集

                是经常集合在一起出现的物品的集合 

                

        1.2  关联规则

                某两种规则之间存在很强的联系

                 

         1.3 支持度

                 定义为数据集中包括该记录所占比例

          1.3  可信度或者置信度

                针对一条记录x->另一条记录y的关联规则定义而来

                   


二 频繁项集生成

        说明:

          k: 代表当前项有k个元素

          

 频繁项集

         

: 候选项集

  主要原理:

             如果某个项集合是频繁的,那么它所有的子集也是

SCan: (生成满足频繁度的候选子集)

    对数据中的每个记录tran

           对每个候选集

                    检查can是否是tran 的子集

                             如果是: 则增加can的计数值

      对每个候选集

                如果该支持度不小于最小值,则保留该项集

        返回频繁集列表

 

    Apriori 完整算法

             当集合中项的候选项大于0

                   构建一个k个项组成的候选项集的列表

                   检查数据以确认每个项集都是频繁的

                  保留频繁项,并构建一个k+1的候选集的列表

 

三  关联规则

      若某条规则不满足最小置信度要求,则所有的子集也不满足.

对每个单独的平反集元素,从上到下递推出规则

    

# -*- coding: utf-8 -*-
"""
Created on Tue Dec 17 14:32:25 2019

@author: chengxf2
"""

"""
加载数据集
Args
   None
return
   数据集
"""
import numpy as np

"""
加载数据集
Args
   None: 这些数据集每一个样本之间是没有时序关系的
return
   dataList: 数据集
"""
def LoadDataSet():
    
    dataList =[[1,3,4],
               [2,3,5],
               [1,2,3,5],
               [2,5]]
    
    return dataList

"""
创建一个空列表C1,存储不重复的项值
Args
   dataSet: 数据集
return
   C1: 子数据集
"""
def CreateC1(dataSet):
    
    C1 = []
    for tran in dataSet:
        for item in tran:
            if not [item] in C1:
                C1.append([item])
    C1.sort()

    return list(map(frozenset, C1))      

"""
数据集扫描,返回支持度support,发现频繁项集
每个子集必须是频繁项
Args
D: 数据集
C1: 候选项集列表CK
最小支持度: minSupport

return
   Lk: 频繁项
"""
def SCan(D, Ck,minSupport):
    ssCnt ={}
    
    ##检查当前的交易
    for tid in D:
    
      
        for key in Ck: ##候选子集
            if key.issubset(tid):
                if key not in ssCnt:
                    ssCnt[key] =1
                else:
                    ssCnt[key]+=1
            
    
   #检测频繁度
    
    num = len(D)
    Lk = []
    supportData ={}
    
    for key in ssCnt:
        support = ssCnt[key]/num
        if support>= minSupport:
            Lk.insert(0, key)
        supportData[key]=support
   # print("\n supportData :\n ",supportData)
    return Lk, supportData

"""
   产生一个集合,该集合的子集都是由频繁项组成,元素长度为K
Arg
    Lk: 频繁项集列表
    k: 项集元素个数
输出
   Ck: 产生一个集合,该集合的子集都是由频繁项组成
"""
def ApriorGen(Lk, k):
    ckList = []
    
    n = len(Lk)
    #print("in Lk ",list(Lk), "\t n: ",n,"\t :k ",k)
   
    for i in range(n):
        L1 = list(Lk[i])[:k-2]
        #print("L1:::: \t",L1)
        L1.sort()
        for j in range(i+1, n):        
            L2 = list(Lk[j])[:k-2]
            L2.sort()
            
            if L1 == L2:
                ckList.append(Lk[i]|Lk[j])
    return ckList
            

"""
完整的算法
Args
   dataSet: 数据集
   minSupport: 最小支持度
return
   L: 频繁项,suppportData:支持度
"""
def Apriori(dataSet, minSupport=0.6):
    
    C1 = CreateC1(dataSet) ##创建子集
    D = list(map(set,dataSet))
    
    L1, supportData = SCan(D, C1, minSupport)  ##产生候选集
   # print("\n ======= L1 =========== \n",L1)
    
    L = [L1]
    k=2 
    
    while (len(L[k-2])>0):
        ck = ApriorGen(L[k-2],k) ##产生候选子集
       # print("\n ck===> \t \n ",k,ck)
        Lk,supK = SCan(D, ck, minSupport) ##产生候选子集Lk
        supportData.update(supK)  ##更新支持度
        L.append(Lk)
        k+=1
    return L, supportData
        
        
        

"""
关联规则生成
Args
    L:频繁项
    supportData: 支持度
    minConf: 最小支持度
return
    bigRuleList:  最大支持度
"""
def GenerateRule(L, supportData, minConf=0.5):
    
    bigRuleList = []
    
    n = len(L)
    
    print("\n *****关联规则生成************\t ")
    
    
    for i in range(1, n):
        print("\n i: ",i,"\t 频繁项集合 ",L[i])
        for freqSet in L[i]: ##检查每个频繁集
            H1 =[frozenset([item]) for item in freqSet] ##生成对应的子集
            
            if(i>1):
              print("\n H1: ",H1,"\t, freqSet \t",freqSet)
              RulesFromConseq(freqSet, H1, supportData, bigRuleList, minConf)
            else:
              CalcConf(freqSet, H1, supportData, bigRuleList, minConf)
              
    return bigRuleList
"""
计算支持度
y =h
p(y|x)=P(x,y)/p(x)
x= freqSet-y
Args
   freqSet: 频繁集例如 {23}
   H: 频繁集合中每个元素的集合[2,3]
   supportData: P(23) 的支持度
   br1: 关联度集合
   minconf: 最小置信度
"""
def CalcConf(freqSet, H, supportData, br1, minconf):
    prunedH = []
    
    for h in H:
        conf = supportData[freqSet]/supportData[freqSet-h] 
        
        if conf>=minconf:
            br1.append([freqSet-h, h,conf])
            prunedH.append(h)
    return prunedH


""""
生成一个基本的规则
Args
   freqSet: 频繁集例如 {123}
   H: 频繁集合中每个元素的集合[1,2,3]
   supportData: P(23) 的支持度
   br1: 关联度集合
   minconf: 最小置信度

"""
def RulesFromConseq(freqSet, H, supportData, br1, minconf= 0.5):
            m = len(H[0])
            print("\n m: ",m,"\t freSetNum: ",len(freqSet))
            if (len(freqSet)> (m+1)):  ##防止为NULL
                H1 = ApriorGen(H,m+1) ##产生一个频繁集合的增广集合
                H1 = CalcConf(freqSet, H1, supportData, br1, minconf)
                
                if (len(H1)>1):
                    RulesFromConseq(freqSet, H1,supportData, br1,minconf)
 
               
          
def Test():
     
     dataSet = LoadDataSet()
     L, supportData = Apriori(dataSet,0.5)
     print("\n L: \n",L)
     print("\n supportData:  \n",supportData)
     print("\n **************End******************\n")
     #print("\n :::L:::::::\n ",L, "\n supportData::::::\n ",supportData)
     
     rule= GenerateRule(L, supportData)
     print("\n *********规则生成结束***********\n")
     print("\n rule, ",rule)
     
     
  
    # print("\n C1:",C1)
     
Test()

参考文档:

    《机器学习与应用》

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!