Apriori算法的原理與python 實現。


前言:這是一個老故事, 但每次看總是能從中想到點什么.在一家超市里,有一個有趣的現象:尿布和啤酒赫然擺在一起出售。但是這個奇怪的舉措卻使尿布和啤酒的銷量雙雙增加了。這不是一個笑話,而是發生在美國沃爾瑪連鎖店超市的真實案例,並一直為商家所津津樂道。原來,美國的婦女們經常會囑咐她們的丈夫下班以后要為孩子買尿布。而丈夫在買完尿布之后又要順手買回自己愛喝的啤酒,因此啤酒和尿布在一起購買的機會還是很多的。 是什么讓沃爾瑪發現了尿布和啤酒之間的關系呢?正是商家通過對超市一年多原始交易數字進行詳細的分析,才發現了這對神奇的組合。 無獨有偶。美國密執安州有一家名為"阿漢"的小餐館有個異常奇特的做法:經常光顧該餐館的顧客, 只要願意,便可報上自己的常住地址,在客戶登記簿上注冊,開一個"戶頭",以后顧客每次到這里來就餐,餐館都會如實地在其戶頭上記下用餐款額。每年的9月30日,餐館便會按客戶登記簿上的記載算出每位顧客從上年9月30日以來在餐館的消費總額,然后再按餐館純利10%的比例算出每位顧客應得的利潤分發給顧客,這樣,餐館自然就常常門庭若市。阿漢餐館給顧客分紅的方法雖然損失了一部分純利,但卻使顧客感到自己與餐館的利潤息息相關,自己也是餐館的一員。這樣一來,餐館密切了與消費者的關系,吸引了許多回頭客。 這種讓食客成為"股東"的做法其實也是一種"組合"式的生意之道,不同的是前者是明顯的"物質組合",而后者是隱蔽的"人員組合",兩者都是以消費者心甘情願地付出而給老板帶來了滾滾利潤,何樂而不為呢?

上面的例子我們不討論他的經營之道,我們來挖掘其中用到的技術思想。

一:關聯分析

我們一般去網點或者店里購物,一般都會有這樣的購物清單吧。

有的人說,這種有什么用?那再來看看這個:

這是我隨便找的一家網店的超值搭配。你會說這有什么聯系嗎?

假如,我是這個店長,我分析了我店里的歷史數據,看見衣服1和褲子2被同一個顧客購買的可能性很大。那我是不是可以在我的店里搭配這兩個套餐,同時也可以在給點擊衣服1的人推薦我的褲子2,說不定,這個人看上了褲子2,又感覺與衣服1搭配還挺合適的,那么就會把這兩件都買下來,商家在這次的購物行為中就賺了一筆。

那可能,你會問,小的數據集我可能很快就分析出來了,假如我的店很大,有很多物品。類似於天貓超市那樣的,我怎樣才能找到他們的關聯項呢?不會讓我窮盡所有操作吧。那么下面我們來介紹Apriori幫助店長解決這個繁瑣的問題。

二 :Apriori算法

先介紹兩個概念:

支持度:用於表示給定數據集的頻繁程度。公式: 分子為X與Y同

        時出現的概率,N為整個數據的個數。

置信度:Y在包含X的事物中出現的頻繁程度。公式:

項集:一個購物籃中任意的商品組合就是一個項集(包括單獨的一個,但是項集不能出現重復的商品)

頻繁項集:出現的項集大於一個人為設置的閥值,我們稱之為頻繁項集。

三:算法過程

    先通過偏離數據庫得到一個項集(也就是一個商品),然后計算他的支持度,如果小於某一個閥值則刪除,大於則保留,然后組合求2兩個項的項集的支持度。低於閥值則去掉,高於閥值則保留。用上面的用以上步驟重復處理新得到的頻繁項集合, 直到沒有頻繁項集合產生。其中候選項集產生的過程被分為連接與剪技兩個部分。 采用這種方式, 使得所有的頻繁項集既不會遺漏又不會重復。 為提高頻繁項集逐層產生的效率, Apriori算法利用了兩個重要的性質用於壓縮搜索空間。

性質 1  k維數據項目集 X是頻繁項目集的必要條件是它的所有 k-1維子集均是頻繁項目集。

性質 2  若 k維項目集 X中有 (k-1)維子集不是頻繁項集, 則 X不是頻繁項集

四:算法的python實現

本算法和數據來自機器學習實戰。

'''
Created on Mar 24, 2011
Ch 11 code
@author: Peter
'''
from numpy import *

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

def createC1(dataSet):
C1 = []
for transaction in dataSet:
for item in transaction:
if not [item] in C1:
C1.append([item])

C1.sort()
return map(frozenset, C1)#use frozen set so we
#can use it as a key in a dict

def scanD(D, Ck, minSupport):
ssCnt = {}
for tid in D:
for can in Ck:
if can.issubset(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): #creates Ck
retList = []
lenLk = len(Lk)
for i in range(lenLk):
for j in range(i+1, lenLk):
L1 = list(Lk[i])[:k-2]; L2 = list(Lk[j])[:k-2]
L1.sort(); L2.sort()
if L1==L2: #if first k-2 elements are equal
retList.append(Lk[i] | Lk[j]) #set union
return retList

def apriori(dataSet, minSupport = 0.5):
C1 = createC1(dataSet)
D = map(set, dataSet)
L1, supportData = scanD(D, C1, minSupport)
L = [L1]
k = 2
while (len(L[k-2]) > 0):
Ck = aprioriGen(L[k-2], k)
Lk, supK = scanD(D, Ck, minSupport)#scan DB to get Lk
supportData.update(supK)
L.append(Lk)
k += 1
return L, supportData

def generateRules(L, supportData, minConf=0.7): #supportData is a dict coming from scanD
bigRuleList = []
for i in range(1, len(L)):#only get the sets with two or more items
for freqSet in L[i]:
H1 = [frozenset([item]) for item in freqSet]
if (i > 1):
rulesFromConseq(freqSet, H1, supportData, bigRuleList, minConf)
else:
calcConf(freqSet, H1, supportData, bigRuleList, minConf)
return bigRuleList

def calcConf(freqSet, H, supportData, brl, minConf=0.7):
prunedH = [] #create new list to return
for conseq in H:
conf = supportData[freqSet]/supportData[freqSet-conseq] #calc confidence
if conf >= minConf:
print freqSet-conseq,'-->',conseq,'conf:',conf
brl.append((freqSet-conseq, conseq, conf))
prunedH.append(conseq)
return prunedH

def rulesFromConseq(freqSet, H, supportData, brl, minConf=0.7):
m = len(H[0])
if (len(freqSet) > (m + 1)): #try further merging
Hmp1 = aprioriGen(H, m+1)#create Hm+1 new candidates
Hmp1 = calcConf(freqSet, Hmp1, supportData, brl, minConf)
if (len(Hmp1) > 1): #need at least two sets to merge
rulesFromConseq(freqSet, Hmp1, supportData, brl, minConf)

def pntRules(ruleList, itemMeaning):
for ruleTup in ruleList:
for item in ruleTup[0]:
print itemMeaning[item]
print " -------->"
for
item in ruleTup[1]:
print itemMeaning[item]
print "confidence: %f" % ruleTup[2]
print #print a blank line

因為Apriori算法比較簡單,也沒什么好說的,有時會要結合具體硬件進行改進,也可以通過數據的存儲形式進行改變。

在這里說一下,那個阿漢餐館為每個人開個賬戶我們是不是可以根據他的消費習慣,給他推薦一些相似的餐品。這就用到我們的推薦算法了,哈哈。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM