
1.關聯分析
關聯分析是一種在大規模數據集中尋找有趣關系的任務。這種關系表現為兩種形式:
1.頻繁項集(frequency item sets):經常同時出現的一些元素的集合;
2.關聯規則(association rules): 意味著兩種元素之間存在很強的關系。
下面舉例來說明上面的兩個概念:
頻繁項集是指經常出現在一起的元素的集合,上表中的集合 {葡萄酒,尿布,豆奶} 就是頻繁項集的一個例子。同樣可以找到如 “尿布 –> 葡萄酒”的關聯規則,意味著如果有人買了尿布,就很可能也會買葡萄酒。使用頻繁項集和關聯規則,商家可以更好地理解顧客的消費行為,所以大部分關聯規則分析示例來自零售業。
理解關聯分析首先需要搞清楚下面三個問題:
1.如何定義這些有用的關系?
2.這些關系的強弱程度又是如何定義?
3.頻繁的定義是什么?
要回答上面的問題,最重要的是理解兩個概念:支持度和可信度。
支持度:一個項集的支持度(support)被定義為數據集中包含該項集的記錄占總記錄的比例。從表1 可以看出 項集 {豆奶} 的支持度為 4/5; 而在 5 條交易記錄中 3 條包含 {豆奶,尿布},因此 {豆奶,尿布} 的支持度為 3/5.
可信度或置信度(confidence):是針對一條諸如尿布??>葡萄酒的關聯規則來定義的,這條規則的可信度被定義為“ 支持度({尿布,葡萄酒}) / 支持度({尿布})”。在表1 中可以發現 {尿布,葡萄酒} 的支持度是 3/5, {尿布} 的支持度為 4/5, 所以關聯規則 “尿布 –> 葡萄酒”的可信度為 3/4=0.75, 意思是對于所有包含 “尿布”的記錄中,該關聯規則對其中的 75% 記錄都適用。
2. Apriori 原理
假設經營了一家雜貨店,于是我們對那些經常在一起購買的商品非常感興趣。假設我們只有 4 種商品:商品0,商品1,商品 2,商品3. 那么如何得可能被一起購買的商品的組合?
上圖顯示了物品之間所有可能的組合,從上往下一個集合是 ??,表示不包含任何物品的空集,物品集合之間的連線表明兩個或者更多集合可以組合形成一個更大的集合。
我們的目標是找到經常在一起購買的物品集合。這里使用集合的支持度來度量其出現的頻率。一個集合出現的支持度是指有多少比例的交易記錄包含該集合。例如,對于上圖,要計算 0,3 的支持度,直接的想法是遍歷每條記錄,統計包含有 0 和 3 的記錄的數量,使用該數量除以總記錄數,就可以得到支持度。而這只是針對單個集合 0,3. 要獲得每種可能集合的支持度就需要多次重復上述過程。對于上圖,雖然僅有4中物品,也需要遍歷數據15次。隨著物品數目的增加,遍歷次數會急劇增加,對于包含 N 種物品的數據集共有 2N?1 種項集組合。所以即使只出售 100 種商品的商店也會有 1.26×1030 中可能的組合。計算量太大。
為了降低計算時間,研究人員發現了Apriori 原理,可以幫我們減少感興趣的頻繁項集的數目。
Apriori 的原理:如果某個項集是頻繁項集,那么它所有的子集也是頻繁的。
即如果 {0,1} 是頻繁的,那么 {0}, {1} 也一定是頻繁的。
這個原理直觀上沒有什么用,但是反過來看就有用了,也就是說如果一個項集是非頻繁的,那么它的所有超集也是非頻繁的。如下圖所示:
3. 使用 Apriori 算法來發現頻繁集
上面提到,關聯分析的兩個目標:發現頻繁項集和發現關聯規則。首先需要找到頻繁項集,然后根據頻繁項集獲得關聯規則。首先來討論發現頻繁項集。Apriori 是發現頻繁項集的一種方法。
首先會生成所有單個物品的項集列表;
掃描交易記錄來查看哪些項集滿足最小支持度要求,那些不滿足最小支持度的集合會被去掉;
對剩下的集合進行組合以生成包含兩個元素的項集;
接下來重新掃描交易記錄,去掉不滿足最小支持度的項集,重復進行直到所有項集都被去掉。
數據集掃描的偽代碼:
對數據集中的每條交易記錄tran:
對每個候選項集can:
檢查一下can是否是tran的子集:
如果是,則增加can的計數值
對每個候選項集:
如果其支持度不低于最低值,則保留
返回所有頻繁項集列表
有上面的偽代碼寫出代碼如下:
# -*- coding: utf-8 -*-
"""
Apriori exercise.
Created on Fri Nov 27 11:09:03 2015
@author: 90Zeng
"""
def loadDataSet():
'''創建一個用于測試的簡單的數據集'''
return [ [ 1, 3, 4 ], [ 2, 3, 5 ], [ 1, 2, 3, 5 ], [ 2, 5 ] ]
def createC1( dataSet ):
'''
構建初始候選項集的列表,即所有候選項集只包含一個元素,
C1是大小為1的所有候選項集的集合
'''
C1 = []
for transaction in dataSet:
for item in transaction:
if [ item ] not in C1:
C1.append( [ item ] )
C1.sort()
return map( frozenset, C1 )
def scanD( D, Ck, minSupport ):
'''
計算Ck中的項集在數據集合D(記錄或者transactions)中的支持度,
返回滿足最小支持度的項集的集合,和所有項集支持度信息的字典。
'''
ssCnt = {}
for tid in D:
# 對于每一條transaction
for can in Ck:
# 對于每一個候選項集can,檢查是否是transaction的一部分
# 即該候選can是否得到transaction的支持
if can.issubset( tid ):
ssCnt[ can ] = ssCnt.get( can, 0) + 1
numItems = float( len( D ) )
retList = []
supportData = {}
for key in ssCnt:
# 每個項集的支持度
support = ssCnt[ key ] / numItems
# 將滿足最小支持度的項集,加入retList
if support >= minSupport:
retList.insert( 0, key )
# 匯總支持度數據
supportData[ key ] = support
return retList, supportData
注:關于上面代碼中 “frozenset”,是為了凍結集合,使集合由“可變”變為 “不可變”,這樣,這些集合就可以作為字典的鍵值。
首先來測試一下上面代碼,看看運行效果:
if __name__ == '__main__':
# 導入數據集
myDat = loadDataSet()
# 構建第一個候選項集列表C1
C1 = createC1( myDat )
# 構建集合表示的數據集 D
D = map( set, myDat )
# 選擇出支持度不小于0.5 的項集作為頻繁項集
L, suppData = scanD( D, C1, 0.5 )
print u"頻繁項集L:", L
print u"所有候選項集的支持度信息:", suppData
運行結果:
>>> runfile(‘E:/Python/PythonScripts/Apriori.py’, wdir=r’E:/Python/PythonScripts’)
頻繁項集L: [frozenset([1]), frozenset([3]), frozenset([2]), frozenset([5])]
所有候選項集的支持度信息: {frozenset([4]): 0.25, frozenset([5]): 0.75, frozenset([2]): 0.75, frozenset([3]): 0.75, frozenset([1]): 0.5}
可以看出,只有支持度不小于 0.5 的項集被選中到 L 中作為頻繁項集,根據不同的需求,我們可以設定最小支持度的值,從而得到我們想要的頻繁項集。
上面的示例只是選擇出來了項集中只包含一個元素的頻繁項集,下面需要整合上面的代碼,選擇出包含 2個,3個直至個數據等于所有候選元素個數的頻繁項集,
從而形成完整的 Apriori 的算法,首先給出偽代碼:
當集合中的元素個數大于 0 時:
構建一個 k 個項組成的候選項集列表
檢查數據,確認每個項集都是頻繁項集
保留頻繁項集,并構建 k+1 項組成的候選項集的列表
程序清單:
# Aprior算法
def aprioriGen( Lk, k ):
'''
由初始候選項集的集合Lk生成新的生成候選項集,
k表示生成的新項集中所含有的元素個數
'''
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:
retList.append( Lk[ i ] | Lk[ j ] )
return retList
def apriori( dataSet, minSupport = 0.5 ):
# 構建初始候選項集C1
C1 = createC1( dataSet )
# 將dataSet集合化,以滿足scanD的格式要求
D = map( set, dataSet )
# 構建初始的頻繁項集,即所有項集只有一個元素
L1, suppData = scanD( D, C1, minSupport )
L = [ L1 ]
# 最初的L1中的每個項集含有一個元素,新生成的
# 項集應該含有2個元素,所以 k=2
k = 2
while ( len( L[ k - 2 ] ) > 0 ):
Ck = aprioriGen( L[ k - 2 ], k )
Lk, supK = scanD( D, Ck, minSupport )
# 將新的項集的支持度數據加入原來的總支持度字典中
suppData.update( supK )
# 將符合最小支持度要求的項集加入L
L.append( Lk )
# 新生成的項集中的元素個數應不斷增加
k += 1
# 返回所有滿足條件的頻繁項集的列表,和所有候選項集的支持度信息
return L, suppData
關于上面程序 函數 aprioriGen 中的 k?2的說明:當利用 {0}, {1}, {2} 這些只含有一個元素的候選項集構建含有 2 個元素的候選項集時,就是兩兩合并得到 {0,1}, {0,2}, {1,2}; 如果進一步用包含連個元素的候選項集來構建包含 3 個元素的候選項集,同樣兩兩合并,就會得到 {0,1,2},{0,1,2},{0,1,2}. 就是說會出現重復的項集,接下來就需要掃描三元素項集得到非重復結果,顯然增加了計算時間?,F在,如果比較 {0,1}, {0,2}, {1,2} 的第 0 個元素并只對第 0 個元素相同的集合求并,就會得到 {0,1,2}, 而且只有一次操作,這樣就不需要遍歷列表來尋找非重復值。
測試上面代碼:
if __name__ == '__main__':
# 導入數據集
myDat = loadDataSet()
# 選擇頻繁項集
L, suppData = apriori( myDat, 0.5 )
print u"頻繁項集L:", L
print u"所有候選項集的支持度信息:", suppData
運行結果(最小支持度 0.5) :
>>> runfile('E:/Python/PythonScripts/Apriori.py', wdir=r'E:/Python/PythonScripts')
頻繁項集L: [[frozenset([1]), frozenset([3]), frozenset([2]), frozenset([5])], [frozenset([1, 3]), frozenset([2, 5]), frozenset([2, 3]), frozenset([3, 5])], [frozenset([2, 3, 5])], []]
所有候選項集的支持度信息: {frozenset([5]): 0.75, frozenset([3]): 0.75, frozenset([2, 3, 5]): 0.5, frozenset([1, 2]): 0.25, frozenset([1, 5]): 0.25, frozenset([3, 5]): 0.5, frozenset([4]): 0.25, frozenset([2, 3]): 0.5, frozenset([2, 5]): 0.75, frozenset([1]): 0.5, frozenset([1, 3]): 0.5, frozenset([2]): 0.75}
在測試一下最小支持度為 0.7 時的情況:
>>> runfile('E:/Python/PythonScripts/Apriori.py', wdir=r'E:/Python/PythonScripts')
頻繁項集L: [[frozenset([3]), frozenset([2]), frozenset([5])], [frozenset([2, 5])], []]
所有候選項集的支持度信息: {frozenset([5]): 0.75, frozenset([3]): 0.75, frozenset([3, 5]): 0.5, frozenset([4]): 0.25, frozenset([2, 3]): 0.5, frozenset([2, 5]): 0.75, frozenset([1]): 0.5, frozenset([2]): 0.75}
頻繁項集相比最小支持度 0.5 時要少,符合預期。
4.從頻繁集中挖掘關聯規則
要找到關聯規則,先從一個頻繁集開始,我們想知道對于頻繁項集中的元素能否獲取其它內容,即某個元素或者某個集合可能會推導出另一個元素。從表1 可以得到,如果有一個頻繁項集 {豆奶,萵苣},那么就可能有一條關聯規則 “豆奶 –> 萵苣”,意味著如果有人購買了豆奶,那么在統計上他會購買萵苣的概率較大。但是這一條反過來并不一定成立。
從一個頻繁項集可以產生多少條關聯規則呢?可以基于該頻繁項集生成一個可能的規則列表,然后測試每條規則的可信度,如果可信度不滿足最小值要求,則去掉該規則。類似于前面討論的頻繁項集生成,一個頻繁項集可以產生許多可能的關聯規則,如果能在計算規則可信度之前就減少規則的數目,就會很好的提高計算效率。
這里有一條規律就是:如果某條規則并不滿足最小可信度要求,那么該規則的所有子集也不會滿足最小可信度要求,例如下圖的解釋:
所以,可以利用上圖所示的性質來減少測試的規則數目。
關聯規則生成函數清單:
# 規則生成與評價
def calcConf( freqSet, H, supportData, brl, minConf=0.7 ):
'''
計算規則的可信度,返回滿足最小可信度的規則。
freqSet(frozenset):頻繁項集
H(frozenset):頻繁項集中所有的元素
supportData(dic):頻繁項集中所有元素的支持度
brl(tuple):滿足可信度條件的關聯規則
minConf(float):最小可信度
'''
prunedH = []
for conseq in H:
conf = supportData[ freqSet ] / supportData[ freqSet - conseq ]
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 ):
'''
對頻繁項集中元素超過2的項集進行合并。
freqSet(frozenset):頻繁項集
H(frozenset):頻繁項集中的所有元素,即可以出現在規則右部的元素
supportData(dict):所有項集的支持度信息
brl(tuple):生成的規則
'''
m = len( H[ 0 ] )
# 查看頻繁項集是否大到移除大小為 m 的子集
if len( freqSet ) > m + 1:
Hmp1 = aprioriGen( H, m + 1 )
Hmp1 = calcConf( freqSet, Hmp1, supportData, brl, minConf )
# 如果不止一條規則滿足要求,進一步遞歸合并
if len( Hmp1 ) > 1:
rulesFromConseq( freqSet, Hmp1, supportData, brl, minConf )
def generateRules( L, supportData, minConf=0.7 ):
'''
根據頻繁項集和最小可信度生成規則。
L(list):存儲頻繁項集
supportData(dict):存儲著所有項集(不僅僅是頻繁項集)的支持度
minConf(float):最小可信度
'''
bigRuleList = []
for i in range( 1, len( L ) ):
for freqSet in L[ i ]:
# 對于每一個頻繁項集的集合freqSet
H1 = [ frozenset( [ item ] ) for item in freqSet ]
# 如果頻繁項集中的元素個數大于2,需要進一步合并
if i > 1:
rulesFromConseq( freqSet, H1, supportData, bigRuleList, minConf )
else:
calcConf( freqSet, H1, supportData, bigRuleList, minConf )
return bigRuleList
測試:
if __name__ == '__main__':
# 導入數據集
myDat = loadDataSet()
# 選擇頻繁項集
L, suppData = apriori( myDat, 0.5 )
rules = generateRules( L, suppData, minConf=0.7 )
print 'rules:\n', rules
運行結果:
>>> runfile('E:/Python/PythonScripts/Apriori.py', wdir=r'E:/Python/PythonScripts')
frozenset([1]) --> frozenset([3]) conf: 1.0
frozenset([5]) --> frozenset([2]) conf: 1.0
frozenset([2]) --> frozenset([5]) conf: 1.0
rules:
[(frozenset([1]), frozenset([3]), 1.0), (frozenset([5]), frozenset([2]), 1.0), (frozenset([2]), frozenset([5]), 1.0)]
將可信度降為 0.5 之后:
>>> runfile('E:/Python/PythonScripts/Apriori.py', wdir=r'E:/Python/PythonScripts')
frozenset([3]) --> frozenset([1]) conf: 0.666666666667
frozenset([1]) --> frozenset([3]) conf: 1.0
frozenset([5]) --> frozenset([2]) conf: 1.0
frozenset([2]) --> frozenset([5]) conf: 1.0
frozenset([3]) --> frozenset([2]) conf: 0.666666666667
frozenset([2]) --> frozenset([3]) conf: 0.666666666667
frozenset([5]) --> frozenset([3]) conf: 0.666666666667
frozenset([3]) --> frozenset([5]) conf: 0.666666666667
frozenset([5]) --> frozenset([2, 3]) conf: 0.666666666667
frozenset([3]) --> frozenset([2, 5]) conf: 0.666666666667
frozenset([2]) --> frozenset([3, 5]) conf: 0.666666666667
rules:
[(frozenset([3]), frozenset([1]), 0.6666666666666666), (frozenset([1]), frozenset([3]), 1.0), (frozenset([5]), frozenset([2]), 1.0), (frozenset([2]), frozenset([5]), 1.0), (frozenset([3]), frozenset([2]), 0.6666666666666666), (frozenset([2]), frozenset([3]), 0.6666666666666666), (frozenset([5]), frozenset([3]), 0.6666666666666666), (frozenset([3]), frozenset([5]), 0.6666666666666666), (frozenset([5]), frozenset([2, 3]), 0.6666666666666666), (frozenset([3]), frozenset([2, 5]), 0.6666666666666666), (frozenset([2]), frozenset([3, 5]), 0.6666666666666666)]
一旦降低可信度閾值,就可以獲得更多的規則。
5. 總結
有上面分析可以看出 Apriori 算法易編碼,缺點是在大數據集上可能較慢。
數據分析咨詢請掃描二維碼
若不方便掃碼,搜微信號:CDAshujufenxi
CDA數據分析師證書考試體系(更新于2025年05月22日)
2025-05-26解碼數據基因:從數字敏感度到邏輯思維 每當看到超市貨架上商品的排列變化,你是否會聯想到背后的銷售數據波動?三年前在零售行 ...
2025-05-23在本文中,我們將探討 AI 為何能夠加速數據分析、如何在每個步驟中實現數據分析自動化以及使用哪些工具。 數據分析中的AI是什么 ...
2025-05-20當數據遇見人生:我的第一個分析項目 記得三年前接手第一個數據分析項目時,我面對Excel里密密麻麻的銷售數據手足無措。那些跳動 ...
2025-05-20在數字化運營的時代,企業每天都在產生海量數據:用戶點擊行為、商品銷售記錄、廣告投放反饋…… 這些數據就像散落的拼圖,而相 ...
2025-05-19在當今數字化營銷時代,小紅書作為國內領先的社交電商平臺,其銷售數據蘊含著巨大的商業價值。通過對小紅書銷售數據的深入分析, ...
2025-05-16Excel作為最常用的數據分析工具,有沒有什么工具可以幫助我們快速地使用excel表格,只要輕松幾步甚至輸入幾項指令就能搞定呢? ...
2025-05-15數據,如同無形的燃料,驅動著現代社會的運轉。從全球互聯網用戶每天產生的2.5億TB數據,到制造業的傳感器、金融交易 ...
2025-05-15大數據是什么_數據分析師培訓 其實,現在的大數據指的并不僅僅是海量數據,更準確而言是對大數據分析的方法。傳統的數 ...
2025-05-14CDA持證人簡介: 萬木,CDA L1持證人,某電商中廠BI工程師 ,5年數據經驗1年BI內訓師,高級數據分析師,擁有豐富的行業經驗。 ...
2025-05-13CDA持證人簡介: 王明月 ,CDA 數據分析師二級持證人,2年數據產品工作經驗,管理學博士在讀。 學習入口:https://edu.cda.cn/g ...
2025-05-12CDA持證人簡介: 楊貞璽 ,CDA一級持證人,鄭州大學情報學碩士研究生,某上市公司數據分析師。 學習入口:https://edu.cda.cn/g ...
2025-05-09CDA持證人簡介 程靖 CDA會員大咖,暢銷書《小白學產品》作者,13年頂級互聯網公司產品經理相關經驗,曾在百度、美團、阿里等 ...
2025-05-07相信很多做數據分析的小伙伴,都接到過一些高階的數據分析需求,實現的過程需要用到一些數據獲取,數據清洗轉換,建模方法等,這 ...
2025-05-06以下的文章內容來源于劉靜老師的專欄,如果您想閱讀專欄《10大業務分析模型突破業務瓶頸》,點擊下方鏈接 https://edu.cda.cn/g ...
2025-04-30CDA持證人簡介: 邱立峰 CDA 數據分析師二級持證人,數字化轉型專家,數據治理專家,高級數據分析師,擁有豐富的行業經驗。 ...
2025-04-29CDA持證人簡介: 程靖 CDA會員大咖,暢銷書《小白學產品》作者,13年頂級互聯網公司產品經理相關經驗,曾在百度,美團,阿里等 ...
2025-04-28CDA持證人簡介: 居瑜 ,CDA一級持證人國企財務經理,13年財務管理運營經驗,在數據分析就業和實踐經驗方面有著豐富的積累和經 ...
2025-04-27數據分析在當今信息時代發揮著重要作用。單因素方差分析(One-Way ANOVA)是一種關鍵的統計方法,用于比較三個或更多獨立樣本組 ...
2025-04-25CDA持證人簡介: 居瑜 ,CDA一級持證人國企財務經理,13年財務管理運營經驗,在數據分析就業和實踐經驗方面有著豐富的積累和經 ...
2025-04-25