数据挖掘之Apriori算法

来源:互联网 发布:淘宝网退货运费怎么算 编辑:程序博客网 时间:2024/05/22 11:33

本文实现数据挖掘中关联规则的挖掘。关联规则挖掘一般针对交易数据库,挖掘每次交易中用户购买的项(即购买的物品)之间的关联关系。最常用的度量方式有:置信度,支持度,兴趣度,期望可达度等等。

假设交易数据库为D={T1,T2,T3,.......,Tn},购买的物品的项集为I={I1,I2,I3,.......,In}。假设X为某次交易Ti购买的项,Y为每次交易Tj购买的项。置信度: X-->Y = P(X|Y)=P(X,Y)/P(X),置信度实际上反应了一个可信度的度量,即由X推出Y的可信度,在计算上本质是一个条件概率。支持度:Support(X-->Y) = Num(X,Y)/Num(D),即(X,Y)同时发生的频率,本质上反应了关联规则X-->Y的重要程度。期望可达度P(Y)=Num(Y)/Num(X),即Y本身的频率统计。兴趣度:(置信度-支持度)/Max(置信度,支持度),一条规则的兴趣度大于0,实际利用价值越大。

若一条规则满足最小支持度以及最小置信度,则称这条规则为强关联规则。

Apriori利用最小支持度,统计频繁项集。频繁一项:即每个项在整个交易数据库中出现的次数(每个一项的次数需要满足最小支持度)。频繁二项:先由频繁一项的物品,排列组合得到二项组合,再根据最小支持度,得到频繁二项集。频繁三项:由频繁二项组合得到.......知道某一项的频繁项集为空。得到各频繁项集,相应就得到了关联规则。具体来说:频繁一项-->频繁二项-->频繁三项-->频繁四项-->........

Apriori会出现组合爆炸,搜索时间可能会较长,也和数据量有关。本文的数据集是关联规则分析经典数据集Groceries数据,有9896条交易数据。

运行结果如下图所示:


本文最小支持度设置为3,到了频繁四项为空,算法结束。频繁三项的搜索时间大概20分钟左右,最小支持度设置的越小,所花费的时间越长。

源代码如下:

# !/usr/bin/env python# -*- coding:utf-8 -*- # Author: wsw# 数据挖掘中关联规则Apriori算法import pandas as pdimport reimport timeimport numpy as npdef main():datapath = '../Groceries.csv'rowdata = pd.read_csv(datapath)# 数据集中的项集itemSets = rowdata.loc[:, 'items']# 得到交易个数Num = itemSets.shape[0]# 定义最小支持度为4minSupport = 3# 正则模式# 匹配2个字符中间的内容,注意括号里面是要匹配的内容,'{'或者','开头,','或者'}'结尾pattern = re.compile('[{,](.*)?[,}]')# 得到频繁一项统计freqOne, time1 = countFreqOneItem(itemSets, pattern, minSupport)print('频繁一项统计结果:')print(freqOne)print('频繁一项搜索时间:(S)', time1)freqTwo, time2 = countFreqTwo(itemSets, freqOne, minSupport)print('频繁二项统计结果:')print(freqTwo)print('频繁二项搜索时间:(S)', time2)freqThree, time3 = countFreqThree(itemSets, freqTwo, minSupport)print('频繁三项统计结果:')print(freqThree)print('频繁三项搜索时间:(S)', time3)freqFour, time4 = countFreqFour(itemSets, freqTwo, minSupport)print('频繁四项统计结果:')print(freqFour)print('频繁四项搜索时间:(S)', time4)pass# 统计数据集中的频繁一项def countFreqOneItem(itemset, pattern, minSupport):# 支持度度量统计start = time.time()countSupport = {}for itemTransction in itemset:# 拆分每次交易中,单个物品res = re.findall(pattern, itemTransction)items = res[0].split(',')for item in items:if item in countSupport.keys():countSupport[item] += 1else:countSupport[item] = 0# 频繁一项freqOne = {}for key, value in countSupport.items():if value >= minSupport:freqOne[key] = valueend = time.time()time1 = end - startreturn freqOne, time1pass# 统计项集中的频繁二项def countFreqTwo(itemset, freqOne, minSupport):# 二项集列表start = time.time()twoItemsList = []itemNames = list(freqOne.keys())num = len(itemNames)for i in range(num - 1):for j in range(i + 1, num):twoItemsList.append(','.join([itemNames[i], itemNames[j]]))# 得到二项集的支持度统计countSupport = {}for item in twoItemsList:countSupport[item] = 0for itemcollection in itemset:if item in itemcollection:countSupport[item] += 1# 得到频繁二项集freqTwo = {}for key, value in countSupport.items():if value >= minSupport:freqTwo[key] = valueend = time.time()time2 = end - startreturn freqTwo, time2pass# 统计频繁三项def countFreqThree(itemset, freqTwo, minSupport):# 三项集列表start = time.time()ThreeItmeList = []twoItemNames = list(freqTwo.keys())num = len(twoItemNames)for i in range(num-1):for j in range(i+1, num):# 拆分得到当前的物品名称currentItem = twoItemNames[i].split(',')# 拆分得到下一个二项集物品的名称nextItem = twoItemNames[j].split(',')# 融合得到三项集for item in nextItem:tempCurrent = currentItem[:]tempCurrent.append(item)threeItem = set(tempCurrent)if len(threeItem) == 3:# 将集合转成列表进行处理threeItem = list(threeItem)threeItem = ','.join(threeItem)ThreeItmeList.append(threeItem)# 得到三项集的支持度度量countSupport = {}for threeitem in ThreeItmeList:countSupport[threeitem] = 0for itemcollection in itemset:if threeitem in itemcollection:countSupport[threeitem] += 1# 统计频繁三项集freqThree = {}for key, value in countSupport.items():if value >= minSupport:freqThree[key] = valueend = time.time()time3 = end - startreturn freqThree, time3pass# 统计频繁四项的个数def countFreqFour(itemset, freqThree, minSupport):# 四项集列表start = time.time()fourItmeList = []threeItemNames = list(freqThree.keys())num = len(threeItemNames)for i in range(num-1):for j in range(i+1, num):# 拆分得到当前的物品名称currentItem = threeItemNames[i].split(',')# 拆分得到下一个三项集物品的名称nextItem = threeItemNames[j].split(',')# 融合得到四项集for item in nextItem:tempCurrent = currentItem[:]tempCurrent.append(item)fourItem = set(tempCurrent)if len(fourItem) == 4:# 将集合转成列表进行处理fourItem = list(fourItem)fourItem = ','.join(fourItem)fourItmeList.append(fourItem)# 得到四项集的支持度度量countSupport = {}for fouritem in fourItmeList:countSupport[fouritem] = 0for itemcollection in itemset:if fouritem in itemcollection:countSupport[fouritem] += 1# 统计频繁四项集freqFour = {}for key, value in countSupport.items():if value >= minSupport:freqFour[key] = valueend = time.time()time4 = end - startreturn freqFour, time4passif __name__ == '__main__':main()pass


原创粉丝点击