python3 關聯規則Apriori代碼模版


 

 

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from numpy import *
 
def loadDataSet():
    return [['a', 'c', 'e'], ['b', 'd'], ['b', 'c'], ['a', 'b', 'c', 'd'], ['a', 'b'], ['b', 'c'], ['a', 'b'],
            ['a', 'b', 'c', 'e'], ['a', 'b', 'c'], ['a', 'c', 'e']]
 
 
def createC1(dataSet):
    C1 = []
    for transaction in dataSet:
        for item in transaction:
            if not [item] in C1:
                C1.append([item])
    C1.sort()
    # 映射為frozenset唯一性的,可使用其構造字典
    return list(map(frozenset, C1))      
 
 
# 從候選K項集到頻繁K項集(支持度計算)
def scanD(D, Ck, minSupport):
    ssCnt = {}
    for tid in D:
        for can in Ck:
            if can.issubset(tid):
                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
        if support >= minSupport:
            retList.insert(0, key)
            supportData[key] = support  
    return retList, supportData
 
 
def calSupport(D, Ck, min_support):
    dict_sup = {}
    for i in D:
        for j in Ck:
            if j.issubset(i):
                if not j in dict_sup:
                    dict_sup[j] = 1
                else:
                    dict_sup[j] += 1
    sumCount = float(len(D))
    supportData = {}
    relist = []
    for i in dict_sup:
        temp_sup = dict_sup[i] / sumCount
        if temp_sup >= min_support:
            relist.append(i)
            supportData[i] = temp_sup  # 此處可設置返回全部的支持度數據(或者頻繁項集的支持度數據)
    return relist, supportData
 
 
# 改進剪枝算法
def aprioriGen(Lk, k):  # 創建候選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:  # 前k-1項相等,則可相乘,這樣可防止重復項出現
                #  進行剪枝(a1為k項集中的一個元素,b為它的所有k-1項子集)
                a = Lk[i] | Lk[j]  # a為frozenset()集合
                a1 = list(a)
                b = []
                # 遍歷取出每一個元素,轉換為set,依次從a1中剔除該元素,並加入到b中
                for q in range(len(a1)):
                    t = [a1[q]]
                    tt = frozenset(set(a1) - set(t))
                    b.append(tt)
                t = 0
                for w in b:
                    # 當b(即所有k-1項子集)都是Lk(頻繁的)的子集,則保留,否則刪除。
                    if w in Lk:
                        t += 1
                if t == len(b):
                    retList.append(b[0] | b[1])
    return retList
 
 
def apriori(dataSet, minSupport=0.2):
    C1 = createC1(dataSet)
    D = list(map(set, dataSet))  # 使用list()轉換為列表
    L1, supportData = calSupport(D, C1, minSupport)
    L = [L1]  # 加列表框,使得1項集為一個單獨元素
    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)  # L最后一個值為空集
        k += 1
    del L[-1]  # 刪除最后一個空集
    return L, supportData  # L為頻繁項集,為一個列表,1,2,3項集分別為一個元素。
 
 
# 生成集合的所有子集
def getSubset(fromList, toList):
    for i in range(len(fromList)):
        t = [fromList[i]]
        tt = frozenset(set(fromList) - set(t))
        if not tt in toList:
            toList.append(tt)
            tt = list(tt)
            if len(tt) > 1:
                getSubset(tt, toList)
 
 
def calcConf(freqSet, H, supportData, ruleList, minConf=0.7):
    for conseq in H:
        conf = supportData[freqSet] / supportData[freqSet - conseq]  # 計算置信度
        # 提升度lift計算lift = p(a & b) / p(a)*p(b)
        lift = supportData[freqSet] / (supportData[conseq] * supportData[freqSet - conseq])
 
        if conf >= minConf and lift > 1:
            print(freqSet - conseq, '-->', conseq, '支持度', round(supportData[freqSet - conseq], 2), '置信度:', conf,
                  'lift值為:', round(lift, 2))
            ruleList.append((freqSet - conseq, conseq, conf))
 
# 生成規則
def gen_rule(L, supportData, minConf=0.7):
    bigRuleList = []
    for i in range(1, len(L)):  # 從二項集開始計算
        for freqSet in L[i]:  # freqSet為所有的k項集
            # 求該三項集的所有非空子集,1項集,2項集,直到k-1項集,用H1表示,為list類型,里面為frozenset類型,
            H1 = list(freqSet)
            all_subset = []
            getSubset(H1, all_subset)  # 生成所有的子集
            calcConf(freqSet, all_subset, supportData, bigRuleList, minConf)
    return bigRuleList
 
 
if __name__ == '__main__':
    dataSet = loadDataSet()
    L, supportData = apriori(dataSet, minSupport=0.2)
    rule = gen_rule(L, supportData, minConf=0.7)

運行結果:

目錄:

1.關聯分析

2. Apriori 原理

3. 使用 Apriori 算法來發現頻繁集

4.從頻繁集中挖掘關聯規則

5. 總結

 

1.關聯分析  返回目錄

關聯分析是一種在大規模數據集中尋找有趣關系的任務。這種關系表現為兩種形式:

1.頻繁項集(frequency item sets):經常同時出現的一些元素的集合;

2.關聯規則(association rules): 意味着兩種元素之間存在很強的關系。

下面舉例來說明上面的兩個概念:

表1 一個來自Hole Foods天食品店的簡單交易清單
交易號碼 商品
0 豆奶, 萵苣
1 萵苣,尿布,葡萄酒,甜菜
2 萵苣,尿布,葡萄酒,橙汁
3 萵苣,豆奶,尿布,葡萄酒
4 萵苣,豆奶,尿布,橙汁

 

頻繁項集是指經常出現在一起的元素的集合,上表中的集合 {葡萄酒,尿布,豆奶} 就是頻繁項集的一個例子。同樣可以找到如 “尿布 --> 葡萄酒”的關聯規則,意味着如果有人買了尿布,就很可能也會買葡萄酒。使用頻繁項集和關聯規則,商家可以更好地理解顧客的消費行為,所以大部分關聯規則分析示例來自零售業。

理解關聯分析首先需要搞清楚下面三個問題:

1.如何定義這些有用的關系?

2.這些關系的強弱程度又是如何定義?

3.頻繁的定義是什么?

要回答上面的問題,最重要的是理解兩個概念:支持度和可信度。

支持度:一個項集的支持度(support)被定義為數據集中包含該項集的記錄占總記錄的比例。從表1 可以看出 項集 {豆奶} 的支持度為 4/54/5; 而在 5 條交易記錄中 3 條包含 {豆奶,尿布},因此 {豆奶,尿布} 的支持度為 3/53/5.

可信度或置信度(confidence):是針對一條諸如尿>尿布−−>葡萄酒的關聯規則來定義的,這條規則的可信度被定義為“ 支持度({尿布,葡萄酒})  /  支持度({尿布})”。在表1 中可以發現  {尿布,葡萄酒} 的支持度是 3/53/5, {尿布} 的支持度為 4/54/5, 所以關聯規則 “尿布 --> 葡萄酒”的可信度為 3/4=0.753/4=0.75, 意思是對於所有包含 "尿布"的記錄中,該關聯規則對其中的 75% 記錄都適用。

2. Apriori 原理 返回目錄

假設經營了一家雜貨店,於是我們對那些經常在一起購買的商品非常感興趣。假設我們只有 4 種商品:商品0,商品1,商品 2,商品3. 那么如何得可能被一起購買的商品的組合?

上圖顯示了物品之間所有可能的組合,從上往下一個集合是 ØØ,表示不包含任何物品的空集,物品集合之間的連線表明兩個或者更多集合可以組合形成一個更大的集合。

  我們的目標是找到經常在一起購買的物品集合。這里使用集合的支持度來度量其出現的頻率。一個集合出現的支持度是指有多少比例的交易記錄包含該集合。例如,對於上圖,要計算 0,30,3 的支持度,直接的想法是遍歷每條記錄,統計包含有 00 和 33 的記錄的數量,使用該數量除以總記錄數,就可以得到支持度。而這只是針對單個集合 0,30,3. 要獲得每種可能集合的支持度就需要多次重復上述過程。對於上圖,雖然僅有4中物品,也需要遍歷數據15次。隨着物品數目的增加,遍歷次數會急劇增加,對於包含 NN 種物品的數據集共有 2N12N−1 種項集組合。所以即使只出售 100100  種商品的商店也會有 1.26×10301.26×1030 中可能的組合。計算量太大。

  為了降低計算時間,研究人員發現了 AprioriApriori 原理,可以幫我們減少感興趣的頻繁項集的數目。

AprioriApriori 的原理:如果某個項集是頻繁項集,那么它所有的子集也是頻繁的。

即如果 {0,1} 是頻繁的,那么 {0}, {1} 也一定是頻繁的。

這個原理直觀上沒有什么用,但是反過來看就有用了,也就是說如果一個項集是非頻繁的,那么它的所有超集也是非頻繁的。如下圖所示:

 

3. 使用 Apriori 算法來發現頻繁集 返回目錄

上面提到,關聯分析的兩個目標:發現頻繁項集和發現關聯規則。首先需要找到頻繁項集,然后根據頻繁項集獲得關聯規則。首先來討論發現頻繁項集。Apriori 是發現頻繁項集的一種方法。

首先會生成所有單個物品的項集列表;

掃描交易記錄來查看哪些項集滿足最小支持度要求,那些不滿足最小支持度的集合會被去掉;

對剩下的集合進行組合以生成包含兩個元素的項集;

接下來重新掃描交易記錄,去掉不滿足最小支持度的項集,重復進行直到所有項集都被去掉。

數據集掃描的偽代碼:

對數據集中的每條交易記錄tran:

  對每個候選項集can:

    檢查一下can是否是tran的子集:

      如果是,則增加can的計數值

對每個候選項集:

  如果其支持度不低於最低值,則保留

返回所有頻繁項集列表


免責聲明!

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



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