規(guī)則關(guān)聯(lián)引入了兩個數(shù)學(xué)度量公式來度量頻繁度與關(guān)聯(lián)度耿币。本主題就是說明這么兩件事兒铐殃,當(dāng)然最后的結(jié)果是產(chǎn)生關(guān)聯(lián)規(guī)則螃概。
??1. 頻繁度:支持度
??2. 關(guān)聯(lián)度:置信度
??3. 實現(xiàn)頻繁集尋找與規(guī)則生成采盒。
算法適合用于商品推薦,屬于無監(jiān)督學(xué)習(xí)兼砖。
關(guān)聯(lián)分析算法說明
-
關(guān)聯(lián)分析:
- 在大規(guī)模數(shù)據(jù)集中尋找有意義的關(guān)系奸远,包含兩個過程:
- 找出:頻繁項集(Frequent Item Sets):
- 出現(xiàn)次數(shù)比較多的數(shù)據(jù)項(物品)的集合;
- 項集:一個或者多個數(shù)據(jù)項的集合(物品的集合)讽挟;
- 項集的大小機(jī)會項集中數(shù)據(jù)項的個數(shù)懒叛。
- 再從頻繁項集中找出:關(guān)聯(lián)規(guī)則(Association Rules):
- 兩個數(shù)據(jù)項(物品)之間的關(guān)系
- 找出:頻繁項集(Frequent Item Sets):
- 在大規(guī)模數(shù)據(jù)集中尋找有意義的關(guān)系奸远,包含兩個過程:
-
關(guān)聯(lián)分析的特點:
- 適合大數(shù)據(jù)樣本;
- 但是在大數(shù)據(jù)樣本下耽梅,速度比較慢薛窥;
關(guān)聯(lián)分析的實現(xiàn)思路
- 關(guān)聯(lián)分析引入了兩個量來度量頻繁度與關(guān)聯(lián)度:
支持度
- 頻繁度的度量-支持度(Support):
- 就是已知數(shù)據(jù)項同時出現(xiàn)的頻率;
- 數(shù)據(jù)集中包含數(shù)據(jù)項的比例 = 眼姐。
- 一個數(shù)據(jù)項構(gòu)成的項集的情況:诅迷。
- 多個數(shù)據(jù)項的構(gòu)成的項集情況:罢杉。
置信度
- 關(guān)聯(lián)度的度量-置信度(Confidence):
- 就是條件概率:數(shù)據(jù)項1出現(xiàn)的情況下,數(shù)據(jù)項2出現(xiàn)的條件概率贡歧;
- P(數(shù)據(jù)項1 | 數(shù)據(jù)項2) =
支持度與置信度的理解例子
- 使用著名的豆奶尿布說明支持度與置信度的概念:
交易流水號 | 商品 |
---|---|
01 | 豆奶滩租,萵苣 |
02 | 萵苣,尿布利朵,葡萄酒律想,甜菜 |
03 | 豆奶,尿布绍弟,葡萄酒技即,橙汁 |
04 | 萵苣,豆奶樟遣,尿布而叼,葡萄酒 |
05 | 萵苣郭脂,豆奶,尿布澈歉,橙汁 |
-
支持度:
- 豆奶的支持度:
- (豆奶,尿布)的支持度 =
-
置信度:
- (葡萄酒埃难,尿布)的置信度 =
-
支持度與置信度公式:
- 聯(lián)合概率:
- 條件概率:
尋找最大頻繁項集的算法
頻繁項集的算法
-
頻繁項集的尋找算法:
-
假設(shè), 有一個大小為的數(shù)據(jù)集合,并:
- 構(gòu)建一個個項組成的備選項集的列表涤久;
- 計算每個備選項集的支持度涡尘;
- 根據(jù)支持度,保留頻繁的項集,得到保留項集列表响迂;
- 考抄,使用保留項集列表,構(gòu)建數(shù)據(jù)集合蔗彤,并繼續(xù)第1步川梅。
算法次循環(huán)結(jié)束,得到個保留項集列表
-
-
尋找最大頻繁項集核心包含三個:
- 構(gòu)建備選項集列表然遏;
- 計算每個備選項集的支持度贫途;
- 根據(jù)支持選取的項集的標(biāo)準(zhǔn),生成保留項集列表待侵;
- 豆奶與尿布的頻繁集經(jīng)典說明
頻繁項集算法實現(xiàn)
構(gòu)建備選項集列表
- 原始數(shù)據(jù)集
import numpy as np
# 準(zhǔn)備數(shù)據(jù)集
data = np.array([
['豆奶', '萵苣'],
['萵苣', '尿布', '葡萄酒', '甜菜'],
['豆奶', '尿布', '葡萄酒', '橙汁'],
['萵苣', '豆奶', '尿布', '葡萄酒'],
['萵苣', '豆奶', '尿布', '橙汁']
])
- 構(gòu)建數(shù)據(jù)集合
S = set()
for item in data:
S = S | frozenset(item)
print(S)
{'萵苣', '豆奶', '甜菜', '尿布', '橙汁', '葡萄酒'}
- 構(gòu)建備選項集列表
- 從數(shù)據(jù)集合構(gòu)建
C_1 = [] # 備選項集列表
for s in S:
C_1.append(frozenset([s]))
C_1
[frozenset({'萵苣'}),
frozenset({'豆奶'}),
frozenset({'甜菜'}),
frozenset({'尿布'}),
frozenset({'橙汁'}),
frozenset({'葡萄酒'})]
-
從項集列表提升構(gòu)建
- 為什么要從已有項集列表產(chǎn)生新的項集列表丢早?
- 如果被拋棄的項集支持度最低,則任何包含這個項集的項集的支持度也會是最低的秧倾,也是被拋棄對象怨酝。
- 提升構(gòu)建就是從大小為的項集列表提升為的項集列表。
- 為什么要從已有項集列表產(chǎn)生新的項集列表丢早?
從1到2的情況
# 要構(gòu)建的長度為2備選項集列表
C_2 = []
# 不是從集合構(gòu)建那先,而是從已有頻繁項集列表中構(gòu)建农猬。
# 從C_1中兩兩組合
len_C = len(C_1)
for i in range(len_C):
for j in range(i+1, len_C):
C_2.append(C_1[i] | C_1[j])
C_2
[frozenset({'萵苣', '豆奶'}),
frozenset({'甜菜', '萵苣'}),
frozenset({'尿布', '萵苣'}),
frozenset({'橙汁', '萵苣'}),
frozenset({'萵苣', '葡萄酒'}),
frozenset({'甜菜', '豆奶'}),
frozenset({'尿布', '豆奶'}),
frozenset({'橙汁', '豆奶'}),
frozenset({'葡萄酒', '豆奶'}),
frozenset({'尿布', '甜菜'}),
frozenset({'橙汁', '甜菜'}),
frozenset({'甜菜', '葡萄酒'}),
frozenset({'尿布', '橙汁'}),
frozenset({'尿布', '葡萄酒'}),
frozenset({'橙汁', '葡萄酒'})]
- 從2到3的情況
C_3 = []
len_C = len(C_2)
for i in range(len_C):
for j in range(i+1, len_C):
# 為了從2變成3,取最后一個不同的合并(前面1個相同胃榕,后面一個不同盛险,就山城長度為3的項集)
# {'萵苣', '豆奶'}, {'萵苣', '葡萄酒'}, 合并就是{'萵苣', '豆奶', '葡萄酒'},
item_outer = list(C_2[i]) # 外層循環(huán)的數(shù)據(jù),轉(zhuǎn)換為list是為了比較方便
item_inner = list(C_2[j]) # 內(nèi)層循環(huán)的數(shù)據(jù)
# 取全面3-2 =1 的數(shù)據(jù)比較
#(構(gòu)建是長度為3的項集列表勋又,實際項集列表長度為2苦掘,只對最后一列差異化檢測,就需要對前面2-1楔壤,或者3-2的數(shù)據(jù)比較)
# 2-1:2是上次項集列表大小鹤啡,3是構(gòu)建的項集列表大小。
c_outer = item_outer[0:3-2] # item_outer[0:2-1] 2表示舊的項集大小
c_inner = item_inner[0:3-2]
c_outer.sort() # 排序是為了比較
c_inner.sort()
if c_outer == c_inner:
C_3.append(C_2[i] | C_2[j])
C_3
[frozenset({'甜菜', '萵苣', '豆奶'}),
frozenset({'尿布', '萵苣', '豆奶'}),
frozenset({'橙汁', '萵苣', '豆奶'}),
frozenset({'萵苣', '葡萄酒', '豆奶'}),
frozenset({'尿布', '甜菜', '萵苣'}),
frozenset({'橙汁', '甜菜', '萵苣'}),
frozenset({'甜菜', '萵苣', '葡萄酒'}),
frozenset({'尿布', '橙汁', '萵苣'}),
frozenset({'尿布', '萵苣', '葡萄酒'}),
frozenset({'橙汁', '萵苣', '葡萄酒'}),
frozenset({'尿布', '甜菜', '豆奶'}),
frozenset({'橙汁', '甜菜', '豆奶'}),
frozenset({'甜菜', '葡萄酒', '豆奶'}),
frozenset({'尿布', '葡萄酒', '豆奶'}),
frozenset({'尿布', '橙汁', '豆奶'}),
frozenset({'橙汁', '葡萄酒', '豆奶'}),
frozenset({'尿布', '橙汁', '甜菜'}),
frozenset({'尿布', '甜菜', '葡萄酒'}),
frozenset({'橙汁', '甜菜', '葡萄酒'}),
frozenset({'尿布', '橙汁', '葡萄酒'})]
- 通用的規(guī)律實現(xiàn):
def generate_item_set(C_k_1, k):
# C_k_1 表示項集大小為k-1的列表
# k表示新的項集大小
C_k = []
len_C = len(C_k_1)
for i in range(len_C):
for j in range(i+1, len_C):
# 為了從2變成3蹲嚣,取最后一個不同的合并(前面1個相同递瑰,后面一個不同祟牲,就山城長度為3的項集)
# {'萵苣', '豆奶'}, {'萵苣', '葡萄酒'}, 合并就是{'萵苣', '豆奶', '葡萄酒'},
item_outer = list(C_k_1[i]) # 外層循環(huán)的數(shù)據(jù),轉(zhuǎn)換為list是為了比較方便
item_inner = list(C_k_1[j]) # 內(nèi)層循環(huán)的數(shù)據(jù)
# 取全面3-2 =1 的數(shù)據(jù)比較
#(構(gòu)建是長度為3的項集列表抖部,實際項集列表長度為2说贝,只對最后一列差異化檢測,就需要對前面2-1慎颗,或者3-2的數(shù)據(jù)比較)
# 2-1:2是上次項集列表大小乡恕,3是構(gòu)建的項集列表大小。
c_outer = item_outer[0:k-2]
c_inner = item_inner[0:k-2]
c_outer.sort() # 排序是為了比較
c_inner.sort()
if c_outer == c_inner:
C_k.append(C_k_1[i] | C_k_1[j])
return C_k
C_2 = generate_item_set(C_1,2)
C_2
[frozenset({'萵苣', '豆奶'}),
frozenset({'甜菜', '萵苣'}),
frozenset({'尿布', '萵苣'}),
frozenset({'橙汁', '萵苣'}),
frozenset({'萵苣', '葡萄酒'}),
frozenset({'甜菜', '豆奶'}),
frozenset({'尿布', '豆奶'}),
frozenset({'橙汁', '豆奶'}),
frozenset({'葡萄酒', '豆奶'}),
frozenset({'尿布', '甜菜'}),
frozenset({'橙汁', '甜菜'}),
frozenset({'甜菜', '葡萄酒'}),
frozenset({'尿布', '橙汁'}),
frozenset({'尿布', '葡萄酒'}),
frozenset({'橙汁', '葡萄酒'})]
C_3 = generate_item_set(C_2,3)
C_3
[frozenset({'甜菜', '萵苣', '豆奶'}),
frozenset({'尿布', '萵苣', '豆奶'}),
frozenset({'橙汁', '萵苣', '豆奶'}),
frozenset({'萵苣', '葡萄酒', '豆奶'}),
frozenset({'尿布', '甜菜', '萵苣'}),
frozenset({'橙汁', '甜菜', '萵苣'}),
frozenset({'甜菜', '萵苣', '葡萄酒'}),
frozenset({'尿布', '橙汁', '萵苣'}),
frozenset({'尿布', '萵苣', '葡萄酒'}),
frozenset({'橙汁', '萵苣', '葡萄酒'}),
frozenset({'尿布', '甜菜', '豆奶'}),
frozenset({'橙汁', '甜菜', '豆奶'}),
frozenset({'甜菜', '葡萄酒', '豆奶'}),
frozenset({'尿布', '葡萄酒', '豆奶'}),
frozenset({'尿布', '橙汁', '豆奶'}),
frozenset({'橙汁', '葡萄酒', '豆奶'}),
frozenset({'尿布', '橙汁', '甜菜'}),
frozenset({'尿布', '甜菜', '葡萄酒'}),
frozenset({'橙汁', '甜菜', '葡萄酒'}),
frozenset({'尿布', '橙汁', '葡萄酒'})]
計算支持度
- 計算支持度的關(guān)鍵是統(tǒng)計項集在元素數(shù)據(jù)集中同時出現(xiàn)的次數(shù)俯萎;
- 這個涉及集合的包含運算傲宜。
- 數(shù)據(jù)準(zhǔn)備
- 把原始數(shù)據(jù)集轉(zhuǎn)變成集合的列表
- 需要一個候選項集列表
# 原始數(shù)據(jù)
data = np.array([
['豆奶', '萵苣'],
['萵苣', '尿布', '葡萄酒', '甜菜'],
['豆奶', '尿布', '葡萄酒', '橙汁'],
['萵苣', '豆奶', '尿布', '葡萄酒'],
['萵苣', '豆奶', '尿布', '橙汁']
])
D = list(map(frozenset, data))
D
[frozenset({'萵苣', '豆奶'}),
frozenset({'尿布', '甜菜', '萵苣', '葡萄酒'}),
frozenset({'尿布', '橙汁', '葡萄酒', '豆奶'}),
frozenset({'尿布', '萵苣', '葡萄酒', '豆奶'}),
frozenset({'尿布', '橙汁', '萵苣', '豆奶'})]
# 把原始數(shù)據(jù)集編程一個數(shù)據(jù)項集合。
S = frozenset()
for item in D:
S = S | item
# 使用數(shù)據(jù)項集合生成C1備選項集列表
C_1 = [] # 備選項集列表
for s in S:
C_1.append(frozenset([s]))
C_1
[frozenset({'萵苣'}),
frozenset({'豆奶'}),
frozenset({'甜菜'}),
frozenset({'尿布'}),
frozenset({'橙汁'}),
frozenset({'葡萄酒'})]
C_2 = generate_item_set(C_1,2)
C_3 = generate_item_set(C_2,3)
C_2, C_3
([frozenset({'萵苣', '豆奶'}),
frozenset({'甜菜', '萵苣'}),
frozenset({'尿布', '萵苣'}),
frozenset({'橙汁', '萵苣'}),
frozenset({'萵苣', '葡萄酒'}),
frozenset({'甜菜', '豆奶'}),
frozenset({'尿布', '豆奶'}),
frozenset({'橙汁', '豆奶'}),
frozenset({'葡萄酒', '豆奶'}),
frozenset({'尿布', '甜菜'}),
frozenset({'橙汁', '甜菜'}),
frozenset({'甜菜', '葡萄酒'}),
frozenset({'尿布', '橙汁'}),
frozenset({'尿布', '葡萄酒'}),
frozenset({'橙汁', '葡萄酒'})],
[frozenset({'甜菜', '萵苣', '豆奶'}),
frozenset({'尿布', '萵苣', '豆奶'}),
frozenset({'橙汁', '萵苣', '豆奶'}),
frozenset({'萵苣', '葡萄酒', '豆奶'}),
frozenset({'尿布', '甜菜', '萵苣'}),
frozenset({'橙汁', '甜菜', '萵苣'}),
frozenset({'甜菜', '萵苣', '葡萄酒'}),
frozenset({'尿布', '橙汁', '萵苣'}),
frozenset({'尿布', '萵苣', '葡萄酒'}),
frozenset({'橙汁', '萵苣', '葡萄酒'}),
frozenset({'尿布', '甜菜', '豆奶'}),
frozenset({'橙汁', '甜菜', '豆奶'}),
frozenset({'甜菜', '葡萄酒', '豆奶'}),
frozenset({'尿布', '葡萄酒', '豆奶'}),
frozenset({'尿布', '橙汁', '豆奶'}),
frozenset({'橙汁', '葡萄酒', '豆奶'}),
frozenset({'尿布', '橙汁', '甜菜'}),
frozenset({'尿布', '甜菜', '葡萄酒'}),
frozenset({'橙汁', '甜菜', '葡萄酒'}),
frozenset({'尿布', '橙汁', '葡萄酒'})])
-
計算支持度
- 下面算法中set類型不能做字典key夫啊,只有frozenset才能使用字典key函卒,所以在所有操作中使用frozenset構(gòu)建集合。
# 使用字典存放統(tǒng)計結(jié)果
item_count = {}
# 循環(huán)計算每個項集的支持度
for c in C_3:
# 循環(huán)統(tǒng)計在原始數(shù)據(jù)中出現(xiàn)的次數(shù)
for d in D:
if c.issubset(d): # 項集包含在原始數(shù)據(jù)項中
item_count[c] = item_count.get(c, 0) + 1
item_count
{frozenset({'尿布', '萵苣', '豆奶'}): 2,
frozenset({'橙汁', '萵苣', '豆奶'}): 1,
frozenset({'萵苣', '葡萄酒', '豆奶'}): 1,
frozenset({'尿布', '甜菜', '萵苣'}): 1,
frozenset({'甜菜', '萵苣', '葡萄酒'}): 1,
frozenset({'尿布', '橙汁', '萵苣'}): 1,
frozenset({'尿布', '萵苣', '葡萄酒'}): 2,
frozenset({'尿布', '葡萄酒', '豆奶'}): 2,
frozenset({'尿布', '橙汁', '豆奶'}): 2,
frozenset({'橙汁', '葡萄酒', '豆奶'}): 1,
frozenset({'尿布', '甜菜', '葡萄酒'}): 1,
frozenset({'尿布', '橙汁', '葡萄酒'}): 1}
# 支持度計算如下:
item_support = {}
total_num = len(D)
for k, v in item_count.items():
item_support[k] = v / total_num
item_support
{frozenset({'尿布', '萵苣', '豆奶'}): 0.4,
frozenset({'橙汁', '萵苣', '豆奶'}): 0.2,
frozenset({'萵苣', '葡萄酒', '豆奶'}): 0.2,
frozenset({'尿布', '甜菜', '萵苣'}): 0.2,
frozenset({'甜菜', '萵苣', '葡萄酒'}): 0.2,
frozenset({'尿布', '橙汁', '萵苣'}): 0.2,
frozenset({'尿布', '萵苣', '葡萄酒'}): 0.4,
frozenset({'尿布', '葡萄酒', '豆奶'}): 0.4,
frozenset({'尿布', '橙汁', '豆奶'}): 0.4,
frozenset({'橙汁', '葡萄酒', '豆奶'}): 0.2,
frozenset({'尿布', '甜菜', '葡萄酒'}): 0.2,
frozenset({'尿布', '橙汁', '葡萄酒'}): 0.2}
根據(jù)支持度返回頻繁項集列表
- 把支持度封裝成函數(shù)
- 同時設(shè)置一個支持度閾值撇眯,用于保留頻繁項集列表报嵌。
def calcute_support(D, C, threshold):
# 使用字典存放統(tǒng)計結(jié)果
item_count = {}
total_num = len(D)
# 循環(huán)計算每個項集的支持度
for c in C:
# 循環(huán)統(tǒng)計在原始數(shù)據(jù)中出現(xiàn)的次數(shù)
for d in D:
if c.issubset(d): # 項集包含在原始數(shù)據(jù)項中
item_count[c] = item_count.get(c, 0) + 1
# 支持度計算如下:
item_support = {}
total_num = len(D)
for k, v in item_count.items():
support = v / total_num
if support >= threshold:
item_support[k] = support
return item_support
O = calcute_support(D,C_3,0.4)
O, list(O.keys())
({frozenset({'尿布', '萵苣', '豆奶'}): 0.4,
frozenset({'尿布', '萵苣', '葡萄酒'}): 0.4,
frozenset({'尿布', '葡萄酒', '豆奶'}): 0.4,
frozenset({'尿布', '橙汁', '豆奶'}): 0.4},
[frozenset({'尿布', '萵苣', '豆奶'}),
frozenset({'尿布', '萵苣', '葡萄酒'}),
frozenset({'尿布', '葡萄酒', '豆奶'}),
frozenset({'尿布', '橙汁', '豆奶'})])
- 返回所有的頻繁項集列表的列表
def generate_item_set(C_k_1, k):
# C_k_1 表示項集大小為k-1的列表
# k表示新的項集大小
C_k = []
len_C = len(C_k_1)
for i in range(len_C):
for j in range(i+1, len_C):
# 為了從2變成3,取最后一個不同的合并(前面1個相同叛本,后面一個不同沪蓬,就山城長度為3的項集)
# {'萵苣', '豆奶'}, {'萵苣', '葡萄酒'}, 合并就是{'萵苣', '豆奶', '葡萄酒'},
item_outer = list(C_k_1[i]) # 外層循環(huán)的數(shù)據(jù),轉(zhuǎn)換為list是為了比較方便
item_inner = list(C_k_1[j]) # 內(nèi)層循環(huán)的數(shù)據(jù)
# 取全面3-2 =1 的數(shù)據(jù)比較
#(構(gòu)建是長度為3的項集列表来候,實際項集列表長度為2跷叉,只對最后一列差異化檢測,就需要對前面2-1营搅,或者3-2的數(shù)據(jù)比較)
# 2-1:2是上次項集列表大小云挟,3是構(gòu)建的項集列表大小。
c_outer = item_outer[0:k-2]
c_inner = item_inner[0:k-2]
c_outer.sort() # 排序是為了比較
c_inner.sort()
if c_outer == c_inner:
C_k.append(C_k_1[i] | C_k_1[j])
return C_k
def calcute_support(D, C, threshold):
# 使用字典存放統(tǒng)計結(jié)果
item_count = {}
total_num = len(D)
# 循環(huán)計算每個項集的支持度
for c in C:
# 循環(huán)統(tǒng)計在原始數(shù)據(jù)中出現(xiàn)的次數(shù)
for d in D:
if c.issubset(d): # 項集包含在原始數(shù)據(jù)項中
item_count[c] = item_count.get(c, 0) + 1
# 支持度計算如下:
item_support = {}
total_num = len(D)
for k, v in item_count.items():
support = v / total_num
if support >= threshold:
item_support[k] = support
return item_support
def get_all_often(data, support):
all_often = {}
# 把數(shù)據(jù)集轉(zhuǎn)換為集合的列表
D = list(map(frozenset, data))
# 生成備選項集列表
S = frozenset()
for item in D:
S = S | item
# 使用數(shù)據(jù)項集合生成C1備選項集列表
C_1 = [] # 備選項集列表
for s in S:
C_1.append(frozenset([s]))
# 計算C1的頻繁項集列表
O_1 = calcute_support(D, C_1, support)
all_often.update(O_1)
# 訓(xùn)練計算2转质,3园欣,4,休蟹。沸枯。。直到返回的列表為0
# print(O_1)
k = 2
while True:
# 候選項集列表
C = generate_item_set(list(O_1.keys()), k)
O = calcute_support(D, C, support)
# 如果沒有備選項集列表赂弓,則結(jié)束
if len(O)==0:
break
k +=1
all_often.update(O)
O_1 = O
return all_often
data = np.array([
['豆奶', '萵苣'],
['萵苣', '尿布', '葡萄酒', '甜菜'],
['豆奶', '尿布', '葡萄酒', '橙汁'],
['萵苣', '豆奶', '尿布', '葡萄酒'],
['萵苣', '豆奶', '尿布', '橙汁']
])
list_often = get_all_often(data, 0.4)
list_often
{frozenset({'萵苣'}): 0.8,
frozenset({'豆奶'}): 0.8,
frozenset({'尿布'}): 0.8,
frozenset({'橙汁'}): 0.4,
frozenset({'葡萄酒'}): 0.6,
frozenset({'萵苣', '豆奶'}): 0.6,
frozenset({'尿布', '萵苣'}): 0.6,
frozenset({'萵苣', '葡萄酒'}): 0.4,
frozenset({'尿布', '豆奶'}): 0.6,
frozenset({'橙汁', '豆奶'}): 0.4,
frozenset({'葡萄酒', '豆奶'}): 0.4,
frozenset({'尿布', '橙汁'}): 0.4,
frozenset({'尿布', '葡萄酒'}): 0.6,
frozenset({'尿布', '萵苣', '豆奶'}): 0.4,
frozenset({'尿布', '萵苣', '葡萄酒'}): 0.4,
frozenset({'尿布', '葡萄酒', '豆奶'}): 0.4,
frozenset({'尿布', '橙汁', '豆奶'}): 0.4}
得到關(guān)聯(lián)規(guī)則
- 規(guī)則度量是置信度(就是條件概率)
理解關(guān)聯(lián)規(guī)則
- 所謂關(guān)聯(lián)規(guī)則就是在已經(jīng)得到頻繁項集的基礎(chǔ)上绑榴,可以使用頻繁項集生成關(guān)聯(lián)規(guī)則:
- 假設(shè)項集為{'尿布', '甜菜', '萵苣', '葡萄酒'},則可以生成很多規(guī)則:
- {尿布', '甜菜', '萵苣'} -> {'葡萄酒'}
- {'尿布', '甜菜', '葡萄酒'} -> {'萵苣'}
- {'尿布', '萵苣', '葡萄酒'} -> {'甜菜'}
- {'甜菜', '萵苣', '葡萄酒'} -> {'尿布''}
- { '甜菜', '萵苣'} -> {'尿布', '葡萄酒'}
- 關(guān)聯(lián)規(guī)則表示為:項集 -> 項集
- 后面項集稱為:后繼(consequent或者right-hand-side:RHS):
- 根據(jù)后繼大小稱為n-后繼盈魁;比如上面的就是1-后繼翔怎。
- 前面項集稱為:先導(dǎo)(antecedent或left-hand-side:LHS)
- 后面項集稱為:后繼(consequent或者right-hand-side:RHS):
- 關(guān)聯(lián)規(guī)則可以分成強(qiáng)關(guān)聯(lián)規(guī)則與弱關(guān)聯(lián)規(guī)則:
- 強(qiáng)關(guān)聯(lián)規(guī)則:支持度與置信度都滿足閾值的。
- 弱關(guān)聯(lián)規(guī)則:支持度與置信度只有一個滿足閾值的。
- 假設(shè)項集為{'尿布', '甜菜', '萵苣', '葡萄酒'},則可以生成很多規(guī)則:
- 關(guān)聯(lián)規(guī)則分析就是:
- 計算關(guān)聯(lián)規(guī)則的置信度赤套。
- 找出滿足閾值的關(guān)聯(lián)規(guī)則飘痛。
分析1-后繼關(guān)鍵規(guī)則
# 這里我們只計算1-后繼的情況
# 規(guī)則的存放形式{(先導(dǎo),后繼), 置信度}
# 生成關(guān)聯(lián)規(guī)則容握,計算關(guān)聯(lián)規(guī)則的置信度
def generate_rule_confidence(all_often, often_item, threshold):
# all_often所有的頻繁項集l列表:字典類型宣脉,提供用來計算置信度的支持度
# often_item需要生成規(guī)則項集:集合類型,同來生成規(guī)則
# threshold置信度閾值:小數(shù)類型剔氏,用來保留強(qiáng)關(guān)聯(lián)規(guī)則
# 生成1-后繼的集合(后繼本身也是集合脖旱,大小為1)
rhs_1s = []
for item in often_item:
rhs_1s .append(frozenset([item]))
# 產(chǎn)生規(guī)則,并計算置信度
rules_confidence = {}
for rhs in rhs_1s:
rule = (often_item - rhs, rhs)
# print(all_often[often_item], all_often[rhs], all_often[often_item - rhs])
confidence = all_often[often_item] / all_often[rhs]
if confidence >= threshold:
rules_confidence[rule] = confidence
return rules_confidence
generate_rule_confidence(list_often, list(list_often.keys())[16], 0.5)
{(frozenset({'尿布', '豆奶'}), frozenset({'橙汁'})): 1.0,
(frozenset({'橙汁', '豆奶'}), frozenset({'尿布'})): 0.5,
(frozenset({'尿布', '橙汁'}), frozenset({'豆奶'})): 0.5}
分析所有頻繁項集的規(guī)則
def get_all_rule(list_often, threshold):
all_rules = {}
for item in list(list_often.keys()):
# 只計算項集大于2的情況
if len(item) >=2:
all_rules.update(generate_rule_confidence(list_often, item, threshold))
return all_rules
get_all_rule(list_often, 0.7)
{(frozenset({'豆奶'}), frozenset({'萵苣'})): 0.7499999999999999,
(frozenset({'萵苣'}), frozenset({'豆奶'})): 0.7499999999999999,
(frozenset({'尿布'}), frozenset({'萵苣'})): 0.7499999999999999,
(frozenset({'萵苣'}), frozenset({'尿布'})): 0.7499999999999999,
(frozenset({'豆奶'}), frozenset({'尿布'})): 0.7499999999999999,
(frozenset({'尿布'}), frozenset({'豆奶'})): 0.7499999999999999,
(frozenset({'豆奶'}), frozenset({'橙汁'})): 1.0,
(frozenset({'尿布'}), frozenset({'橙汁'})): 1.0,
(frozenset({'葡萄酒'}), frozenset({'尿布'})): 0.7499999999999999,
(frozenset({'尿布'}), frozenset({'葡萄酒'})): 1.0,
(frozenset({'尿布', '豆奶'}), frozenset({'橙汁'})): 1.0}
進(jìn)一步的思考
- n-后繼的規(guī)則分析介蛉。
- 有好的算法可以減少計算次數(shù)。
- 規(guī)則去重的問題:
- 下面的規(guī)則是否算重復(fù)的:
- (frozenset({'尿布', '豆奶'}), frozenset({'橙汁'})): 1.0}
- (frozenset({'豆奶'}), frozenset({'橙汁'})): 1.0,
- (frozenset({'尿布'}), frozenset({'橙汁'})): 1.0,
- 下面的規(guī)則是否算重復(fù)的:
- 上面代碼更好的通用性溶褪。
實戰(zhàn)
- 分析用戶購買的習(xí)慣與商品的關(guān)系
- 根據(jù)訂單號與商品的關(guān)系币旧。
- 根據(jù)訂單號與商品類別的關(guān)系。
- 分析商品價格與商品的關(guān)系
- 分析價格段與商品的關(guān)系
- 讀取數(shù)據(jù)
import pandas as pd
import numpy as np
detail_data = pd.read_csv('assiocation.csv')
# detail_data[0:10]
- 按照訂單號分組猿妈,形成商品列表
data_product = detail_data[['Order Number', 'Product']]
data_group_by_order = data_product.groupby(['Order Number'])
# for one_group in data_group_by_order:
# print(one_group)
# data_group_by_order.groups
# data_group_by_order.indices
def products_concate(grp):
list_concate = []
for d in grp['Product']:
list_concate .append(d)
return pd.Series(data=[list_concate], index=['Product'])
products = data_group_by_order.apply(products_concate)
list_products = []
for pr in products['Product']:
list_products.append(pr)
# list_products
def generate_item_set(C_k_1, k):
# C_k_1 表示項集大小為k-1的列表
# k表示新的項集大小
C_k = []
len_C = len(C_k_1)
for i in range(len_C):
for j in range(i+1, len_C):
# 為了從2變成3吹菱,取最后一個不同的合并(前面1個相同,后面一個不同彭则,就山城長度為3的項集)
# {'萵苣', '豆奶'}, {'萵苣', '葡萄酒'}, 合并就是{'萵苣', '豆奶', '葡萄酒'},
item_outer = list(C_k_1[i]) # 外層循環(huán)的數(shù)據(jù)鳍刷,轉(zhuǎn)換為list是為了比較方便
item_inner = list(C_k_1[j]) # 內(nèi)層循環(huán)的數(shù)據(jù)
# 取全面3-2 =1 的數(shù)據(jù)比較
#(構(gòu)建是長度為3的項集列表,實際項集列表長度為2俯抖,只對最后一列差異化檢測输瓜,就需要對前面2-1,或者3-2的數(shù)據(jù)比較)
# 2-1:2是上次項集列表大小芬萍,3是構(gòu)建的項集列表大小尤揣。
c_outer = item_outer[0:k-2]
c_inner = item_inner[0:k-2]
c_outer.sort() # 排序是為了比較
c_inner.sort()
if c_outer == c_inner:
C_k.append(C_k_1[i] | C_k_1[j])
return C_k
def calcute_support(D, C, threshold):
# 使用字典存放統(tǒng)計結(jié)果
item_count = {}
total_num = len(D)
# 循環(huán)計算每個項集的支持度
for c in C:
# 循環(huán)統(tǒng)計在原始數(shù)據(jù)中出現(xiàn)的次數(shù)
for d in D:
if c.issubset(d): # 項集包含在原始數(shù)據(jù)項中
item_count[c] = item_count.get(c, 0) + 1
# 支持度計算如下:
item_support = {}
total_num = len(D)
for k, v in item_count.items():
support = v / total_num
if support >= threshold:
item_support[k] = support
return item_support
def get_all_often(data, support):
all_often = {}
# 把數(shù)據(jù)集轉(zhuǎn)換為集合的列表
D = list(map(frozenset, data))
# 生成備選項集列表
S = frozenset()
for item in D:
S = S | item
# 使用數(shù)據(jù)項集合生成C1備選項集列表
C_1 = [] # 備選項集列表
for s in S:
C_1.append(frozenset([s]))
# 計算C1的頻繁項集列表
O_1 = calcute_support(D, C_1, support)
all_often.update(O_1)
# 訓(xùn)練計算2,3柬祠,4北戏,。漫蛔。嗜愈。直到返回的列表為0
# print(O_1)
k = 2
while True:
# 候選項集列表
C = generate_item_set(list(O_1.keys()), k)
O = calcute_support(D, C, support)
# 如果沒有備選項集列表,則結(jié)束
if len(O)==0:
break
k +=1
all_often.update(O)
O_1 = O
return all_often
# 這里我們只計算1-后繼的情況
# 規(guī)則的存放形式{(先導(dǎo)莽龟,后繼), 置信度}
# 生成關(guān)聯(lián)規(guī)則蠕嫁,計算關(guān)聯(lián)規(guī)則的置信度
def generate_rule_confidence(all_often, often_item, threshold):
# all_often所有的頻繁項集l列表:字典類型,提供用來計算置信度的支持度
# often_item需要生成規(guī)則項集:集合類型轧房,同來生成規(guī)則
# threshold置信度閾值:小數(shù)類型拌阴,用來保留強(qiáng)關(guān)聯(lián)規(guī)則
# 生成1-后繼的集合(后繼本身也是集合,大小為1)
rhs_1s = []
for item in often_item:
rhs_1s .append(frozenset([item]))
# 產(chǎn)生規(guī)則奶镶,并計算置信度
rules_confidence = {}
for rhs in rhs_1s:
rule = (often_item - rhs, rhs)
# print(all_often[often_item], all_often[rhs], all_often[often_item - rhs])
confidence = all_often[often_item] / all_often[rhs]
if confidence >= threshold:
rules_confidence[rule] = confidence
return rules_confidence
def get_all_rule(list_often, threshold):
all_rules = {}
for item in list(list_often.keys()):
# 只計算項集大于2的情況
if len(item) >=2:
all_rules.update(generate_rule_confidence(list_often, item, threshold))
return all_rules
list_often = get_all_often(list_products, 0.02)
list_often
{frozenset({'Half-Finger Gloves'}): 0.06505747126436781,
frozenset({'HL Mountain Tire'}): 0.0625287356321839,
frozenset({'Touring-3000'}): 0.024521072796934867,
frozenset({'ML Mountain Tire'}): 0.05065134099616858,
frozenset({'Short-Sleeve Classic Jersey'}): 0.07088122605363985,
frozenset({'Fender Set - Mountain'}): 0.09486590038314176,
frozenset({'LL Mountain Tire'}): 0.038237547892720304,
frozenset({'Racing Socks'}): 0.024521072796934867,
frozenset({"Women's Mountain Shorts"}): 0.04475095785440613,
frozenset({'Road-750'}): 0.0642911877394636,
frozenset({'Sport-100'}): 0.290727969348659,
frozenset({'Classic Vest'}): 0.02735632183908046,
frozenset({'Road Tire Tube'}): 0.10551724137931034,
frozenset({'Touring Tire'}): 0.04459770114942529,
frozenset({'Road-350-W'}): 0.04681992337164751,
frozenset({'Bike Wash'}): 0.040229885057471264,
frozenset({'ML Road Tire'}): 0.04084291187739464,
frozenset({'Mountain Bottle Cage'}): 0.09203065134099617,
frozenset({'Mountain-400-W'}): 0.02574712643678161,
frozenset({'Road Bottle Cage'}): 0.07701149425287357,
frozenset({'Hydration Pack'}): 0.032796934865900386,
frozenset({'Mountain-200'}): 0.1128735632183908,
frozenset({'Water Bottle'}): 0.1917241379310345,
frozenset({'HL Road Tire'}): 0.035478927203065135,
frozenset({'Touring Tire Tube'}): 0.06873563218390805,
frozenset({'Long-Sleeve Logo Jersey'}): 0.08068965517241379,
frozenset({'LL Road Tire'}): 0.04659003831417625,
frozenset({'Road-250'}): 0.023065134099616857,
frozenset({'Cycling Cap'}): 0.1,
frozenset({'Road-550-W'}): 0.04735632183908046,
frozenset({'Mountain-500'}): 0.021839080459770115,
frozenset({'Mountain Tire Tube'}): 0.13655172413793104,
frozenset({'Touring-1000'}): 0.0621455938697318,
frozenset({'Patch kit'}): 0.14061302681992338,
frozenset({'Half-Finger Gloves', 'Sport-100'}): 0.026973180076628352,
frozenset({'HL Mountain Tire', 'Sport-100'}): 0.020229885057471263,
frozenset({'HL Mountain Tire', 'Mountain-200'}): 0.024061302681992337,
frozenset({'HL Mountain Tire', 'Mountain Tire Tube'}): 0.042298850574712644,
frozenset({'ML Mountain Tire', 'Mountain Tire Tube'}): 0.03333333333333333,
frozenset({'Fender Set - Mountain', 'Sport-100'}): 0.02436781609195402,
frozenset({'Fender Set - Mountain', 'Mountain-200'}): 0.033563218390804596,
frozenset({'LL Mountain Tire', 'Mountain Tire Tube'}): 0.021226053639846743,
frozenset({'Road Bottle Cage', 'Road-750'}): 0.02475095785440613,
frozenset({'Road-750', 'Water Bottle'}): 0.021302681992337164,
frozenset({'Road Tire Tube', 'Sport-100'}): 0.03977011494252874,
frozenset({'Mountain Bottle Cage', 'Sport-100'}): 0.026436781609195402,
frozenset({'Mountain-200', 'Sport-100'}): 0.03118773946360153,
frozenset({'Sport-100', 'Water Bottle'}): 0.049885057471264364,
frozenset({'Sport-100', 'Touring Tire Tube'}): 0.023065134099616857,
frozenset({'Long-Sleeve Logo Jersey', 'Sport-100'}): 0.022911877394636015,
frozenset({'Cycling Cap', 'Sport-100'}): 0.022375478927203065,
frozenset({'Road-550-W', 'Sport-100'}): 0.020229885057471263,
frozenset({'Mountain Tire Tube', 'Sport-100'}): 0.05739463601532567,
frozenset({'Sport-100', 'Touring-1000'}): 0.02636015325670498,
frozenset({'ML Road Tire', 'Road Tire Tube'}): 0.02781609195402299,
frozenset({'HL Road Tire', 'Road Tire Tube'}): 0.024980842911877396,
frozenset({'LL Road Tire', 'Road Tire Tube'}): 0.025593869731800768,
frozenset({'Patch kit', 'Road Tire Tube'}): 0.0242911877394636,
frozenset({'Touring Tire', 'Touring Tire Tube'}): 0.03885057471264368,
frozenset({'Mountain Bottle Cage', 'Mountain-200'}): 0.03295019157088123,
frozenset({'Mountain Bottle Cage', 'Water Bottle'}): 0.07647509578544061,
frozenset({'Road Bottle Cage', 'Water Bottle'}): 0.06873563218390805,
frozenset({'Mountain-200', 'Water Bottle'}): 0.02636015325670498,
frozenset({'Cycling Cap', 'Water Bottle'}): 0.02950191570881226,
frozenset({'Mountain Tire Tube', 'Patch kit'}): 0.03425287356321839,
frozenset({'Road Bottle Cage',
'Road-750',
'Water Bottle'}): 0.021302681992337164,
frozenset({'Mountain Bottle Cage',
'Sport-100',
'Water Bottle'}): 0.02153256704980843,
frozenset({'Mountain Bottle Cage',
'Mountain-200',
'Water Bottle'}): 0.02636015325670498}
get_all_rule(list_often, 0.6)
{(frozenset({'Mountain Tire Tube'}),
frozenset({'HL Mountain Tire'})): 0.6764705882352942,
(frozenset({'Mountain Tire Tube'}),
frozenset({'ML Mountain Tire'})): 0.6580937972768532,
(frozenset({'Road Tire Tube'}),
frozenset({'ML Road Tire'})): 0.6810506566604128,
(frozenset({'Road Tire Tube'}),
frozenset({'HL Road Tire'})): 0.7041036717062635,
(frozenset({'Touring Tire Tube'}),
frozenset({'Touring Tire'})): 0.8711340206185567,
(frozenset({'Water Bottle'}),
frozenset({'Mountain Bottle Cage'})): 0.8309741881765196,
(frozenset({'Water Bottle'}),
frozenset({'Road Bottle Cage'})): 0.8925373134328357}
- 實戰(zhàn)例子的優(yōu)化:
- 可以考慮商品大類的關(guān)聯(lián)規(guī)則分析迟赃,用來提升關(guān)聯(lián)規(guī)則分析結(jié)果陪拘。