从大规模数据集中寻找物品间的隐含关系被称作关联分析(association analysis)或者关联规则学习(association rule learning)。
优点:简单
缺点:对大数据集比较慢
使用数据类型:数值型或者标称型
一、相关定义:
频繁项集:经常出现在一起的物品集合
关联规则:两种物品之间存在很强的关系,表示为P->H
support支持度:该项集在所有数据集中出现的次数所占的比例,Support(P,H) = NUM(P,H) / N
confidence置信度:Confidence(P->H) = support({P,H}) / support({P}) = P(H|P)
二、使用Apriori算法发现频繁项
原理:如果某个项集是频繁的,那么它的子集也是频繁的,也就是说如果一个项集是非频繁的,那么它的超集也是非频繁的。
输入:数据集D,支持度阈值s
输出:最大频繁k项集
1. k=1, 扫描整个数据集,得到所有出现过的数据,作为初始候选频繁1项集candiItem1
2. 计算频繁k项集
a) 计算候选频繁k项集的支持度
b)去掉所有支持度小于阈值s的项集,得到频繁k项集。
c)如果频繁k项集为空,则直接返回频繁k-1项集,算法结束。如果得到的频繁项集只有一项,直接返回频繁k项集,算法结束
d) 基于频繁k项集,连接生成候选频繁k+1项集
3. 令k=k+1,进入步骤2
实现代码:
def loadDataSet(): return [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]] def createC1(DataSet): """ 创建初始候选频繁项集c1 :param DataSet: :return: """ C1 = [] for lineSet in DataSet: for item in lineSet: if not [item] in C1: C1.append([item]) C1.sort() return list(map(frozenset,C1)) #use forzen set so we can use it to as a key in dict def getLk(DataSet, Ck, minSupport): """ 返回ck的频繁项集,和支持度 :param C: :return: """ Lk = []; #频繁项集 Cksupport = {}; #CK的支持度 Lksupport = {}; #LK的支持度 numItem = float(len(DataSet)) for C in Ck: for D in DataSet: if set(C).issubset(set(D)): if C not in Cksupport: Cksupport[C] = 1 else: Cksupport[C] += 1 for key in Cksupport: sup = Cksupport[key] / numItem if sup >= minSupport: Lk.append(key) Lksupport[key] = sup return Lk, Lksupport def aprioriGen(Lk): """ 根据频繁项集LK生成Ck+1 :param Lk: :return: """ Ck = [] for i in range(len(Lk)-1): for j in range(i + 1, len(Lk)): c = list(set(Lk[i]).union(set(Lk[j]))) if c not in Ck: Ck.append(c) return list(map(frozenset, Ck)) def aprior(DataSet, minSupport=0.5): """ 生成频繁项集 :param DataSet:原始数据集 :return: L:满足最小支持度的频繁项集 supportData:支持度数据集 """ k = 1 C1 = createC1(DataSet) L1, supportData = getLk(DataSet, C1, minSupport) L = [L1] C = [C1] while(len(L[-1]) > 1): k += 1 C.append(aprioriGen(L[-1])) Lk, LkSupport = getLk(DataSet, C[k-1], minSupport) L.append(Lk) supportData.update(LkSupport) # if len(L[-1]) == 1 or len(L) <= 1: # for item in L[-1]: # supportData.update({item : LSupport[item]}) # return L[-1], LSupport # else : # for item in L[-2]: # supportData.update({item : LSupport[item]}) # return L[-2], LSupport return L, supportData if __name__ == '__main__': DataSet = loadDataSet() L, LSupport = aprior(DataSet, 0.7) print(L, LSupport)
结果:
三、从频繁项中挖掘关联规则
一条规则P->H的置信度为support(P,H)/support(P)
输入:最大频繁项集L,对应的支持度数据集supportData,最低置信度minConf
输出:满足最低置信度的规则bigRuleList
对每个频繁项集Li:
如果元素个数大于等于2:
生成关联规则(获取单个元素的H1, P=Li-Hk)
计算规则置信度,将置信度大于minConf的规则存入bigRuleList
while:H的长度小于len(Li)-1:
根据Hk,生成关联规则(获取H(k+1), P=Li-H(k+1))
计算规则置信度,将置信度大于minConf的规则存入bigRuleList
返回bigRuleList
实现代码:
def generateRules(L, supportData, minConf=0.7): """ 生成满足最小可信度的关联规则 :param L: 最大频繁项集 :param supportData: 支持度数据集 :param minConf: 最低可信度 :return: 满足最小可信度的关联规则 """ bigRuleList = [] for i in range(len(L)): for freqSet in L[i]: if len(freqSet) >= 2: H1 = [frozenset([item]) for item in freqSet] prunedH = calConf(freqSet, supportData, minConf, H1, bigRuleList) while len(prunedH) < len(H1) - 1: Hk = aprioriGen(prunedH) #CREATE H(K+1) prunedH = calConf(freqSet, supportData, minConf, Hk, bigRuleList) def calConf(Lk, supportData, minCof, H, bigRuleList): """ 计算规则的可信度,返回满足最小可信度的H :param Lk: 频繁项集 :param supportData: 支持度 :param minCof: 最小可信度 :param H: 规则的后件集合 :param bigRuleList: 满足最小可信度的生成规则 :return: prunedH 满足最小可信度的后件 """ prunedH = [] confData = {} for conseq in H: conf = supportData[Lk] / supportData[frozenset(Lk)-frozenset(conseq)] if conf >= minCof: print(Lk-conseq, '-->', conseq, 'conf:', conf) bigRuleList.append((Lk - conseq, H, conf)) prunedH.append(conseq) return prunedH if __name__ == '__main__': DataSet = loadDataSet() L, LSupport = aprior(DataSet, 0.7) print(L, LSupport) generateRules(L, LSupport, 0.5)