python資料分析:關聯規則學習(Association rule learning)
何為關聯規則學習
關聯規則學習是一種基於規則的機器學習方法,用於發現大型資料庫中變數之間的有趣關係。它旨在使用一些有趣的度量來識別在資料庫中發現的強規則。這種基於規則的方法在分析更多資料時也會生成新規則。假設資料集足夠大,最終目標是幫助機器模擬人類大腦的特徵提取和新未分類資料的抽象關聯能力。
基於強有力規則的概念,Rakesh Agrawal,TomaszImieliński和Arun Swami介紹了關聯規則,用於發現超市中銷售點(POS)系統記錄的大規模交易資料中產品之間的規律性。例如,在超市的銷售資料中發現,如果顧客一起購買洋蔥和土豆,他們也可能會購買漢堡肉。這些資訊可以用作關於營銷活動的決策的基礎,例如促銷定價或產品放置。
除了市場購物籃分析的上述示例之外,目前在許多應用領域中使用關聯規則,包括Web使用挖掘,入侵檢測,連續生產和生物資訊學。與序列挖掘相反,關聯規則學習通常不考慮事務內或跨事務的專案順序。
常用的關聯演算法包括
Apriori、FP-Growth、PrefixSpan、SPADE、AprioriAll、Apriori-Some等。
關聯演算法評估規則
頻繁規律與有效規則:
- 頻繁規則指的是關聯結果中支援度和置信度都比較高的規則
- 有效規則指關聯規則真正能促進規則中的前後項提升
假如,資料集有1000條事務資料用來顯示購買蘋果和香蕉的訂單記錄,其中有600個客戶的訂單記錄中包含了蘋果,有800個客戶的訂單記錄中包含了香蕉,而有400個客戶同時購買了蘋果和香蕉。假如我們產生了一條關聯規則,用來表示購買了蘋果的客戶中還有很多人購買香蕉,那麼該規則可以表示為:蘋果→香蕉。
支援度:support = 400/1000= 40%
置信度:confidence = 400/600=67%
如果只是看支援度和置信度,這個規則似乎非常顯著的說明了蘋果和香蕉之間的頻繁關係,買了蘋果的客戶中有67%的人也會一起購買香蕉。但是,如果忽略購買蘋果的事實,只購買香蕉的客戶比例會高達是80%(800/1000)!這顯示了購買蘋果這種條件不會對購買香蕉產生積極的促進作用,反而會阻礙其銷售,蘋果和香蕉之間是一種負相關的關係。因此,只看支援度和置信度將無法完整體現規則的有效性,這裡我們使用提升度來有效應對該問題。
提升度(Lift)指的是應用關聯規則和不應用產生結果的比例。在本示例中,Lift=(400)/(800)=0.5(有關聯規則的前提下只有400個客戶會購買香蕉,沒有關聯規則的前提下會有800個購買香蕉)。當提升度為1時,說明應用關聯規則和不應用關聯規則產生相同的結果;當提升度大於1時,說明應用關聯規則比不應用關聯規則能產生更好的結果;當提升度小於1時,關聯規則具有負相關的作用,該規則是無效規則。
做關聯規則評估時,需要綜合考慮支援度、置信度和提升度三個指標,支援度和置信度的值越大越好。
提升度低的負相關關聯其實也是一種關聯模式,也是可以通過避免的方式利用這種關聯:不將互斥商品放在一個組合中,不將互斥廣告投放整合投放,不將互斥關鍵字提供個客戶,不將互斥資訊流展現給客戶。
運營分析中關聯分析的使用
- 網站頁面關聯分析:幫助我們找到使用者在不同頁面之間的頻繁訪問關係,以分析使用者特定的頁面瀏覽方式,這樣可以幫助瞭解不同頁面之間的分流和引流情況,可用於不同頁面間的推薦已達到提高轉化率。
- 廣告流量關聯分析:針對站外廣告投放渠道使用者瀏覽或點選的行為分析,該分析主要用於瞭解使用者的瀏覽和點選廣告的規則。這種站外廣告曝光和點選的關聯分析可以為廣告客戶的精準投放提供參考。
- 使用者關鍵字搜尋:通過分析使用者在站內的搜尋關鍵字瞭解使用者真實需求的。通過對使用者搜尋的關鍵字的關聯分析,可以得到類似於搜尋了iPhone又搜尋了三星,這種關聯可以用於搜尋推薦、搜尋關聯等場景,有助於改善搜尋體驗,提高客戶的目標轉化率。
- 不同場景發生,這種模式可以廣泛用於分析運營中關注的要素,例如使用者瀏覽商品和購買商品的關聯,關注產品價格和購買產品價格的關聯,加入購物車與購買的關聯。這種關聯可以找到使用者在一個事件中不同行為之間的關聯,可以用來挖掘使用者的真實需求,有針對性的對當前使用者進行個性化推薦,同時也對定價策略有參考價值。
- 相同場景發生,使用者在同一個頁面中點選不同功能、選擇不同的應用。這種關聯可以用於分析使用者使用功能的先後順序,有利於做產品優化和使用者體驗提升;對於不同產品功能組合、開發和升級有了更加明確地參考方向,便於針對永輝習慣性操作模式做功能迭代;同時針對使用者頻繁檢視和點選的內容,可以採用打包、組合、輪轉等策略,幫助客戶查詢,同時增加內容曝光度和使用者體驗。
python程式碼實現
apriori模組:
# -*- coding: utf-8 -*-
from numpy import *
import re
def createData(fileName):
mat = []
req = re.compile(r',')
fr = open(fileName)
content = fr.readlines()
for line in content:
tem = line.replace('\n','').split(',')
mat.append(tem)
return mat
def loadDataSet():
return [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]
# C1 是大小為1的所有候選項集的集合
def createC1(dataSet):
C1 = []
for transaction in dataSet:
for item in transaction:
if not [item] in C1:
C1.append([item]) #store all the item unrepeatly
C1.sort()
#return map(frozenset, C1)#frozen set, user can't change it.
return list(map(frozenset, C1))
def scanD(D,Ck,minSupport):
ssCnt={}
for tid in D:
for can in Ck:
if can.issubset(tid):
#if not ssCnt.has_key(can):
if not can in ssCnt:
ssCnt[can]=1
else: ssCnt[can]+=1
numItems=float(len(D))
retList = []
supportData = {}
for key in ssCnt:
support = ssCnt[key]/numItems #compute support
if support >= minSupport:
retList.insert(0,key)
supportData[key] = support
return retList, supportData
#total apriori
def aprioriGen(Lk, k): #組合,向上合併
#creates Ck 引數:頻繁項集列表 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: #若兩個集合的前k-2個項相同時,則將兩個集合合併
retList.append(Lk[i] | Lk[j]) #set union
return retList
#apriori
def apriori(dataSet, minSupport = 0.5):
C1 = createC1(dataSet)
D = list(map(set, dataSet)) #python3
L1, supportData = scanD(D, C1, minSupport)#單項最小支援度判斷 0.5,生成L1
L = [L1]
k = 2
while (len(L[k-2]) > 0):#建立包含更大項集的更大列表,直到下一個大的項集為空
Ck = aprioriGen(L[k-2], k)#Ck
Lk, supK = scanD(D, Ck, minSupport)#get Lk
supportData.update(supK)
L.append(Lk)
k += 1 #繼續向上合併 生成項集個數更多的
return L, supportData
#生成關聯規則
# 建立關聯規則
def generateRules(fileName, L, supportData, minConf=0.7): # supportData是從scanD獲得的欄位
bigRuleList = []
for i in range(1, len(L)): # 只獲得又有2個或以上的專案的集合
for freqSet in L[i]:
H1 = [frozenset([item]) for item in freqSet]
if (i > 1):
rulesFromConseq(fileName, freqSet, H1, supportData, bigRuleList, minConf)
else:
calcConf(fileName, freqSet, H1, supportData, bigRuleList, minConf)
return bigRuleList
# 例項數、支援度、置信度和提升度評估
def calcConf(fileName, freqSet, H, supportData, brl, minConf=0.7):
prunedH = []
D = fileName
numItems = float(len(D))
for conseq in H:
conf = supportData[freqSet] / supportData[freqSet - conseq] # 計算置信度
if conf >= minConf:
instances = numItems * supportData[freqSet] # 計算例項數
liftvalue = conf / supportData[conseq] # 計算提升度
brl.append((freqSet - conseq, conseq, int(instances), round(supportData[freqSet], 4), round(conf, 4),
round(liftvalue, 4))) # 支援度已經在SCAND中計算得出
prunedH.append(conseq)
return prunedH
# 生成候選規則集
def rulesFromConseq(fileName, freqSet, H, supportData, brl, minConf=0.7):
m = len(H[0])
if (len(freqSet) > (m + 1)):
Hmp1 = aprioriGen(H, m + 1)
Hmp1 = calcConf(fileName, freqSet, Hmp1, supportData, brl, minConf)
if (len(Hmp1) > 1):
rulesFromConseq(fileName, freqSet, Hmp1, supportData, brl, minConf)
apriori演算法實現:
import apriori
import pandas as pd
from graphviz import Digraph
# 設定最小支援度閾值
minS = 0.5
# 設定最小置信度閾值
minC = 0.7
data = apriori.loadDataSet()
# 計算符合最小支援度的規則
L, suppdata = apriori.apriori(data, minSupport=minS)
# 計算滿足最小置信度規則
rules = apriori.generateRules(data, L, suppdata, minConf=minC)
### 關聯結果評估###
model_summary = 'data record: {1} \nassociation rules count: {0}' # 展示資料集記錄數和滿足閾值定義的規則數量
print (model_summary.format(len(rules), len(data))) # 使用str.format做格式化輸出
df = pd.DataFrame(rules, columns=['item1', 'itme2', 'instance', 'support',
'confidence', 'lift']) # 建立頻繁規則資料框
df_lift = df[df['lift'] > 1.0] # 只選擇提升度>1的規則
df_lift.sort_values('instance', ascending=False)
# 關聯結果圖形展示
dot = Digraph() # 建立有向圖
graph_data = df_lift[['item1', 'itme2', 'instance']] # 切分畫圖用的前項、後項和例項數資料
for each_data in graph_data.values: # 迴圈讀出每條規則
node1, node2, weight = each_data # 分割每條資料畫圖用的前項、後項和例項數
node1 = str(node1).strip('frozenset({})') # 轉化為字串
node2 = str(node2).strip('frozenset({})') # 轉化為字串
label = '%s' % weight # 建立一個標籤用於展示例項數
dot.node(node1, node1, shape='record') # 增加節點(規則中的前項)
dot.edge(node1, node2, label=label, constraint='true') # 增加有向邊
dot.render('apriori', view=True) # 儲存規則為pdf檔案
使用pyfpgrowth模組實現FP-Growth:
import pyfpgrowth
# 資料
data = [[1, 2, 5],
[2, 4],
[2, 3],
[1, 2, 4],
[1, 3],
[2, 3],
[1, 3],
[1, 2, 3, 5],
[1, 2, 3]]
# 設定支援度和置信度
minS = 0.2
minC = 0.7
# 計算支援值
support = minS*len(data)
# 獲取符合支援度規則資料
patterns = pyfpgrowth.find_frequent_patterns(data, support)
# 獲取符合置信度規則資料
rules = pyfpgrowth.generate_association_rules(patterns, minC)
rules
結果如下:
{(5,): ((1, 2), 1.0),
(1, 5): ((2,), 1.0),
(2, 5): ((1,), 1.0),
(4,): ((2,), 1.0)}
補充
除了打包組合的思維方式之外,還可以這樣考慮應用:既然使用者具有較強的發生關聯事件關係(例如購買、檢視等)的可能性,那麼可以基於使用者的這種習慣,將前後項內容故意分離開,利用使用者主動查詢的時機來產生更多價值或完成特定轉化目標。
例如:使用者經常一起購買啤酒和尿布,我們可以分別將啤酒和尿布陳列在展櫃的兩端(或者隔開一段距離),然後在使用者購買啤酒又去購買尿布的途中,也許會發現別的商品進而產生興趣,從而實現更多的銷售。但是需要注意這種關聯需求的效用能否支撐這種搜尋過程,則剛需最好,強有效規則其次,不可過多降低使用者體驗。
序列模式的關聯規則:
序列模式相較於普通關聯模式最大的區別是不同的事件之間具有明顯的時間區隔,以及先後的序列發生關係,能得到類似於“完成某個事件之後會在特定的時間週期內完成其他事件”的結論,例如購買了冰箱的客戶會在3個月內購買洗衣機的結論。這是一種預測性分析的模式,能夠將事件發生的時間和物件提取出來,使用與基於時間序列的資料化運營需求。
應用場景:
- 基於使用者上一次購買時間和商品資訊,推斷使用者下一次購物時間和購買的商品,如果使用者脫離週期過久需要實施挽留措施
- 基於使用者上一次瀏覽頁面的時間和頁面資訊,推斷使用者下一次可能瀏覽的頁面
- 通過上衣此關鍵字的搜尋預測下一次最可能搜尋的關鍵字
能實現序列模式的關聯演算法包括:
- AprioriAll:基於雜湊樹的序列關聯演算法,它與Apriori演算法的執行過程是一樣的,不同點在於候選集的產生,需要區分最後兩個元素的前後順序。
- AprioriSome:該演算法是對AprioriAll演算法的改進。
- CARMA(Continuous Association Rule Mining Algorithm):CARMA是一種比較新的關聯規則演算法,能夠處理線上連續交易流資料。
- GSP(Generalized Sequential Patterns):基於水平儲存結構和雜湊樹遍歷操作的序列關聯演算法,它具有類似於Apriori演算法的實現步驟,主要區別在於產生候選序列模式。
- SPADE(Sequential PAttern Discovery using Equivalence classes):基於垂直儲存結構和格理論連線操作的序列關聯演算法,它是一種改進的GSP演算法。
- FreeSpan:頻繁模式投影的序列關聯演算法,利用頻繁項遞迴地將序列資料庫投影到更小的投影資料庫集中,在每個投影資料庫中生成子序列片斷,是一種分治思想的演算法。
- PrefixSpan(Prefix-Projected Pattern Growth):基於字首樹的序列關聯演算法,從Free-Span中推導演化而來
參考:
《python資料分析與資料化運營》 宋天龍