关联规则
1、基础知识
在购买计算机的顾客中,有30%的顾客同时购买了打印店,那么打印机和计算机之间有一定关联。
关联:若两个或多个变量的取值之间存在某种规律
关联规则:寻找在同一事件中出现不同项的相关性
1、基础
1、一个样本称为“事务”
2、多个事务由多个属性来确定,属性称为“项”
3、多个项组成的集合称为“项集”
{牛奶}1项集
{牛奶,咖啡}2项集
3、x==>y:
x和y是项集
x:规则前项 antecedent
y:规则后项 consequent
2、支持度support
一个项集或者规则在所有事务中出现的频率
s(X)=σ(X)/N
σ(X):表示项集X的支持度计数
N:所用事务的数量
3、置信度confidence
确定y在包含x的事务中出现的频繁程度
(反应了购买了项目集X中的商品的顾客同时也购买了Y中商品的可能性有多大)
c(X → Y) = σ(X∪Y)/σ(X)
=p(Y│X)=p(XY)/p(X)
注意:可能与support有些混淆
置信度是存在方向的,所以X → Y也会Y → X
4、提升度lift:
lift(A==>B)=confidence(A==>B)/support(B)=p(B|A)/p(B)=p(AB)/p(A)p(B)
if lift=1,X与Y独立,X对Y出现的可能性没有提升作用,
其值越大(lift>1),则表明X对Y的提升程度越大,也表明关联性越强。
2、库函数应用
- pip install mlxtend#需提前下载包
1、数据预处理
import pandas as pd
from mlxtend.frequent_patterns import apriori
from mlxtend.frequent_patterns import association_rules
retail_shopping_basket = {'ID':[1,2,3,4,5,6],
'Basket':[['Beer', 'Diaper', 'Pretzels', 'Chips', 'Aspirin'],
['Diaper', 'Beer', 'Chips', 'Lotion', 'Juice', 'BabyFood', 'Milk'],
['Soda', 'Chips', 'Milk'],
['Soup', 'Beer', 'Diaper', 'Milk', 'IceCream'],
['Soda', 'Coffee', 'Milk', 'Bread'],
['Beer', 'Chips']
]
}
retail = pd.DataFrame(retail_shopping_basket)
需要将retail.Basket的数据转换成one-hot代码,才能运用库函数
#得到retail_id列
retail_id = retail.drop('Basket' ,1)
#将retail.Basket数据转换为one-hot
retail_Basket = retail.Basket.str.join(',')
retail_Basket = retail_Basket.str.get_dummies(',')
#得到所需数据
retail = retail_id.join(retail_Basket)
2、库函数代入
## apriori:从一个独热编码的DataFrame中获取频繁项集。该方法基于Apriori算法,根据最小支持度筛选出频繁项集,
# 可以用于发现数据中频繁出现的组合。
frequent_itemsets_2 = apriori(retail.drop('ID',1), use_colnames=True)
## association_rules:生成关联规则的DataFrame,包括指标如’支持度’、'置信度’和’提升度’等。
# 可以根据指定的关联规则评价指标和最小阈值筛选出具有一定关联性的规则。
association_rules(frequent_itemsets_2, metric='lift')
3、代码书写
1、思路:
1、
一个项集是非频繁集,那么它的所有超集也是非频繁集
这是简便运算的关键
若23是非频繁集,那么同时包含23的均是非频繁集,均不满足最低阙值
2、
2.1总体思路:
数据–ScanD----->C1(所有的1项集)-----------计算support>阙值的保留------>L1(满足阙值的1项集)
L1-----ScanD----->C2(所有满足条件的2项集)—计算support>阙值的保留------>L2
由小向大计算
2.2注意:
怎样得到三项集呢?需要满足二项集中第一位数相同,{2,3},{2,5}均以2开头
推到多项集:需满足k-2个头相同
因为,其余不满足的就是非频繁的超集了,算出support也不满足阙值,就简便运算啦
2、apriori==>support,
主要的程序思路
def apriori(dataSet,minSupport=0.5):
C1 = createC1(dataSet)#创建1项集
L1,supportData = scanD(dataSet,C1,minSupport)#判断条件(>阙值)
#L1=[],L=[[]]多一维了
L = [L1]#满足条件的项集
k = 2
while(len(L[k-2]) > 0):#
CK = aprioriGen(L[k-2],k)#得到多项集
LK,supk = scanD(dataSet,CK,minSupport)
supportData.update(supk)
L.append(LK)
k += 1
return L,supportData
C1创建,1项集的创建
def createC1(dataSet):
C1 = []
for transaction in dataSet:#得到每一条数据[1,3,4]
for item in transaction:#得到条数据中的每一项1
if not [item] in C1:
C1.append([item])
#主要是提取出所有数据中出现的项
C1.sort()#进行排序
#将其映射成为不可更改的集合
return list(map(frozenset,C1))
ScanD扫描算法,主要得到符合条件的项集
def scanD(D,CK,minSupport):
ssCnt = {}#字典格式,记录每个项在数据出现的频数,相当于C1
#再次将数据遍历一遍
for tid in D:#每行数据
for can in CK:#得到的项集中的每一项
if can.issubset(tid):#若项集是数据的子项
if not can in ssCnt:#若第一次出现未知字典格式中,加入并记初值为1
ssCnt[can] = 1
else:
ssCnt[can] += 1#再次出现,记录+1
numItems = float(len(list(D)))#记录总共有多少数据,用来算概率
retlist = []#记录满足条件的项集
supportData = {}#记录算得的support值
for key in ssCnt:#字典格式保存项出现的频数
support = ssCnt[key]/numItems
if support >= minSupport:#判断是否大于阙值,确定是否是频繁集
retlist.insert(0,key)
supportData[key] = support
return retlist,supportData#满足条件的项集,全部的项集及support记录
多项集使用,为了选出频繁集
def aprioriGen(LK,k):
retlist = []
lenLK = len(LK)
for i in range(lenLK):#注意L的存储格式
#L=[[5,2,3,1],[(2,3),(3,5)]]不同数量的项集各组成一个list
for j in range(i+1,lenLK):
L1 = list(LK[i])[:k-2]
L2 = list(LK[j])[:k-2]
if L1 == L2:#1项集时,两者均为空
#连接到新项集
retlist.append(LK[i]|LK[j])
return retlist
与图相同的数据
def loadDataSet():
return [[1,3,4],[2,3,5],[1,2,3,5],[2,5]]
主代码,进行输出:
if __name__ == '__main__':
dataSet = loadDataSet()#得到数据
L,support = apriori(dataSet)
i = 0
for freq in L:
print ('项数',i+1,':',freq)
i+=1
结果:
3、association_rules
(掌握的不好,代码存在一点错误)