一原理:
为了我们的决策,我们需要从数据海洋中寻找元素之间的隐含关系(注意:这里的隐含很重要,因为数据量很大的情况下,人脑很难胜任这种复杂的计算),基于这些关联规则分析,我们可以更好的理解我们客户的行为。但问题是,元素之间的关系往往需要大量计算,为了在合理的时间范围内寻找频繁项集和关联规则,可以使用Apriori算法。
二 Apriori算法基如下结论:
如果一个项集是非频繁的,那么这个项集的超集也是非频繁的,这样可以减少我们关注的项集的个数。如果R->H不满足可信度要求,那么subset(R)->H肯定也不会满足。
三 基本过程:
首先,定义两个量化指标,支持度和可信度。
支持度用来衡量某个项集在样本集中出现的频率,出现频率高的作为频繁项集。可信度用来衡量元素之间的关联关系,如上面例子,买尿布的人当中,同时买葡萄酒的人越多,说明这种倾向就越明显,也就是关联关系越明显(同时买尿布和葡萄酒的是单独买尿布的子集,固定分母,分子越大,说明这类人中买葡萄酒的人越多)。其实,支持度就是集合出现的概率,可信度就是条件概率。P(A)=counter(A)/Counter(total) A->B P(B|A)=p(AB)/P(A) p(AB)<P(A)或P(B)
我们可以根据输入样本集合,构造初始集合,初始集合只包含单个元素组合,记做C1, 然后计算符合支持度(实际上,就是一个算法的度量指标,在样本集中出现的次数(是否为子集)/样本总数,即该元素出现的概率,很明显,概率越大,出现的频率越高,支持度越高吗,相应关联度也越大),不断迭代,通过Ck-1生成Ck(通过元素组合,每次取k-1前缀相同的集合然后取并集即可,想想A(4,4)是咋计算的就明白了),不断过滤掉不符合支持度的样本组合,直到无法找到新的组合为止,这样我们就得到了所有符合支持度的元素组合集合。
得到符合支持度的集合和对应支持度的列表,我们可以基于此计算可信度,R->H conf 条件:Count(R U H)>=2 Count(H)<=Count(R U H)-1 可信度的计算: conf(R->H)=S(R U H)/S(R),我们会先固定RUH,取符合支持度的集合列表且元素个数大于等于2 (RUH),根据符合支持度的集合列表得到单个元素,然后计算到单个元素及其组合的可信度,选出符合条件的,放到列表中,元素为元祖(R,H,conf) ,这里会用到一个理论:如果R->H不满足可信度要求,那么subset(R)->H肯定也不会满足。
貌似监督类的机器学习算法,试图利用样本,枚举“所有可能性”(涉及到一些数据过滤,比如剪枝,尽量减少数据计算量),并通过一定的指标评估这些可能性,得出某种结论(量化的)。而非监督类的机器学习算法,也试图利用样本,也是度量一定的指标,但总是会形成数学模型,然后利用这种模型去进行预测。//没想明白。。。。。呵呵呵呵。。。。。
四。算法实现
import matplotlib.pyplot as plt
import numpy as np
import random
from numpy import *
from operator import *
def loadDataSet():
return [[1,3,4],[2,3,5],[1,2,3,5],[2,5]]
#创建C1集合,包含单个元素的集合,这里假设数据集包含两层
def createC1Set(dataSet):
c1=[]
for items in dataSet:
for item in items:
#元素未包含在集合中,就添加,转化成单个列表元素
if not item in c1:
c1.append([item])
#使用默认排序规则进行排序
c1.sort()
print(c1)
#转化成单个集合元素的list
c1list = list(map(set,c1))
c2list=[]
#这里自己实现了个转换函数,比较长,看着比较恶心
for i in c1list:
if not i in c2list:
c2list.append(i)
c2list=list(map(frozenset,c2list))
print(c2list)
return c2list
def scanD(D,ck,minSupport):
#记录子集的出现个数
counterDict={}
for item in D:
for k in ck:
#print(type(item),type(k))
#查看k是否为总的样本集合的子集
if k.issubset(item) :
#统计子集的出现次数
#集合的key只能为可以hash的类型(非可变类型),set不能hash,需要转换下
if not k in counterDict:
counterDict[k]=1
else:
counterDict[k]+=1
print('样本出现频率:\n',counterDict)
#总的样本数
totalCount=len(D)
retList=[]
supportDict={}
#计算支持度
for key in counterDict.keys():
support=(counterDict[key])/totalCount
#如果大于传入的支持度,就保留下来
if support>=minSupport :
retList.append(key)
supportDict[key]=support
print('符合支持度的候选项集:\n',retList)
print('各个候选项集的支持度:\n',supportDict)
return retList,supportDict
#生成列表,列表元素包含k个元素的集合,创建Ck
def aprioryGen(Lk,k):
retList=[]
length=len(Lk)
for i in range(length):
for j in range(i+1,length):
#注意每次集合元素个数加1,需要比较前缀是否相同,只有相同的才能合并,固定k-2,添加k-2+1个元素
#并集生成新的元素
#检查Lk[i]和Lk[j]的k-2的前缀是否相同
L1=list(Lk[i])[:k-2]
L2=list(Lk[j])[:k-2]
L1.sort()
L2.sort()
if L1==L2:
retList.append(Lk[i].union(Lk[j]))
#print('生成的Ck列表:\n',retList)
return retList
#apriori算法实现
#原理:如果一个项集是非频繁的,那么这个项集的超集也是非频繁的,这样可以减少我们关注的项集的个数。
#我们可以发现那些频繁出现的项集,评价的标准也是使用该项集出现的概率,出现的概率越大,表明越频繁
#输入数据集 最小支持度
#返回不同元素个数组合的大于等于最小支持度的元素集合
def apriori(dataSet,minSupport=0.5):
#将传入的数据集-元素为列表的-列表转换成-元素为集合的-列表
listDataSet = list(map(set, dataSet))
#创建C1集合,即列表元素为集合;而集合只有一个元素
c1 = createC1Set(dataSet)
#计算符合支持度的集合元素
retList,supportDict=scanD(listDataSet,c1,minSupport)
#定义列表存储所有满足支持度条件的集合元素
L=[retList]
k=2
#不断遍历,直到找到所有满足支持度条件且不同元素的个数组合的集合元素
while len(L[k-2])>0 :
#根据Ck-1产生Ck组合
retListCk=aprioryGen(L[k-2],k)
#对Ck组合评估支持度
Lck, supportDictCk=scanD(listDataSet,retListCk,minSupport)
#收集符合支持度的Ck
L.append(Lck)
supportDict.update(supportDictCk)
k+=1
return L,supportDict
#关联规则生成函数
#输入:频繁项集L 对应的支持度集合 关联规则的可信度
def genRules(L,supportDict,minReliability=0.5):
#存储所有符合可信度的规则列表,元素格式:(R,H,conf)
bigRules=[]
#R->H conf Count(R U H)>=2 Count(H)<=Count(R U H)-1 conf(R->H)=S(R U H)/S(R)
#遍历频繁项集,从第1个开始(总是从0开始),即集合元素至少要两个
for i in range(1,len(L)):
#H中的元素肯定来源于R中的元素及其组合,现在考虑H只有两个元素的情况
for RUH in L[i]:
#取出里面的每个元素,把单个元素作为一个不变集合,frozenset(x) x必须是可遍历的
singleElemFroSet=[frozenset([item]) for item in RUH]
m = 1
LenR = len(RUH)
HSet = singleElemFroSet
LenH = len(HSet[0])
while LenR > LenH:
# 计算可信度
for H in HSet:
# 这里使用差集还是原集??? 感觉使用原集更好理解吧??
conf = supportDict[RUH] / supportDict[RUH-H]
if conf >= minReliability:
# 如果可信,记录到规则列表
bigRules.append((RUH-H, H, conf))
m += 1
HSet = aprioryGen(HSet, m)
LenH = len(HSet[0])
return bigRules
dataSet=loadDataSet()
L,supportDict=apriori(dataSet,0.5)
print("所有元素为:\n",mat(dataSet))
print('所有符合支持度的Ck:\n', L)
print('所有组合的支持度:\n', supportDict)
bigRules=genRules(L,supportDict,0.5)
print('规则列表为:\n',bigRules)
from collections import Counter
#注意
ls=[1,2,3]
print(set(ls))
ls=[[1],[2],[3]]
#TypeError: unhashable type: 'list'
#print(set(ls))
t=(1,2,3)
print(set(t))
t=((1),(2),(3))
print(set(t))
t=[(1),(2),(3)]
print(set(t))
t=([1],[2],[3])
#元素为list,不可hash类型,无法使用set()
#print(set(t))
print(list(map(set,ls)))
ls=[1,2,3,2]
print(Counter(ls))
ls="1 1 1 2 2 2"
dicCounter=Counter(ls)
print(dicCounter)
#注意跟字典的update方法的区别
dicCounter.update("1 1 1")
print(dicCounter)
dic={'1':1,'1':1,'2':2}
print(dic)
#更新对应key的值,没有就新增
dic.update({'1':2,'3':3})
print(dic)
L=[]
ls=[[1],[2],[3]]
#添加元素,非添加引用
L.append(ls)
print(L)