Apriori算法通常用于发现样本间的某种关系,比如超市购物中心,通常会根据用户的数据,发现买牛奶的人通常也会买西瓜这样的关系, 来安排把牛奶和西瓜捆绑在一起进行销售。
Apriori的核心思想:
1.发现样本中的频繁集
2.从频繁集中挖掘关联规则
频繁集: 就是样本中出现的次数多的集合(这个多是相对的,算法需要定义一个度来表示什么才是真正的频繁) x(i)/n
看下图:
上图可以看到, 比如我们有5个商品分别是A,B,C,D,E. 现在从样本中我们看到集合{A,C,D} {B,C,E} {A,B,C,E} {B,E}. 能够获取出单个商品的频繁度, A出现了2次, b出现了3次
c出现了3次等,之后我们假定频繁度要大于1才可以,这样我们就把D这个单独的集合给丢弃了,现在满足频繁度的就只剩下 ABCE了
PS:丢弃这个思想是怎么来得呢? 可以这么考虑, A如果是一个集合{A} , 如果我认为A出现的频繁度很低,不予考虑的话, 那么{A,B}这样的集合出现的概率是比也是很低的,
那是不是更不需要考虑了呢。 这样带来的好处就是减少了很多的计算量。
随后在ABCE中继续筛选频繁度,看下图:
持续的对于频繁度的筛选,最终可以获取满足频繁度的所有可能的集合,之后就是根据这个频繁度的集合列表进行关联规则的生成
python实现:
import numpy as np
def loadDataSet():
return [[1,3,4],[2,3,5],[1,2,3,5],[2,5]]
def createC1(dataset):
c1 = []
for transaction in dataset:
for item in transaction:
if not [item] in c1:
c1.append([item])
c1.sort()
return map(frozenset,c1)
def scanD(D,Ck,minsupport):
ssCnt = {}
for tid in D:
for can in Ck:
if can.issubset(tid):
if not ssCnt.has_key(can):
ssCnt[can] = 1
else:
ssCnt[can] += 1
numItems = float(len(D))
retList = []
supportData = {}
for key in ssCnt:
support = ssCnt[key]/numItems
if support >= minsupport:
retList.insert(0,key)
supportData[key] = support
return retList,supportData
def aprioriGen(Lk,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):
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)
L.append(Lk)
k += 1
return L,supportdata
dataset = loadDataSet()
ret,support = apriori(dataset)
print support
怎么来获取隐含的关联规则呢? 对于关联规则,我们也有量化方法,叫做可信度。
可信度: support(p|H) /support(p)
套用这个公式,就可以算出每个商品之前的关系了
比如: B --> E , sup(B,E)/sup(B) sup就是上面频繁度字典中的各个集合的值
BE-->C ,sup(b,e,c) / sup(b,e)
PS:注意,只能顺序关联,不能逆向关联,求出的可信度只能说明买了b的商品的人会买e 不能倒过来,倒过来的话要重新计算
当然我们也要和频繁度一样设定一个我们的可信度值,来丢弃那些我们认为没有太多关联的规则。