引入:
啤酒與尿布的故事
關聯規律挖掘:從交易數據中發現:買了X 還會買Y 的規則
關聯規律挖掘‘購物籃分析’Market Basket Analysis(MBA)
關聯規律->應用于推薦系統
1. 關聯規則代碼演示
使用的是mlxtend.frequent_patterns.Apriori()
import numpy as np
import pandas as pdfrom mlxtend.frequent_patterns import apriori,association_rules
#TransactionEncoder 事務,編碼
#事務:表示事件
#(比如每次去商場購買東西是一次事務,而實際購買到的東西就是項集)
from mlxtend.preprocessing import TransactionEncoder
te = TransactionEncoder()
X =te.fit_transform(data)
colmns = te.columns_
df = pd.DataFrame(X,columns=colmns)
df.astype(np.uint8)
尿布 | 橙汁 | 甜菜 | 萵苣 | 葡萄酒 | 豆奶 | |
---|---|---|---|---|---|---|
0 | 0 | 0 | 0 | 1 | 0 | 1 |
1 | 1 | 0 | 1 | 1 | 1 | 0 |
2 | 1 | 1 | 0 | 0 | 1 | 1 |
3 | 1 | 0 | 0 | 1 | 1 | 1 |
4 | 1 | 1 | 0 | 1 | 0 | 1 |
data=[['豆奶','萵苣'],['萵苣','尿布','葡萄酒','甜菜'],['豆奶','尿布','葡萄酒','橙汁'],['萵苣','豆奶','尿布','葡萄酒'],['萵苣','豆奶','尿布','橙汁']]result =apriori(df,min_support=0.6,use_colnames=True)
result
support | itemsets | |
---|---|---|
0 | 0.8 | (尿布) |
1 | 0.8 | (萵苣) |
2 | 0.6 | (葡萄酒) |
3 | 0.8 | (豆奶) |
4 | 0.6 | (尿布, 萵苣) |
5 | 0.6 | (尿布, 葡萄酒) |
6 | 0.6 | (尿布, 豆奶) |
7 | 0.6 | (萵苣, 豆奶) |
關聯規則
條目 —》另一些條目之間有關聯的
根據關聯性強,進行推薦
推薦系統(小公司:分類,)
關聯規則的三個計算:
支持度 support
置信度 confidence
提升度 lift
公式計算如下:
association_rules(result,min_threshold=0.5)
antecedents | consequents | antecedent support | consequent support | support | confidence | lift | leverage | conviction | |
---|---|---|---|---|---|---|---|---|---|
0 | (尿布) | (萵苣) | 0.8 | 0.8 | 0.6 | 0.75 | 0.9375 | -0.04 | 0.8 |
1 | (萵苣) | (尿布) | 0.8 | 0.8 | 0.6 | 0.75 | 0.9375 | -0.04 | 0.8 |
2 | (尿布) | (葡萄酒) | 0.8 | 0.6 | 0.6 | 0.75 | 1.2500 | 0.12 | 1.6 |
3 | (葡萄酒) | (尿布) | 0.6 | 0.8 | 0.6 | 1.00 | 1.2500 | 0.12 | inf |
4 | (尿布) | (豆奶) | 0.8 | 0.8 | 0.6 | 0.75 | 0.9375 | -0.04 | 0.8 |
5 | (豆奶) | (尿布) | 0.8 | 0.8 | 0.6 | 0.75 | 0.9375 | -0.04 | 0.8 |
6 | (萵苣) | (豆奶) | 0.8 | 0.8 | 0.6 | 0.75 | 0.9375 | -0.04 | 0.8 |
7 | (豆奶) | (萵苣) | 0.8 | 0.8 | 0.6 | 0.75 | 0.9375 | -0.04 | 0.8 |
探究關聯規則的原始代碼
import numpy as np
def createC1(dataSet):C1 = []for transaction in dataSet:for item in transaction:if not [item] in C1:C1.append([item]) #store all the item unrepeatlyC1.sort()#return map(frozenset, C1)#frozen set, user can't change it.return list(map(frozenset, C1))def scanD(D,Ck,minSupport):
#參數:數據集、候選項集列表 Ck以及感興趣項集的最小支持度 minSupportssCnt={}for tid in D:#遍歷數據集for can in Ck:#遍歷候選項if can.issubset(tid):#判斷候選項中是否含數據集的各項#if not ssCnt.has_key(can): # python3 can not supportif not can in ssCnt:ssCnt[can]=1 #不含設為1else: ssCnt[can]+=1#有則計數加1numItems=float(len(D))#數據集大小retList = []#L1初始化supportData = {}#記錄候選項中各個數據的支持度for key in ssCnt:support = ssCnt[key]/numItems#計算支持度if support >= minSupport:retList.insert(0,key)#滿足條件加入L1中supportData[key] = supportreturn retList, supportDatadef aprioriGen(Lk, k): #組合,向上合并#creates Ck 參數:頻繁項集列表 Lk 與項集元素個數 kretList = []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: #若兩個集合的前k-2個項相同時,則將兩個集合合并retList.append(Lk[i] | Lk[j]) #set unionreturn retListdef apriori(dataSet, minSupport = 0.5):C1 = createC1(dataSet)D = list(map(set, dataSet)) #python3L1, supportData = scanD(D, C1, minSupport)#單項最小支持度判斷 0.5,生成L1L = [L1]k = 2while (len(L[k-2]) > 0):#創建包含更大項集的更大列表,直到下一個大的項集為空Ck = aprioriGen(L[k-2], k)#CkLk, supK = scanD(D, Ck, minSupport)#get LksupportData.update(supK)L.append(Lk)k += 1return L, supportDatadef generateRules(L, supportData, minConf=0.7):#頻繁項集列表、包含那些頻繁項集支持數據的字典、最小可信度閾值bigRuleList = [] #存儲所有的關聯規則for i in range(1, len(L)): #只獲取有兩個或者更多集合的項目,從1,即第二個元素開始,L[0]是單個元素的# 兩個及以上的才可能有關聯一說,單個元素的項集不存在關聯問題for freqSet in L[i]:H1 = [frozenset([item]) for item in freqSet]#該函數遍歷L中的每一個頻繁項集并對每個頻繁項集創建只包含單個元素集合的列表H1if (i > 1):#如果頻繁項集元素數目超過2,那么會考慮對它做進一步的合并rulesFromConseq(freqSet, H1, supportData, bigRuleList, minConf)else:#第一層時,后件數為1calcConf(freqSet, H1, supportData, bigRuleList, minConf)# 調用函數2return bigRuleListdef calcConf(freqSet, H, supportData, brl, minConf=0.7):#針對項集中只有兩個元素時,計算可信度prunedH = []#返回一個滿足最小可信度要求的規則列表for conseq in H:#后件,遍歷 H中的所有項集并計算它們的可信度值conf = supportData[freqSet]/supportData[freqSet-conseq] #可信度計算,結合支持度數據if conf >= minConf:print (freqSet-conseq,'-->',conseq,'conf:',conf)#如果某條規則滿足最小可信度值,那么將這些規則輸出到屏幕顯示brl.append((freqSet-conseq, conseq, conf))#添加到規則里,brl 是前面通過檢查的 bigRuleListprunedH.append(conseq)#同樣需要放入列表到后面檢查return prunedHdef rulesFromConseq(freqSet, H, supportData, brl, minConf=0.7):#參數:一個是頻繁項集,另一個是可以出現在規則右部的元素列表 Hm = len(H[0])if (len(freqSet) > (m + 1)): #頻繁項集元素數目大于單個集合的元素數Hmp1 = aprioriGen(H, m+1)#存在不同順序、元素相同的集合,合并具有相同部分的集合Hmp1 = calcConf(freqSet, Hmp1, supportData, brl, minConf)#計算可信度if (len(Hmp1) > 1): #滿足最小可信度要求的規則列表多于1,則遞歸來判斷是否可以進一步組合這些規則rulesFromConseq(freqSet, Hmp1, supportData, brl, minConf)
data=[['豆奶','萵苣'],['萵苣','尿布','葡萄酒','甜菜'],['豆奶','尿布','葡萄酒','橙汁'],['萵苣','豆奶','尿布','葡萄酒'],['萵苣','豆奶','尿布','橙汁']]
L, supportData = apriori(data,minSupport = 0.5)
# 頻繁項集
display(L)
#計算
display(supportData)
[[frozenset({‘葡萄酒’}), frozenset({‘尿布’}), frozenset({‘豆奶’}), frozenset({‘萵苣’})],
[frozenset({‘尿布’, ‘豆奶’}),
frozenset({‘尿布’, ‘萵苣’}),
frozenset({‘尿布’, ‘葡萄酒’}),
frozenset({‘萵苣’, ‘豆奶’})],
[]]
{frozenset({‘萵苣’}): 0.8,
frozenset({‘豆奶’}): 0.8,
frozenset({‘尿布’}): 0.8,
frozenset({‘甜菜’}): 0.2,
frozenset({‘葡萄酒’}): 0.6,
frozenset({‘橙汁’}): 0.4,
frozenset({‘萵苣’, ‘豆奶’}): 0.6,
frozenset({‘尿布’, ‘葡萄酒’}): 0.6,
frozenset({‘萵苣’, ‘葡萄酒’}): 0.4,
frozenset({‘尿布’, ‘萵苣’}): 0.6,
frozenset({‘葡萄酒’, ‘豆奶’}): 0.4,
frozenset({‘尿布’, ‘豆奶’}): 0.6,
frozenset({‘尿布’, ‘萵苣’, ‘豆奶’}): 0.4}
generateRules(L,supportData,minConf=0.8)
[(frozenset({‘葡萄酒’}), frozenset({‘尿布’}), 1.0)]
核心思想簡單來說就是 :
1、發現頻繁項集過程為
①掃描(掃描所有數據)
②計數(計算各個候選集的支持度)
③比較(選出適合條件的頻繁項集)
④產生頻繁集
⑤連接、再剪枝產生候選集
2、產生關聯規則。過程:根據前面提到的置信度的定義,關聯規則的產生如下:
①對于每個頻繁項集L,產生L的所有非空子集。
②對于L的每個非空子集S,如果P(L)/P(S)>=min_conf,則輸出規則“Sa L-S”。(L-S表示在項集中除去S子集的項集。)
Apriori缺點:
①由頻繁k-1項集進行自連接生成的候選頻繁k項集數量巨大
②在驗證候選頻繁k項集的時候需要對整個數據庫進行掃描,非常耗時。
更多推薦算法參考:
史上最全機器學習算法(源于逼乎)