這里把之前的實驗報告搬出來,代碼參考了一下各位大哥的數(shù)據(jù)挖掘算法實現(xiàn)代碼,然后自己再溫習(xí)一遍~
作為數(shù)據(jù)挖掘的典型算法(也是機(jī)器學(xué)習(xí)的典型算法),算法是一種挖掘關(guān)聯(lián)規(guī)則的頻繁項集算法,其核心思想是通過候選集生成和情節(jié)的向下封閉檢測兩個階段來挖掘頻繁項集。關(guān)于其更多的介紹網(wǎng)上很多就不寫了。
算法的基本步驟如下:
1. 首先先掃描數(shù)據(jù)集,計算每個單項集的支持度,根據(jù)給定的最小支持度的值,得到第一項頻繁集。
2. 然后通過運(yùn)算,得到二項候選集,對每個候選集再次掃描數(shù)據(jù)集,得出每個候選集的支持度,再與最小支持度比較,刪除不合格的單項集,得到二項頻繁集。
3. 如此進(jìn)行下去,直到不能連接產(chǎn)生新的候選集為止。
4. 對于找到的所有頻繁集,用規(guī)則提取算法進(jìn)行關(guān)聯(lián)規(guī)則的提取,算出置信度。
算法的關(guān)鍵代碼如下:
L1 = find_frequent_1-itemsets(D);
for (k=2;Lk-1 ≠Φ ;k++) {
Ck = apriori_gen(Lk-1 ,min_sup);
for each transaction t ∈?D?{//scan D for counts
Ct = subset(Ck,t);//get the subsets of t that are candidates
for each candidate c ∈ Ct
c.count++;
?}
Lk ={c ∈ Ck|c.count≥min_sup}
? }
return L= ∪ k Lk;
一個題外話,為了把實驗報告做得好看一些 :-) ,本人使用了這個工具來生成大大的華麗的字符再添加到輸出中,至于它的下載安裝網(wǎng)上教程很多也很簡單數(shù)據(jù)挖掘算法實現(xiàn)代碼,這里就看看效果:
接著直接將整個字符圖形都復(fù)制粘貼到輸出就OK了。
走正題,代碼如下:
#!/usr/bin/python
#coding=utf-8
import itertools
#事務(wù)數(shù)據(jù)庫,和課本上的數(shù)據(jù)一致
Data = {
'T100':['I1','I2','I5'],
'T200':['I2','I4'],
'T300':['I2','I3'],
'T400':['I1','I2','I4'],
'T500':['I1','I3'],
'T600':['I2','I3'],
'T700':['I1','I3'],
'T800':['I1','I2','I3','I5'],
'T900':['I1','I2','I3']
}
#定義Apriori類
class Apriori:
def __init__(self,min_sup=0.2,dataDic={}):
#事務(wù)數(shù)據(jù)庫data
self.data = dataDic
#獲取事務(wù)的數(shù)量
self.size = len(dataDic)
#最小支持度閾值
self.min_sup = min_sup
self.min_sup_val = min_sup * self.size
#找出頻繁1項集的集合L1
def find_frequent_1_itemsets(self):
#這里的字典格式設(shè)置為: {itemset1:freq1,itemsets2:freq2}
FreqDic = {}
for event in self.data:
for item in self.data[event]:
if item in FreqDic:
FreqDic[item] += 1
else:
FreqDic[item] = 1
L1 = []
for itemset in FreqDic:
if itemset >= self.min_sup_val:
L1.append([itemset])
return L1
#實現(xiàn)連接和剪枝
def apriori_gen(self,L_last):
k = len(L_last[0]) + 1
Ck = []
for itemset1 in L_last:
for itemset2 in L_last:
#連接步:產(chǎn)生候選
flag = 0
for i in range(k-2):
if itemset1[i] != itemset2[i]:
flag = 1
break;
if flag == 1:
continue
if itemset1[k-2] < itemset2[k-2]:
c = itemset1 + [itemset2[k-2]]
else:
continue
#剪枝步:刪除非頻繁的候選
if self.has_infrequent_subset(c,L_last,k):
continue
else:
Ck.append(c)
return Ck
#使用先驗知識
def has_infrequent_subset(self,c,L_last,k):
#返回列表中元組的項
subsets = list(itertools.combinations(c,k-1))
for each in subsets:
#將元組轉(zhuǎn)換成列表
each = list(each)
if each not in L_last:
return True
return False
#運(yùn)行Apriori算法
def run(self):
L_last = self.find_frequent_1_itemsets()
L = L_last
i = 0
j = 2
while L_last != []:
Ck = self.apriori_gen(L_last)
FreqDic = {}
for event in self.data:
#獲取所有支持的子集
for c in Ck:
#判斷是否是子集
if set(c) <= set(self.data[event]):
if tuple(c) in FreqDic:
FreqDic[tuple(c)]+=1
else:
FreqDic[tuple(c)]=1
Lk = []
num = []
Lo = []
for c in FreqDic:
if FreqDic[c] > self.min_sup_val:
Lk.append(list(c))
num.append(FreqDic[c])
L_last = Lk
L += Lk
if len(Lk) != 0:
print "[*] 頻繁%d項集L%d:"%(j,j)
for i in xrange(0,len(Lk)):
print Lk[i],':',num[i]
print
j += 1
return L
def main():
print '''
_ _ _
/ \ _ __ _ __(_) ___ _ __(_)
/ _ \ | '_ \| '__| |/ _ \| '__| |
/ ___ \| |_) | | | | (_) | | | |
/_/ \_\ .__/|_| |_|\___/|_| |_|
|_|
'''
a = Apriori(dataDic=Data)
result = a.run()
print "[*] 所有的頻繁項集:"
for r in result:
print r
if __name__ == '__main__':
main()
這里將數(shù)據(jù)也寫在腳本中,數(shù)據(jù)是跟書上一模一樣的(具體的可以看《數(shù)據(jù)挖掘概念與技術(shù) 第三版》,具體第幾頁忘了)
運(yùn)行結(jié)果: