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

1.主要概念

关联分析:从大规模数据集中寻找物品间隐含关系

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

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

支持度:数据集中包含该项集的记录所占的比例

置信度(可信度): 对于规则A-->B      定义可信度=支持度(A,B)/支持度(A),即规则在A中的适应程度

2.Aprior原理

假设四种商品0,1,2,3,则所有可能的项集如下所示: 

N中物品,项集可能数有2的N次幂-1,若计算每一种可能项集的支持度,计算量太大。

Aprior原理:某个项集是频繁的,所有子集也是频繁的;若某个项集非频繁,他的所有超集也是非频繁的。

若23非频繁,则023,123,0123必定也非频繁,因此不需要计算其支持度,这样可以大大减少求解的数量。

扫描二维码关注公众号,回复: 3917560 查看本文章

3.Aprior算法发现频繁集

 加载数据集:

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

根据数据集创建单元素项集C1:

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))#use frozen set so we
                            #can use it as a key in a dict

分解数据集的每一个单元素,放入一个集合中

由C1过滤掉不符合最小支持度的单元素,得到L1

def scanD(D, Ck, minSupport):
    #key 项  value次数
    ssCnt = {}
	#遍历数据集
    for tid in D:
	    #遍历频繁项集
        for can in Ck:
		    #某一项是数据的子集
            if can.issubset(tid):
			    #python3语法改变
                if not can in ssCnt: ssCnt[can]=1
                else: ssCnt[can] += 1
	#总数据数
    numItems = float(len(D))
	#非频繁项
    retList = []
	#key 项 value 支持度
    supportData = {}
    for key in ssCnt:
	    #支持度
        support = ssCnt[key]/numItems
        if support >= minSupport:
		    #记录非频繁项
            retList.insert(0,key)
        supportData[key] = support
    return retList, supportData

返回为单元素的非频繁项集,以及单元素频繁项集的支持度。

由Lk得到Ck,由Lk两两合并,得到不重复的Ck    0,1,2       (0,1)   (0,2 )   (1,2)

def aprioriGen(Lk, k): #creates Ck
    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: #if first k-2 elements are equal
                retList.append(Lk[i] | Lk[j]) #set union
    return retList

为了避免不必要的集合重复操作比较两个项集前K-2个元素,如果相同则进行合并。如果相同,前k-2个元素相同,合并之后新项集变为k长度。

由数据集产生一定支持度的频繁项集:

def apriori(dataSet, minSupport = 0.5):
    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)#scan DB to get Lk
        supportData.update(supK)
        L.append(Lk)
        k += 1
    return L, supportData

数据集--C1---L1---...Ck----Lk  返回最终的频繁项集。

4.频繁项集挖掘关联规则

关联规则可信度的定义    规则P--->H可信度:   support(P|H)/support(P)

根据频繁项集先生成一个可能的关联规则集合,然后逐一测试可信度,把不满足可信度的规则去掉

当某一条规则不满足可信度时,那么所有子集也都不满足可信度要求。

由频繁项集以及频繁项集的项与支持度来产生关联规则

def generateRules(L, supportData, minConf=0.7):  #supportData is a dict coming from scanD
    bigRuleList = []
    for i in range(1, len(L)):#only get the sets with two or more items
        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

例如频繁项集L:
[[frozenset({5}), frozenset({2}), frozenset({3}), frozenset({1})], [frozenset({2, 3}), frozenset({3, 5}), frozenset({2, 5}), frozenset({1, 3})], [frozenset({2, 3, 5})], []]

对应的支持度:

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

初始i=1  首先计算长度为1的项集的可信度,直接计算即可,可信度大于0.7 记录下来输出。

def calcConf(freqSet, H, supportData, brl, minConf=0.7):
    prunedH = [] #create new list to return
    for conseq in H:
        conf = supportData[freqSet]/supportData[freqSet-conseq] #calc confidence
        if conf >= minConf: 
            print (freqSet-conseq,'-->',conseq,'conf:',conf)
            brl.append((freqSet-conseq, conseq, conf))
            prunedH.append(conseq)
    return prunedH

一条规则对应左边--右边 ,H对应右边项

freqSet频繁项集  H可以出现在元素右侧的元素列表

计算H的长度,如果频繁项集长度大于len(H)+1,说明H应该继续合并以产生长度更长的集合,计算新集合与频繁项集的可信度,如果新集合中长度大于1,则继续合并。

def rulesFromConseq(freqSet, H, supportData, brl, minConf=0.7):
    m = len(H[0])
    if (len(freqSet) > (m + 1)): #try further merging
        Hmp1 = aprioriGen(H, m+1)#create Hm+1 new candidates
        Hmp1 = calcConf(freqSet, Hmp1, supportData, brl, minConf)
        if (len(Hmp1) > 1):    #need at least two sets to merge
            rulesFromConseq(freqSet, Hmp1, supportData, brl, minConf)

观察了另一位大神的代码,思路清晰多了:

https://blog.csdn.net/hanghangaidoudou/article/details/79306220

规则形式   左边---右边

左边由频繁项集产生   右边首先是长度为1的可能选项,然后通过合并长度来产生更长的长度。例如:

{1}  {2}   {3}     {1,2}    {1,3}  {123}   {1234}

当频繁项的长度l==1时,此时是无法推导出关联规则

l==2时  以{1,2} 可能的规则    12---1     12---2  分别检查每一种的可信度  右边元素记录在H

l>2时,123  首先测试  123-1    123-2    123-3    然后测试123--12   123-13   123-23

1234   1234-1  1234-2  1234-3  1234-4   1234-12  1234-13  1234-14   1234-23  1234-24  1234-34   1234-123  1234-134  1234-234

def getBigRule(freq,support,minConf=0.5):
    '''
    input:  
            freq   : the frequent k-itemset,k=1,2,...n
            support:  corresponding support  
    outpur:
            bigRuleList: a list of all the rule that satisfy min confidence
    '''
    bigRuleList=[]
    m=len(freq)
    for i in range(1,m):
        genRules(freq[i],support,bigRuleList,minConf)
    return bigRuleList
 
def genRules(freq,support,brl,minConf=0.5):
    '''
    extract rules that satisfy min confidence from a list of k-itemset(k>1)
    put the eligible rules in the brl
    '''
	#如果频繁项集为空,则直接返回
    if len(freq)==0:return
	#如果频繁项集每一项长度2   1,2    则规则是1,2---1     1,2---2
    if len(freq[0])==2: #handle 2-itemset
        for itemset in freq:
            for conseq in itemset:
                conseq=frozenset([conseq])
				#集合做差
                conf=support[itemset]/support[itemset-conseq]
                if conf>=minConf:
                    print (itemset-conseq, '-->',conseq,'conf:',conf)
                    brl.append((itemset-conseq,conseq,conf))
    elif len(freq[0])>2:
        H=[]
		# 1,2,3 ---1  2  3
        for itemset in freq:
            # first generate 1-consequence list
			#123--1    123--2   123--3
            for conseq in itemset:
                conseq=frozenset([conseq])
                conf=support[itemset]/support[itemset-conseq]
                if conf>=minConf:
                    print (itemset-conseq, '-->',conseq,'conf:',conf)
                    brl.append((itemset-conseq,conseq,conf))
                    H.append(conseq)
            m=2  
            #  generate 2,...,k-1 consequence
			#  123--12   123--13   123--23
            while m<len(freq[0]):
                H=generateLk(H,m)
                for conseq in H:
                    conf=support[itemset]/support[itemset-conseq]
                    if conf>=minConf:
                        print (itemset-conseq, '-->',conseq,'conf:',conf)
                        brl.append((itemset-conseq,conseq,conf))
                m+=1
				
def generateLk(freq,k):
    '''
    input:
            freq:  the itemset in freq is k-1 itemset
               k:  create k-itemset from k-1_itemset
    output:
            Lk:a list of k-itemset,frequent and infrequent
    '''
    Lk=[]
    for i in range(0,len(freq)-1):
        for j in range(i+1,len(freq)):
            if list(freq[i])[0:k-2]==list(freq[j])[0:k-2]:#fore k-1 item is identity
                Lk.append(frozenset(freq[i]|freq[j]))
    return Lk

猜你喜欢

转载自blog.csdn.net/u014106644/article/details/83589292