web数据挖掘学习笔记-Apriori(二)MS-Apriori-python实现

上一部分,我们讨论了apriori是如何减少子项集频繁度搜寻的。并且介绍了规则生成过程。
传送:https://blog.csdn.net/montecarlostyle/article/details/79850029

新问题提出

在类似商品关联挖掘的应用中,可能会遇到一个问题:那些具有较低支持度但是价值较高(高利润)的项目集不会生成。由于它们的支持度太低,在普通apriori算法迭代的过程中被抛弃了。例如,{食品加工机, 平底锅}是一个有意义的项目集,它的支持度=0.006%.如果我们把最小支持度调低为0.005%,我们可以利用apriori算法得到这个频繁项集,但同时会得到更多的无意义的频繁项目集。
由于商品之间的性质不同,有的商品是利润高的耐用品,有的是廉价的消耗品。耐用品购买的频率较少,但是利润普遍较高。对于这种情况,我们对它们使用统一的最小支持度就太不公平了。
思考
**以上问题的产生是因为我们对不同类型的商品使用了相同的支持度。**我们可以对每个项目(商品)都指定一个最小支持度(Minimum Item Support, MIS)。那么,一条规则R的最小支持度就是R中所有项目中最低的MIS值。我们称一条规则
i 1 , i 2 , . . . , i k − > i k + 1 , . . . , i r i_1, i_2, ..., i_k -> i_{k+1}, ..., i_r i1,i2,...,ik>ik+1,...,ir
满足它的最小支持度,如果这条规则在数据集中的真实支持度大于或等于它们中的最小MIS值 m i n ( M I S ( i 1 ) , M I S ( i 2 ) , . . . , M I S ( i r ) ) min(MIS(i_1), MIS(i_2), ..., MIS(i_r)) min(MIS(i1),MIS(i2),...,MIS(ir))。这样,包含稀有项目的规则,其最小支持度很小,同时,频繁项目规则的最小支持度很大。
给每个项目设定MIS产生的问题——向下封闭性失效
下面我们用一个例子探讨这个方法有什么副作用。设一个数据集中有4个项目1, 2, 3, 4.它们的最小项目支持度分别为:
MIS(1)=10% MIS(2)=20% MIS(3)=5% MIS(4)=6%
假设{1, 2, 3}和{1, 2, 4}是我们要的频繁项(它们的最小支持度很低)。算法在第二轮搜索后得到项集{1, 2},支持度为9%,不满足项目1和2的最小支持度(10%)。按原则,它将要被丢弃。问题来了…把它丢弃之后,第三轮就不会生成{1, 2, 3}和{1, 2, 4}(为什么?回忆一下向下封闭性,通过其他方式生成{1, 2, 3}之后,它的子集{1, 2}不是频繁项集,立马又被剪掉了)。这样可能有点遭…向下封闭性失效了。难道要放弃剪枝,回归穷举法么?
补救——设置新的剪枝规则
我们先分析一下问题,刚才的例子中,{1, 2, 3}的最小支持度小于{1, 2}的最小支持度。因为加了个MIS比较低的3进来,{1, 2, 3}就可以是频繁项。我是不是频繁项集,你{1, 2}说了不算,关键看{2, 3},{1, 3}。下面有个解决思路:记下给频繁项{1, 2, 3}贡献最低支持度的那个元素3,剪枝过程中,只要3参与的子集有一个不是频繁项集,那{1, 2, 3}肯定也不是频繁项集。如果3参与的都是呢?那就留着这个候选项,一会儿送到全事件集里搜寻,看{1, 2, 3}的真实支持度是否真的大于3的MIS。
在实际操作中,每次都要寻找项集里的最小MIS项太麻烦了,则开始就按照MIS大小做个排序。以后项集的最小支持度就等于项集中第一个元素的MIS,多方便。另外,防止过小MIS的项目与大MIS项目相组合(假设90%的客人都要买口香糖,那就不能设定出一个规则:买了一台挖掘机的人通常也会买一个口香糖。),我们接着设置一个阈值φ,如果两个项集的最小支持度差别大于这个阈值,就不能进行合集操作。
——————————————————————————————————————————

Python实现

需要的数据有两种。transaction.txt存放购买记录,ms.txt说明每种商品的MIS值。

Beef,Bread
Bread,Clothes
Beef,Bread,Milk
Cheese,Boots
Beef,Bread,Cheese,Shoes
Beef,Bread,Cheese,Milk
Bread,Milk,Clothes


Milk:0.5
Bread:0.7
Clothes:0.25
Beef:0.25
Cheese:0.25
Boots:0.25
Shoes:0.25


数据文件要和代码放在同一目录。
结果如下图

Python代码

#----------------------------------------------------- 
#   function:MS-Apriori 
#   author:hanshuo	 
#   date:2018-4-07
#   tools:Python 2.7.6  
#   system:linux or Windows
#-----------------------------------------------------
import copy

def msApriori(tFileName = 'transaction.txt', msFileName = 'ms.txt', phi = 1):
	T = transactionGet(tFileName)
	MS = msGet(msFileName)
	msListSorted = sorted(MS.items(), key = lambda x:x[1])
	goodList = [i[0] for i in msListSorted]
	n = len(T)
	l = supCount(goodList, T)
	L = []

	for values in l:
		if values[-1] >= msListSorted[0][-1]:
			L.append(values)

	itemSup = dict(L)

	f1 = []
	for items in L:
		if items[1] >= MS[items[0]]:
			f1.append(items)

	print f1
	c2 = leve2CandidateGen(L, MS, phi, n)
	f2 = supCount(c2, T)
	F = []

	for eachIssue in f2:
		if eachIssue[-1] >= MS[(eachIssue[0][0],)]:
			F.append(eachIssue)
	print F

	f = f2
	while True:
		F = []
		c = msCandidateGen(f, phi, itemSup, MS)
		f = supCount(c, T)
		for eachIssue in f:
			if eachIssue[-1] >= MS[(eachIssue[0][0],)]:
				F.append(eachIssue)
		
		if F == []:
			break
		print F

def supCount(nonCountList, transactionList):
	countList = []
	n = float(len(transactionList))

	for values in nonCountList:
		count = 0

		for issue in transactionList:
			if set(values).issubset(set(issue)):
				count += 1
		countList.append((values, count/n))

	return countList

def msGet(fileName = 'ms.txt'):
	f = open(fileName)
	msList = []

	for line in f.readlines():
		lineTuple = ((line.strip().split(':')[0],), eval(line.strip().split(':')[1]))
		msList.append(lineTuple)

	return dict(msList)

def transactionGet(fileName = 'transaction.txt'):
	f = open(fileName)
	transactionList = []

	for line in f.readlines():
		lineTuple = line.strip().split(',')
		transactionList.append(lineTuple)

	return transactionList

def leve2CandidateGen(L, ms, phi, n):
	c2 = []

	for i in range(len(L)):
		if L[i][1] >= ms[L[i][0]]:
			for values in L[i+1:]:
				if (values[1] >= ms[L[i][0]]) & ((abs(L[i][1] - values[1])) <= phi):
					c2.append((L[i][0][0], values[0][0]))
	
	return c2

def msCandidateGen(f, phi, itemSup, ms):
	c = []

	for i in range(len(f)):
		for value in f[i+1:]:
			temp = list(copy.copy(f[i][0]))
			if (abs(itemSup[(f[i][0][-1],)] - itemSup[(value[0][-1],)]) <= phi) & (f[i][0][:-1] == value[0][:-1]):
				temp.append(value[0][-1])
				c.append(tuple(temp))		

	for issue in c:
		for item in issue:
			issueCarbon = list(copy.copy(issue))
			issueCarbon.remove(item)
			if (item in issue) | (ms[(issue[1],)] == ms[(issue[0],)]):
				if tuple(issueCarbon) not in [item[0] for item in f]:
					c.remove(issue)
					break

	return c
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值