您的位置:首页 > 编程语言 > Python开发

Apriori

2015-07-18 09:05 771 查看
# -*-coding:utf-8-*-
'''
Apriori
'''
import numpy as np

def loadDataSet():
return [[1,3,4],[2,3,5],[1,2,3,5],[2,5]]

def createC1(dataSet):
'''
大小为1的所有候选项集合
'''
C1 = []
for _transaction_ in dataSet:   # 每一条记录
for _item_ in _transaction_:  # 每一条记录中的每一项
if [_item_] not in C1:    # 如果没有出现在C1出现:
C1.append([_item_])   # 将只包含item的一个列表添加到C1中
C1.sort()   # 排序
return map(frozenset,C1) # map:[f(x) for x in C1] frozenset是不可改变的集合

def scanD(D,Ck,minSupport):
'''
数据集CK,包含候选项集合的列表D,最小支持度
扫描数据集判断只有一个元素的项集是否满足最小支持度
'''
_ssCnt = {}
for _tid_ in D:   # 遍历数据集中的所有记录
for _can_ in Ck:    # 遍历所有候选项集
if _can_.issubset(_tid_):   # 如果Ck中的项是记录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):
'''
每项所含元素个数:n ————> n+1
输入:频繁项集列表Lk + 项集元素个数k
eg. {0} {1} {2} ---> {0,1},{0,2},{1,2}
'''
retList = []
_lenLk = len(Lk)    # 项数
for i in range(_lenLk):  # 对Lk中的每一项
L1 = list(Lk[i])[:k-2]  # 项中元素[第一个:倒数第二个]
L1.sort()   # 排序
for j in range(i+1,_lenLk):  # 对Lk中除Lk[i]以外的每一项
L2 = list(Lk[j])[:k-2]  # 项中前k-1个元素列表
L2.sort()   # 排序
if L1 == L2:
retList.append(Lk[i] | Lk[j])
return retList

def apriori(dataSet,minSupport=0.5):
'''
数据集 ,最小支持度
当集合中项的个数大于0时:
构建一个由k个项组成的候选项集的列表
检查数据以确认每个项集都是频繁的
保留频繁项集并构建k+1项组成的候选项集的列表
'''
C1 = createC1(dataSet)  # 数据--->单项
D = map(set,dataSet)    # 数据集--->集合
L1,supportData = scanD(D,C1,minSupport) # 支持度大于阈值的单元素集合|项集支持度字典
L = [L1] # 只有单项的集合,接下来生成2元素项集,3元素项集,。。。
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

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_]    # 只含单个元素集合的列表H1
if (i > 1): # 项的元素数目>2,进一步合并
rulesFromConseq(_freqSet_,_H1,supportData,bigRuleList,minConf)
else:   # 项只有2个元素,直接计算可信度
calcConf(_freqSet_,_H1,supportData,bigRuleList,minConf)
return bigRuleList

def calcConf(freqSet,H,supportData,br1,minConf=0.7):
'''
项集只含两个元素
 频繁项 |频繁项拆分为单元素列表|所有频繁项的支持度字典|空列表|最小可信度阈值
 计算由给定频繁项产生的所有满足最小可信度阈值的关联规则
'''
prunedH = []
for _conseq_ in H:    # 遍历H中的两元素
'''
eg. {1}--->{2}的可信度计算:{1,2}.支持度 / {1}.支持度
{2}--->{1}的可信度计算:{1,2}.支持度 / {2}.支持度
'''
_conf = supportData[freqSet] / supportData[freqSet - _conseq_]
if _conf >= minConf:
print freqSet-_conseq_ , '--->', _conseq_ ,'conf:' , _conf
br1.append((freqSet-_conseq_ , _conseq_ , _conf))
prunedH.append(_conseq_)
return prunedH

def rulesFromConseq(freqSet,H,supportData,br1,minConf=0.7):
'''
从最初的项集中生成更多的关联规则
'''
m = len(H[0])   # m = 1
if (len(freqSet) > (m+1)): # 项集中含有多于2个元素
_Hmp1 = aprioriGen(H,m+1)    # m元素 ---> m+1元素
_Hmp1 = calcConf(freqSet,_Hmp1,supportData,br1,minConf) # 满足可信度阈值的项集集合
if (len(_Hmp1) > 1):  # 如果不止一条规则满足要求
rulesFromConseq(freqSet,_Hmp1,supportData,br1,minConf)   # 判断是否可以合并规则

dataSet = loadDataSet()
L,suppData = apriori(dataSet,minSupport=0.5)
rules = generateRules(L,suppData,minConf=0.7)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息