关联分析:从大规模数据集中寻找物品间的隐 含关系被称作关联分析(association analysis)或者关联规则学习(association rule learning)。关联分析是一种在大规模数据集中寻找有趣关系的任务。这些关系可以有两种形式:频繁项 集或者关联规则。
频繁项集:频繁项集(frequent item sets)是经常出现在一块的物品的集合。
关联规则:暗示两种物品之间可能存在很强的关系。
支持度:数据集中包含该项集的记录所占的比例。
可信度:针对一条诸如{尿布}->{葡萄酒}的关联规则来定义的。这条规则的可行度被定义为“支持度{尿布,葡萄酒}/支持度{尿布}”
支持度和可信度是用来量化关联分析是否成功的方法
当商品数量大的时候,如果要遍历每一种可能集合的支持度,计算时间是不允许的。为了降低所需的计算时间,我们可以采用Apriori 原理来帮我们减少可能感兴趣的项集。Aprori原理是说,如果某个项集是频繁的,那么他的所有自己也是频繁的。也就是说如果一个项集是非频繁集,那么他的所有超集也是非频繁的。
Apriori算法原理:Apriori算法是发现频繁项集的一种方法。Apriori算法的两个输入参数分别是小支持度和数 据集。该算法首先会生成所有单个物品的项集列表。接着扫描交易记录来查看哪些项集满足小 支持度要求,那些不满足小支持度的集合会被去掉。然后,对剩下来的集合进行组合以生成包 含两个元素的项集。接下来,再重新扫描交易记录,去掉不满足小支持度的项集。该过程重复 进行直到所有项集都被去掉。
加载数据集
def loadDataSet():
return [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]
创建集合C1,对dataset去重,排序,放入list表,转换所有元素为frozenset,C1是大小为1的所有候选项集的集合
def createC1(dataSet):
C1 = []
for transaction in dataSet:
for item in transaction:
if not [item] in C1:
# 遍历所有的元素,如果不在 C1 出现过,那么就 append
C1.append([item])
# 对数组进行 `从小到大` 的排序
C1.sort()
# frozenset是指被“冰冻”的集合,就 是说它们是不可改变的,即用户不能修改它们。这里必须要使用frozenset而不是set类型,因为之后 必须要将这些集合作为字典键值使用,使用frozenset可以实现这一点,而set却做不到。
return map(frozenset, C1) 对C1中的每个项构建一个不变集合
计算候选集CK在数据集D中的支持度,并返回支持度大于最小支持度的数据
def scanD(D, Ck, minSupport):
# ssCnt 临时存放选数据集 Ck 的频率. 例如: a->10, b->5, c->8
ssCnt = {}
for tid in D:
for can in Ck:
# s.issubset(t) 测试是否 s 中的每一个元素都在 t 中
if can.issubset(tid):
if not ssCnt.has_key(can):
ssCnt[can] = 1
else:
ssCnt[can] += 1
numItems = float(len(D)) # 数据集 D 的数量
retList = []
supportData = {}
for key in ssCnt:
# 支持度 = 候选项(key)出现的次数 / 所有数据集的数量
support = ssCnt[key]/numItems
if support >= minSupport:
# 在 retList 的首位插入元素,只存储支持度满足频繁项集的值
retList.insert(0, key)
# 存储所有的候选项(key)和对应的支持度(support)
supportData[key] = support
return retList, supportData
整个Apriori算法的伪代码:
当集合中项的个数大于0时
构建一个k个项组成的候选项集的列表
检查数据以确认每个项集都是频繁的
保留频繁项集并构建k+1项组成的候选项集的列表
完整apriori算法python代码
# 输入频繁项集列表 Lk 与返回的元素个数 k,然后输出所有可能的候选项集 Ck
def aprioriGen(Lk, k):
"""
前k-2个项相同时,将两个集合合并成为一个大小为k的集合
"""
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:
retList.append(Lk[i] | Lk[j])
return retList
# 得到频繁项集。
def apriori(dataSet, minSupport=0.5):
"""
扫描数据集,从Ck得到Lk
"""
C1 = createC1(dataSet)
D = 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)
supportData.update(supK)
if len(Lk) == 0:
break
L.append(Lk)
k += 1
return L, supportData
计算可信度
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 generateRules(L, supportData, minConf=0.7):
bigRuleList = []
for i in range(1, len(L)):
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
从原理上来说Apriori原理并不难理解,如果一个项集是非频繁集,那么他的所有超集也是非频繁的。基于这个思想,我们可以从集合项数小的从小到大依次构造,这个过程中会减去一些已经因为支持度小,被排除掉的候选集,这样可以避免集合组合的指数级增长,大大提高了算法效率。python代码实现,具有比较技巧性,因此在学习过程中感觉还是收获到不少python技巧的。
机器学习实战 Machine learning in action 美Peter Harrington 著 人民邮电出版社
APACHECN学习笔记[https://github.com/apachecn/AiLearning/blob/master/docs/ml]