1. Apriori算法
Apriori算法是一種挖掘關聯規則的頻繁項集算法,這些關係有兩種形式 : 頻繁項集和關聯規則。
舉個例子就知道了:著名的”尿布與啤酒”。
這就是通過關聯分析來獲取到的結果。
2. 名詞解釋
前後文中存在的名詞都放在這裏了
1. 頻繁項集 : 在事件集合中出現頻繁的項目
2. 關聯規則 : 尿布-啤酒 關聯等等 說明有很大的機率同時出現
3. 支持度:該項出現的次數/數據集的大小
4. 置信度:對於尿布-啤酒這一關聯 置信度的定義 支持度(尿布與啤酒)/支持度(尿布)
一般的,A-B置信度 : conf(A-B) = support(AB)/support(A),這也是關聯規則中很重要的依靠的一個數據
3. 主要算法僞代碼以及思想
主要思想
- 先計算各項的支持度,然後計算其置信度,如果直接運算如此多的數據,會有很大的計算開銷,那麼這時候你就要給算法一個閾值或者說是支持度置信度最小值,如果比這個值小就在後續中“剪”掉,這樣一來就會節省很多時間………
- 所謂的Apriori原理,是說如果一個項是頻繁的,那麼他的子集也是頻繁的,看他的逆否命題:一個項非頻繁,那麼他的超集也是非頻繁的……是不是很有道理……例如:{{0},{1}}頻繁 , 那麼{0},{1}也頻繁;如果{0}非頻繁,那麼{{0},{1}}就是非頻繁……..或者把01換成實際生活中盒裝奶與吸管…..理解一下…..
優缺點
優點 : 算法簡單
缺點:數據過大運算量大
僞代碼
# 1. scanData 生成頻繁項集
for 數據集中的每條交易記錄item:
for 每個候選項集elem:
檢查elem是否是item的子集
如果是,則增加elem的計數
for 每個候選項集:
如果其支持度不低於最小值,則保留該項集以及支持度
返回所有頻繁項集列表以及對應支持度列表
# 2. AprioriGen 生成候選項集
for i-len(頻繁項集)
for i+1-len(頻繁項集)
合併操作
返回候選集
# 3. Apriori 算法
當頻繁項集中的項的個數大於0時:
生成候選集(AprioriGen 函數)
計算候選項集的支持度,刪除非頻繁項集
生成頻繁項集(scanData 函數)
返回頻繁項集以及對應支持度
# 4. 關聯規則挖掘見代碼註釋...
4. 代碼
# coding:utf-8
from numpy import *
def loadSimpleData():
return [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5]]
def creatC1(data): # 創建一個候選集合 其中包含幾個size爲1的小集合
c1 = [] # python不允許一個集合只包含一個數字 所以用list代替 [[],[],[],[]]
for item in data: # for "賬單"條目
for elem in item: # for 條目的每個元素
if [elem] not in c1:
c1.append([elem])
c1.sort() # sort to 123...
return map(frozenset, c1) # frozen意爲凍住的,返回一個不可更改的list
def scanData(data, Ck, minSupport): # creat Lk from Ck (L代表頻繁集 C代表候選集)
appearNum = {} # 記錄候選集在數據中出現的次數
for item in data: # for 數據條目
for elem in Ck: # for 候選集元素
if elem.issubset(item): # 如果候選集出現在條目中
if not appearNum.has_key(elem): # 計數操作
appearNum[elem] = 1
else:
appearNum[elem] += 1
sum = float(len(data)) # 數據總條目數 float
Lk = [] # LK記錄
supportData = {} # 支持度的list
for elem in appearNum:
support = appearNum[elem] / sum # 計算支持度
if support >= minSupport: # 是否大於最小支持度
Lk.append(elem)
supportData[elem] = support
return Lk, supportData # 返回頻繁項集 以及 支持度
def AprioriGen(Lk, k): # creat Ck+1 form Lk
Ck = []
lenLk = len(Lk)
for i in range(lenLk):
for j in range(i + 1, lenLk): # 合併的過程很巧妙
l1 = list(Lk[i])[:k - 2] # 例如過程 [0] [1] [2] -> [01] [02] [12] -> [012]
l2 = list(Lk[j])[:k - 2] # [01][02][12]直接合並會出現3組[012]需要去重
l1.sort() # 而利用k-2這個篩選條件就只會出現 01|02 -> 012 這一種情況,以此類推
l2.sort()
if l1 == l2:
Ck.append(Lk[i] | Lk[j]) # 集合並集
return Ck # 返回候選集
def Apriori(data, minSupport=0.5): # minSupport is default 0.5
c1 = creatC1(data)
D = map(set, data) # 內部去重 例如[1,1,2]->[1,2] ?
L1, supportData = scanData(data, c1, minSupport)
L = [L1] # L集合存放了長度爲i的頻繁項集
k = 2 # k=2 設計很巧妙
while len(L[k - 2]) > 0:
Ck = AprioriGen(L[k - 2], k) # 從LK 生成 CK
Lk, supportLK = scanData(D, Ck, minSupport)
supportData.update(supportLK)
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] # 拆分每個頻繁項
''' 理解註釋 '''
# print "index is :", i
# print "freqSet :", freqSet
# print "H1 :", H1
''' 理解註釋 '''
if i > 1: # 如果大於兩個元素 需要進一步關聯規則生成以及判斷置信度
rulesFromConseq(freqSet, H1, supportData, bigRuleList, minConf)
else: # 如果只是兩個元素 直接判斷其置信度
# print "+ + + + + generateRules else begin + + + + +"
calcConf(freqSet, H1, supportData, bigRuleList, minConf)
# print "+ + + + + generateRules else end + + + + +"
# print 'bigRuleList is :', bigRuleList, '\n-------------------------- generateRules for end ---------------------------------------------------'
return bigRuleList
def calcConf(freqSet, H, supportData, bigRuleList, minConf=0.7): # 計算其 freq->H的置信度
Hmp1 = [] # 返回置信度符合條件的H
for elem in H:
conf = supportData[freqSet] / supportData[freqSet - elem] # 計算置信度 利用了集合減法
if conf >= minConf:
# print freqSet - elem, '-->', elem, 'conf:', conf
bigRuleList.append((freqSet - elem, elem, conf))
Hmp1.append(elem) # 此時不滿足條件不會加入list 因爲其超集也不會頻繁
return Hmp1
def rulesFromConseq(freqSet, H, supportData, bigRuleList, minConf=0.7): # 生成關聯規則
m = len(H[0])
''' 理解註釋 '''
# print "--------- + + + rulesFromConseq + + + -----------"
# print "H0 is :", H[0]
# print "m is :", m
# print "freqSet is :", len(freqSet)
# 爲什麼len > m+1呢 簡單來說 既要生成CK+1 又不能和freqSet長度相等(以防無法進行關聯計算freqSet->H)
# 4個元素的關聯規則 len:2->2,1->3 (本文 遞歸執行)
# 消除註釋可見過程
''' 理解註釋 '''
if len(freqSet) > (m + 1):
Hmp1 = AprioriGen(H, m + 1) # 生成C(Hmp1 : Hm plus 1) 來進行關聯分析
Hmp1 = calcConf(freqSet, Hmp1, supportData, bigRuleList, minConf)
if len(Hmp1) > 1: # 滿足條件 遞歸
rulesFromConseq(freqSet, Hmp1, supportData, bigRuleList, minConf)
if __name__ == '__main__':
data = loadSimpleData()
c1 = creatC1(data)
L, support = Apriori(data, 0.6)
print L
rules = generateRules(L, support, 0.6)
print '----'*12
for x in rules:
print x
5. 結果分析
'''
[[frozenset([5]), frozenset([2]), frozenset([3]), frozenset([1])], [frozenset([3, 5]), frozenset([2, 3]), frozenset([2, 5]), frozenset([1, 3])], [frozenset([2, 3, 5])], []]
------------------------------------------------
(frozenset([5]), frozenset([3]), 0.7999999999999999)
(frozenset([3]), frozenset([5]), 0.7999999999999999)
(frozenset([3]), frozenset([2]), 0.7999999999999999)
(frozenset([2]), frozenset([3]), 0.7999999999999999)
(frozenset([5]), frozenset([2]), 1.0)
(frozenset([2]), frozenset([5]), 1.0)
(frozenset([3]), frozenset([1]), 0.7999999999999999)
(frozenset([1]), frozenset([3]), 1.0)
(frozenset([5]), frozenset([2, 3]), 0.7999999999999999)
(frozenset([3]), frozenset([2, 5]), 0.7999999999999999)
(frozenset([2]), frozenset([3, 5]), 0.7999999999999999)
'''
# frozenset 是 '凍起來' 的意思,就是不可變的
# 結果是 a,b,置信度
# 即買a產品順便買b產品的機率是多少...可以排序看...