从大规模数据集中寻找物品间的隐含关系被称作关联分析(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)