用java实现Apriori算法

20 篇文章 0 订阅
18 篇文章 0 订阅

首先大家了解一下Apriori算法,如下:

Apriori算法 是一种最有影响的挖掘布尔关联规则频繁项集的算法。其核心是基于两阶段频集思想的递推算法。该关联规则在分类上属于单维、单层、布尔关联规则。在这里,所有支持度大于最小支持度的项集称为频繁项集,简称频集。

该算法的基本思想 是:首先找出所有的频集,这些项集出现的频繁性至少和预定义的最小支持度一样。然后由频集产生强关联规则,这些规则必须满足最小支持度和最小可信度。然后使用第1步找到的频集产生期望的规则,产生只包含集合的项的所有规则,其中每一条规则的右部只有一项,这里采用的是中规则的定义。一旦这些规则被生成,那么只有那些大于用户给定的最小可信度的规则才被留下来。为了生成所有频集,使用了递归的方法。

我们来看一下该算法的python实现,如下:

#创建基础字典
def createC1(dataSet):
    C1 = []
    for transaction in dataSet:
        for item in transaction:
            if not [item] in C1:
                C1.append([item])
                
    C1.sort()
    return map(frozenset, C1)#use frozen set so we
                            #can use it as a key in a dict    

#计算数据集在字典中的数据且满足最低支持度要求比例
def scanD(D, Ck, minSupport):
    ssCnt = {}
    for tid in D:
        for can in Ck:
            if can.issubset(tid):
                if not ssCnt.has_key(can): 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 aprioriGen(Lk, k): #creates Ck
    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: #if first k-2 elements are equal
                retList.append(Lk[i] | Lk[j]) #set union
    return retList

#算法核心
def apriori(dataSet, minSupport = 0.5):
    C1 = createC1(dataSet)
    D = map(set, dataSet)
    L1, supportData = scanD(D, C1, minSupport)
    L = [L1]
    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)
        k += 1
    return L, supportData

我们开始用java实现,如下:

首先是创建基础字典

private static List<List<String>> createC1(List<List<String>> dataSet){
		List<String> C1 = new ArrayList<String>();
		
		for(int i=0;i<dataSet.size();i++) {
			for(String item : dataSet.get(i)) {
				if(!C1.contains(item)) {
					C1.add(item);
				}
			}
		}
		
        Collections.sort(C1);  
        
        List<List<String>> rs = new ArrayList<List<String>>();
        
        for(String item : C1) {
        	List<String> tmp = new ArrayList<String>();
        		tmp.add(item);
        	rs.add(tmp);
        }
        
        return rs;
		
	}

然后是计算数据集在字典中的数据且满足最低支持度要求比例

private static ScanInfo scanD(List<List<String>> D,List<List<String>> Ck,double minSupport){
		
		Map<List<String>,Integer> ssCnt = new HashMap<List<String>,Integer>();
		
		for(List<String> tid : D) {
			
			for(List<String> can : Ck) {
				
				if(tid.containsAll(can)) {
					if(ssCnt.containsKey(can)) {
						ssCnt.replace(can, ssCnt.get(can)+1);
					}else {
						ssCnt.put(can, 1);
					}
				}
			}
		}
		
		
		List<List<String>> retList = new ArrayList<List<String>>();
		Map<List<String>,Double> supportData = new HashMap<List<String>,Double>();
		
		for (Map.Entry<List<String>,Integer> entry : ssCnt.entrySet()) { 
			double support = (double)entry.getValue()/(double)D.size();
			if(support >= minSupport) {
				retList.add(entry.getKey());
			}
			supportData.put(entry.getKey(), support);
		}
		
		
		return new ScanInfo(retList,supportData);
		
	}

然后根据字典组装新的字典

private static List<List<String>> aprioriGen(List<List<String>> Lk,int k){
		List<List<String>> retList = new ArrayList<List<String>>();

		for(int i=0;i<Lk.size();i++) {
			for(int j=i+1;j<Lk.size();j++) {
				
				List<String> L1 = new ArrayList<String>();
				List<String> L2 = new ArrayList<String>();
				
				if(Lk.get(i).size() > 1) {
					for(int n=0;n<(Lk.get(i).size()-k+2);n++) {
						L1.add(Lk.get(i).get(n));
					}
				}
				
				if(Lk.get(j).size() > 1) {
					for(int n=0;n<(Lk.get(j).size()-k+2);n++) {
						L2.add(Lk.get(j).get(n));
					}
				}
				
				Collections.sort(L1);  
				Collections.sort(L2);  
				
				if((L1.containsAll(L2) && L2.containsAll(L1)) || (L1.size() ==0 && L2.size() ==0)) {
					List<String> tmp = new ArrayList<String>();
					tmp.addAll(Lk.get(i));
					tmp.addAll(Lk.get(j));
					retList.add(removeDuplicate(tmp));
				}
			}
		}
		 

		 return retList;
	}

最后是Apriori的主体,循环推算各层满足最低支持度的集合

public static List<List<List<String>>> apriori(List<List<String>> dataSet,double minSupport) {
		List<List<String>>  C1 = createC1(dataSet);
		ScanInfo si = scanD(dataSet, C1, minSupport);
		List<List<List<String>>> L = new ArrayList<List<List<String>>>();
		L.add(si.getRetList());
		int k = 2;
		while(L.get(k-2).size() > 0) {
			List<List<String>> Ck = aprioriGen(L.get(k-2), k);
			ScanInfo tmp = scanD(dataSet, Ck, minSupport);
	        L.add(tmp.getRetList());
	        k += 1;
		}
        return L;
	}

我们开始测试

List<String[]> datas = new ArrayList<String[]>();
		
			datas.add(new String[]{"1","3","4"});
			datas.add(new String[]{"2","3","5"});
			datas.add(new String[]{"1","2","3","5"});
			datas.add(new String[]{"2","5"});
		
		List<List<String>> dataIns = new ArrayList<List<String>>();	
		
		for(String[] item : datas) {
			dataIns.add(Arrays.asList(item));
		}
		
		List<List<List<String>>> tmp =  apriori(dataIns,0.5);
		
		System.out.println(tmp.toString());

结果正确如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路边草随风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值