Apriori、FP-Growth及Eclat算法

注:本文轉載自yangliuy http://blog.csdn.net/yangliuy/article/details/7494983 數據挖掘-關聯分析頻繁模式挖掘Apriori、FP-Growth及Eclat算法的JAVA及C++實現

一、Apriori算法

       Apriori是非常經典的關聯分析頻繁模式挖掘算法,其思想簡明,實現方便,只是效率很低,可以作爲頻繁模式挖掘的入門算法。其主要特點是

       1、k-1項集連接規律:若有兩個k-1項集,每個項集保證有序,如果兩個k-1項集的前k-2個項相同,而最後一個項不同,則證明它們是可連接的,可連接生成k項集。
       2、反單調性。如果一個項集是頻繁的,那麼它的所有子集都是頻繁的。即若一個項集的子集不是頻繁項集,則該項集肯定也不是頻繁項集。
       主要算法流程:
      1. 掃描數據庫,生成候選1項集和頻繁1項集。
      2. 從2項集開始循環,由頻繁k-1項集生成頻繁頻繁k項集。
      2.1  頻繁k-1項集兩兩組合,判定是否可以連接,若能則連接生成k項集。
      2.2  對k項集中的每個項集檢測其子集是否頻繁,捨棄掉子集不是頻繁項集即   不在頻繁k-1項集中的項集。
      2.3  掃描數據庫,計算2.3步中過濾後的k項集的支持度,捨棄掉支持度小於閾值的項集,生成頻繁k項集。
      3.  若當前k項集中只有一個項集時循環結束。

      僞代碼如下:


 JAVA實現代碼

package com.pku.yangliu;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

/**頻繁模式挖掘算法Apriori實現
 *
 */

public class AprioriFPMining {
	private int minSup;//最小支持度
	private static List<Set<String>> dataTrans;//以List<Set<String>>格式保存的事物數據庫,利用Set的有序性
	
	public int getMinSup() {
		return minSup;
	}
	
	public void setMinSup(int minSup) {
		this.minSup = minSup;
	}
	
	/**
	 * @param args
	 */
	 public static void main(String[] args) throws IOException { 
		AprioriFPMining apriori = new AprioriFPMining();
		double [] threshold = {0.25, 0.20, 0.15, 0.10, 0.05};
		String srcFile = "F:/DataMiningSample/FPmining/Mushroom.dat";
		String shortFileName = srcFile.split("/")[3];
        String targetFile = "F:/DataMiningSample/FPmining/" + shortFileName.substring(0, shortFileName.indexOf("."))+"_fp_threshold";
		dataTrans = apriori.readTrans(srcFile);
		for(int k = 0; k < threshold.length; k++){
			System.out.println(srcFile + " threshold: " + threshold[k]);
			long totalItem = 0;
			long totalTime = 0;
			FileWriter tgFileWriter = new FileWriter(targetFile + (threshold[k]*100));
			apriori.setMinSup((int)(dataTrans.size() * threshold[k]));//原始蘑菇的數據0.25只需要67秒跑出結果
			long startTime = System.currentTimeMillis();
			Map<String, Integer> f1Set = apriori.findFP1Items(dataTrans);
			long endTime = System.currentTimeMillis();
			totalTime += endTime - startTime;
			//頻繁1項集信息得加入支持度
			Map<Set<String>, Integer> f1Map = new HashMap<Set<String>, Integer>();
			for(Map.Entry<String, Integer> f1Item : f1Set.entrySet()){
				Set<String> fs = new HashSet<String>();
				fs.add(f1Item.getKey());
				f1Map.put(fs, f1Item.getValue());
			}
			
			totalItem += apriori.printMap(f1Map, tgFileWriter);
			Map<Set<String>, Integer> result = f1Map;
			do {	
				startTime = System.currentTimeMillis();
				result = apriori.genNextKItem(result);
				endTime = System.currentTimeMillis();
				totalTime += endTime - startTime;
				totalItem += apriori.printMap(result, tgFileWriter);
			} while(result.size() != 0);
			tgFileWriter.close();
			System.out.println("共用時:" + totalTime + "ms");
			System.out.println("共有" + totalItem + "項頻繁模式");
		}
	}

	 /**由頻繁K-1項集生成頻繁K項集
	 * @param preMap 保存頻繁K項集的map
	 * @param tgFileWriter 輸出文件句柄
	 * @return int 頻繁i項集的數目
	 * @throws IOException 
	 */
	private Map<Set<String>, Integer> genNextKItem(Map<Set<String>, Integer> preMap) {
		// TODO Auto-generated method stub
		Map<Set<String>, Integer> result = new HashMap<Set<String>, Integer>();
		//遍歷兩個k-1項集生成k項集
		List<Set<String>> preSetArray = new ArrayList<Set<String>>();
		for(Map.Entry<Set<String>, Integer> preMapItem : preMap.entrySet()){
			preSetArray.add(preMapItem.getKey());
		}
		int preSetLength = preSetArray.size();
		for (int i = 0; i < preSetLength - 1; i++) {
			for (int j = i + 1; j < preSetLength; j++) {
				String[] strA1 = preSetArray.get(i).toArray(new String[0]);
				String[] strA2 = preSetArray.get(j).toArray(new String[0]);
				if (isCanLink(strA1, strA2)) { // 判斷兩個k-1項集是否符合連接成k項集的條件 
					Set<String> set = new TreeSet<String>();
					for (String str : strA1) {
						set.add(str);
					}
					set.add((String) strA2[strA2.length - 1]); // 連接成k項集
					// 判斷k項集是否需要剪切掉,如果不需要被cut掉,則加入到k項集列表中
					if (!isNeedCut(preMap, set)) {//由於單調性,必須保證k項集的所有k-1項子集都在preMap中出現,否則就該剪切該k項集
						result.put(set, 0);
					}
				}
			}
		}
		return assertFP(result);//遍歷事物數據庫,求支持度,確保爲頻繁項集
	}
	
	/**檢測k項集是否該剪切。由於單調性,必須保證k項集的所有k-1項子集都在preMap中出現,否則就該剪切該k項集
	 * @param preMap k-1項頻繁集map
	 * @param set 待檢測的k項集
	 * @return boolean 是否該剪切
	 * @throws IOException 
	 */
	private boolean isNeedCut(Map<Set<String>, Integer> preMap, Set<String> set) {
		// TODO Auto-generated method stub
		boolean flag = false;
		List<Set<String>> subSets = getSubSets(set);
		for(Set<String> subSet : subSets){
			if(!preMap.containsKey(subSet)){
				flag = true;
				break;
			}
		}
		return flag;
	}

	/**獲取k項集set的所有k-1項子集
	 * @param set 頻繁k項集
	 * @return List<Set<String>> 所有k-1項子集容器
	 * @throws IOException 
	 */
	private List<Set<String>> getSubSets(Set<String> set) {
		// TODO Auto-generated method stub
		String[] setArray = set.toArray(new String[0]);
		List<Set<String>> result = new ArrayList<Set<String>>();
		for(int i = 0; i < setArray.length; i++){
			Set<String> subSet = new HashSet<String>();
			for(int j = 0; j < setArray.length; j++){
				if(j != i) subSet.add(setArray[j]);
			}
			result.add(subSet);
		}
		return result;
	}

	/**遍歷事物數據庫,求支持度,確保爲頻繁項集
	 * @param allKItem 候選頻繁k項集
	 * @return Map<Set<String>, Integer> 支持度大於閾值的頻繁項集和支持度map
	 * @throws IOException 
	 */
	private Map<Set<String>, Integer> assertFP(
			Map<Set<String>, Integer> allKItem) {
		// TODO Auto-generated method stub
		Map<Set<String>, Integer> result = new HashMap<Set<String>, Integer>();
		for(Set<String> kItem : allKItem.keySet()){
			for(Set<String> data : dataTrans){
				boolean flag = true;
				for(String str : kItem){
					if(!data.contains(str)){
						flag = false;
						break;
					}
				}
				if(flag) allKItem.put(kItem, allKItem.get(kItem) + 1);
			}
			if(allKItem.get(kItem) >= minSup) {
				result.put(kItem, allKItem.get(kItem));
			}
		}
		return result;
	}

	/**檢測兩個頻繁K項集是否可以連接,連接條件是隻有最後一個項不同
	 * @param strA1 k項集1
	 * @param strA1 k項集2
	 * @return boolean 是否可以連接
	 * @throws IOException 
	 */
	private boolean isCanLink(String[] strA1, String[] strA2) {
		// TODO Auto-generated method stub
		boolean flag = true;
		if(strA1.length != strA2.length){
			return false;
		}else {
			for(int i = 0; i < strA1.length - 1; i++){
				if(!strA1[i].equals(strA2[i])){
					flag = false;
					break;
				}
			}
			if(strA1[strA1.length -1].equals(strA2[strA1.length -1])){
				flag = false;
			}
		}
		return flag;
	}

	/**將頻繁i項集的內容及支持度輸出到文件 格式爲 模式:支持度
	 * @param f1Map 保存頻繁i項集的容器<i項集 , 支持度>
	 * @param tgFileWriter 輸出文件句柄
	 * @return int 頻繁i項集的數目
	 * @throws IOException 
	 */
	private int printMap(Map<Set<String>, Integer> f1Map, FileWriter tgFileWriter) throws IOException {
		// TODO Auto-generated method stub
		for(Map.Entry<Set<String>, Integer> f1MapItem : f1Map.entrySet()){
			for(String p : f1MapItem.getKey()){
				tgFileWriter.append(p + " ");
			}
			tgFileWriter.append(": " + f1MapItem.getValue() + "\n");
		}
		tgFileWriter.flush();
		return f1Map.size();
	}
	
	/**生成頻繁1項集
	 * @param fileDir 事務文件目錄
	 * @return Map<String, Integer> 保存頻繁1項集的容器<1項集 , 支持度>
	 * @throws IOException 
	 */
	private Map<String, Integer> findFP1Items(List<Set<String>> dataTrans) {
		// TODO Auto-generated method stub
		Map<String, Integer> result = new HashMap<String, Integer>();
		Map<String, Integer> itemCount = new HashMap<String, Integer>();
		for(Set<String> ds : dataTrans){
			for(String d : ds){
				if(itemCount.containsKey(d)){
					itemCount.put(d, itemCount.get(d) + 1);
				} else {
					itemCount.put(d, 1);
				}
			}
		}
		
		for(Map.Entry<String, Integer> ic : itemCount.entrySet()){
			if(ic.getValue() >= minSup){
				result.put(ic.getKey(), ic.getValue());
			}
		}
		return result;
	}

	/**讀取事務數據庫
	 * @param fileDir 事務文件目錄
	 * @return List<String> 保存事務的容器
	 * @throws IOException 
	 */
	private List<Set<String>> readTrans(String fileDir) {
		// TODO Auto-generated method stub
		List<Set<String>> records = new ArrayList<Set<String>>(); 
        try { 
            FileReader fr = new FileReader(new File(fileDir)); 
            BufferedReader br = new BufferedReader(fr); 
       
            String line = null; 
            while ((line = br.readLine()) != null) { 
                if (line.trim() != "") { 
                    Set<String> record = new HashSet<String>(); 
                    String[] items = line.split(" "); 
                    for (String item : items) { 
                        record.add(item); 
                    } 
                    records.add(record); 
                } 
            } 
        } catch (IOException e) { 
            System.out.println("讀取事務文件失敗。"); 
            System.exit(-2); 
        } 
        return records; 
	}
}
 
硬件環境:Intel Core 2 Duo CPU T5750 2GHZ, 2G內存
實驗結果
F:/DataMiningSample/FPmining/Mushroom.dat threshold: 0.25
共用時:54015ms
共有5545項頻繁模式
F:/DataMiningSample/FPmining/Mushroom.dat threshold: 0.2
共用時:991610ms
共有53663項頻繁模式
F:/DataMiningSample/FPmining/Mushroom.dat threshold: 0.15
結論:對Mushroom.dat挖掘出來的頻繁模式及支持度、頻繁模式總數正確,但是算法速度很慢,對大數據量如T10I4D100K低閾值挖掘時間太長
解決辦法:改用C++寫FP-Growth算法做頻繁模式挖掘!

二、FP-Growth算法
       FP-Growth算法由數據挖掘界大牛Han Jiawei教授於SIGMOD 00‘大會提出,提出根據事物數據庫構建FP-Tree,然後基於FP-Tree生成頻繁模式集。主要算法流程如下
Step1 讀取數據庫,構造頻繁1項集及FP-tree

Step2 遍歷FP-tree的頭表,對於每個頻繁項x,累積項x的所有前綴路徑形成x的條件模式庫CPB


Step3 對CPB上每一條路徑的節點更新計數爲x的計數,根據CPB構造條件FP-tree
Step4 從條件FP-tree中找到所有長路徑,對該路徑上的節點找出所有組合方式,然後合併計數
Step5 將Step4中的頻繁項集與x合併,得到包含x的頻繁項集
Step2-5 循環,直到遍歷頭表中的所有項


由於時間關係,主要基於芬蘭教授Bart Goethals的開源代碼實現,源碼下載見點擊打開鏈接 ,文件結構及運行結果如下


Mushroom.dat,accidents.dat和T10I4D100K.dat三個數據集做頻繁模式挖掘的結果如下




三、Eclat算法
    Eclat算法加入了倒排的思想,加快頻繁集生成速度,其算法思想是 由頻繁k項集求交集,生成候選k+1項集 。對候選k+1項集做裁剪,生成頻繁k+1項集,再求交集生成候選k+2項集。如此迭代,直到項集歸一。
    算法過程:
1.一次掃描數據庫,獲得初始數據。包括頻繁1項集,數據庫包含的所有items,事務總數(行)transNum,最小支持度minsup=limitValue*trans。
2.二次掃描數據庫,獲得頻繁2項集。
3.按照Eclat算法,對頻繁2項集迭代求交集,做裁剪,直到項集歸一。
      JAVA實現如下
package com.pku.yhf;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

public class EclatRelease {

	private File file=new File("D:/mushroom.dat.txt");
	private float limitValue=0.25f;
	private int transNum=0;
	private ArrayList<HeadNode> array=new ArrayList<HeadNode>();
	private HashHeadNode[] hashTable;//存放臨時生成的頻繁項集,作爲重複查詢的備選集合
	public long newItemNum=0;
	
	private File tempFile=null;
	private BufferedWriter bw=null;
	
	public static long modSum=0;
	/**
	 * 第一遍掃描數據庫,確定Itemset,根據閾值計算出支持度數
	 */
	public void init()
	{
		Set itemSet=new TreeSet();
		MyMap<Integer,Integer> itemMap=new MyMap<Integer,Integer>();
		
		int itemNum=0;
		Set[][] a;
		try {
			FileInputStream fis=new FileInputStream(file);
			BufferedReader br=new BufferedReader(new InputStreamReader(fis));
			String str=null;
			
			//第一次掃描數據集合
			while((str=br.readLine()) != null)
			{
				transNum++;
				String[] line=str.split(" ");
				for(String item:line)
				{
					itemSet.add(Integer.parseInt(item));
					itemMap.add(Integer.parseInt((item)));
				}
			}
			br.close();
		//	System.out.println("itemMap lastKey:"+itemMap.lastKey());
		//	System.out.println("itemsize:"+itemSet.size());
		//	System.out.println("trans: "+transNum);
			//ItemSet.limitSupport=(int)Math.ceil(transNum*limitValue);//上取整
			ItemSet.limitSupport=(int)Math.floor(transNum*limitValue);//下取整
			ItemSet.ItemSize=(Integer)itemMap.lastKey();
			ItemSet.TransSize=transNum;
			hashTable=new HashHeadNode[ItemSet.ItemSize*3];//生成項集hash表
			for(int i=0;i<hashTable.length;i++)
			{
				hashTable[i]=new HashHeadNode();
			}
			
		//	System.out.println("limitSupport:"+ItemSet.limitSupport);
			
			
			tempFile=new File(file.getParent()+"/"+file.getName()+".dat");
			if(tempFile.exists())
			{
				tempFile.delete();
			}
			tempFile.createNewFile();
			
			
			bw=new BufferedWriter(new FileWriter(tempFile));
			
			
			
			Set oneItem=itemMap.keySet();
			int countOneItem=0;
			for(Iterator it=oneItem.iterator();it.hasNext();)
			{
				int key=(Integer)it.next();
				int value=(Integer)itemMap.get(key);
				if(value >= ItemSet.limitSupport)
				{
					bw.write(key+" "+":"+" "+value);
					bw.write("\n");
					countOneItem++;
				}
			}
			bw.flush();
			modSum+=countOneItem;
			
			itemNum=(Integer)itemMap.lastKey();
			
			a=new TreeSet[itemNum+1][itemNum+1];
			array.add(new HeadNode());//空項
			
			for(short i=1;i<=itemNum;i++)
			{
				HeadNode hn=new HeadNode();
			//	hn.item=i;
				array.add(hn);
			}
			
			BufferedReader br2=new BufferedReader(new FileReader(file));
			
			//第二次掃描數據集合,形成2-項候選集
			int counter=0;//事務
			int max=0;
			while((str=br2.readLine()) != null)
			{max++;
				String[] line=str.split(" ");
				counter++;
				for(int i=0;i<line.length;i++)
				{
					int sOne=Integer.parseInt(line[i]);
					for(int j=i+1;j<line.length;j++)
					{
						int sTwo=Integer.parseInt(line[j]);
						if(a[sOne][sTwo] == null)
						{
							Set set=new TreeSet();
							set.add(counter);
							a[sOne][sTwo]=set;
						}
						else{
							a[sOne][sTwo].add(counter);
													
						}
					}
				}
			}
			//將數組集合轉換爲鏈表集合
			
			for(int i=1;i<=itemNum;i++)
			{
				HeadNode hn=array.get(i);
				for(int j=i+1;j<=itemNum;j++)
				{
					if(a[i][j] != null && a[i][j].size() >= ItemSet.limitSupport)
					{
						hn.items++;
						ItemSet is=new ItemSet(true);
						is.item=2;
						is.items.set(i);
						is.items.set(j);
						is.supports=a[i][j].size();
						bw.write(i+" "+j+" "+": "+is.supports);
						bw.write("\n");
						//統計頻繁2-項集的個數
						modSum++;
						for(Iterator it=a[i][j].iterator();it.hasNext();)
						{
							int value=(Integer)it.next();
							is.trans.set(value);
						}
						if( hn.first== null)
						{
							hn.first=is;
							hn.last=is;
						}
						else{
							hn.last.next=is;
							hn.last=is;
						}
					}
				}
			}
			bw.flush();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	public void start()
	{
		boolean flag=true;
		//TreeSet ts=new TreeSet();//臨時存儲項目集合,防止重複項集出現,節省空間
		
		int count=0;
		
		ItemSet shareFirst=new ItemSet(false);
		
		while(flag)
		{
			flag=false;
			//System.out.println(++count);
			for(int i=1;i<array.size();i++)
			{
				HeadNode hn=array.get(i);
				
				
				if(hn.items > 1 )//項集個數大於1
				{	
					generateLargeItemSet(hn,shareFirst);
					flag=true;
					
				}
				clear(hashTable);
			}
			
		}try {
			bw.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	public void generateLargeItemSet(HeadNode hn,ItemSet shareFirst){
		
		
		BitSet bsItems=new BitSet(ItemSet.ItemSize);//存放鏈兩個k-1頻繁項集的ItemSet交
		BitSet bsTrans=new BitSet(ItemSet.TransSize);//存放兩個k-1頻繁項集的Trans交
		BitSet containItems=new BitSet(ItemSet.ItemSize);//存放兩個k-1頻繁項集的ItemSet的並
		BitSet bsItems2=new BitSet(ItemSet.ItemSize);//臨時存放容器BitSet
		
		ItemSet oldCurrent=null,oldNext=null;
		oldCurrent=hn.first;
		long countItems=0;
		
		ItemSet newFirst=new ItemSet(false),newLast=newFirst;
		while(oldCurrent != null)
		{
			oldNext=oldCurrent.next;
			while(oldNext != null)
			{
				//生成k—項候選集,由兩個k-1項頻繁集生成
				bsItems.clear();
				bsItems.or(oldCurrent.items);
				bsItems.and(oldNext.items);
				
				if(bsItems.cardinality() < oldCurrent.item-1)
				{
					break;
				}
				//新合併的項集是否已經存在
				
				containItems.clear();
				containItems.or(oldCurrent.items);//將k-1項集合並
				containItems.or(oldNext.items);
				
				if(!containItems(containItems,bsItems2,newFirst)){
					
					bsTrans.clear();
					bsTrans.or(oldCurrent.trans);
					bsTrans.and(oldNext.trans);
					if(bsTrans.cardinality() >= ItemSet.limitSupport)
					{
						ItemSet is=null;
						
						if(shareFirst.next == null)//沒有共享ItemSet鏈表
						{
							is=new ItemSet(true);
							newItemNum++;
						}
						else
						{
							is=shareFirst.next;
							shareFirst.next=shareFirst.next.next;
							
							is.items.clear();
							is.trans.clear();
							is.next=null;
							
						}
						is.item=(oldCurrent.item+1);//生成k—項候選集,由兩個k-1項頻繁集生成
						
						is.items.or(oldCurrent.items);//將k-1項集合並
						is.items.or(oldNext.items);//將k-1項集合並
						
						is.trans.or(oldCurrent.trans);//將bs1的值複製到bs中
						is.trans.and(oldNext.trans);
						
						is.supports=is.trans.cardinality();
						
						writeToFile(is.items,is.supports);//將頻繁項集及其支持度寫入文件
						countItems++;
						
						modSum++;
						newLast.next=is;
						newLast=is;
						
					}
				}
				oldNext=oldNext.next;
			}
			oldCurrent=oldCurrent.next;
		}
		
		ItemSet temp1=hn.first;
		ItemSet temp2=hn.last;
		
		temp2.next=shareFirst.next;
		shareFirst.next=temp1;
		
		hn.first=newFirst.next;
		hn.last=newLast;
		hn.items=countItems;
		
	}
	
	public boolean containItems(BitSet containItems,BitSet bsItems2,ItemSet first)
	{
		long size=containItems.cardinality();//項集數目
		
		int itemSum=0;
		int temp=containItems.nextSetBit(0);
		while(true)
		{
			itemSum+=temp;
			temp=containItems.nextSetBit(temp+1);
			if(temp == -1)
			{
				break;
			}
		}
		
		int hash=itemSum%(ItemSet.ItemSize*3);
		
		HashNode hn=hashTable[hash].next;
		Node pre=hashTable[hash];
		while(true)
		{
			if(hn == null)//不包含containItems
			{
				HashNode node=new HashNode();
				node.bs.or(containItems);
				
				pre.next=node;
				
				return false;
			}
			if(hn.bs.isEmpty())
			{
				hn.bs.or(containItems);
				
				return false;
			}
			
			bsItems2.clear();
			bsItems2.or(containItems);
			bsItems2.and(hn.bs);
			
			if(bsItems2.cardinality() == size)
			{
				return true;
			}
			pre=hn;
			hn=hn.next;
		}
		
	}
	
	public void clear(HashHeadNode[] hashTable)
	{
		for(int i=0;i<hashTable.length;i++)
		{
			HashNode node=hashTable[i].next;
			while(node != null)
			{
				node.bs.clear();
				node=node.next;
			}
		}
	}
	
	public void writeToFile(BitSet items,int supports)
	{
		StringBuilder sb=new StringBuilder();
		//sb.append("<");
		int temp=items.nextSetBit(0);
		sb.append(temp);
		while(true)
		{
			temp=items.nextSetBit(temp+1);
			if(temp == -1)
			{
				break;
			}
			//sb.append(",");
			sb.append(" ");
			sb.append(temp);
		}
		sb.append(" :"+" "+supports);
		try {
			bw.write(sb.toString());
			bw.write("\n");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	public static void main(String[] args) {
		EclatRelease e=new EclatRelease();
		long begin=System.currentTimeMillis();
		e.init();
		e.start();
		long end=System.currentTimeMillis();
		
		double time=(double)(end-begin)/1000;
		System.out.println("共耗時"+time+"秒");
		System.out.println("頻繁模式數目:"+EclatRelease.modSum);
	}
}
class MyMap<T,E> extends TreeMap
{
	public void add(T obj)
	{
		if(this.containsKey(obj))
		{
			int value=(Integer)this.get(obj);
			this.put(obj, value+1);
		}
		else 
			this.put(obj, 1);
	}
}
ItemSet類如下

package com.pku.yhf;

import java.util.BitSet;

public class ItemSet {
	public static  int limitSupport;//根據閾值計算出的最小支持度數
	public static int ItemSize;//Items數目
	public static int TransSize; //事務數目
	
	public boolean flag=true; //true,表示作爲真正的ItemSet,false只作爲標記節點,只在HashTabel中使用
	
	public int item=0;// 某項集
	
	public int supports=0;//項集的支持度
	
	public BitSet items=null;
	public BitSet trans=null;
	
	//public TreeSet items=new TreeSet();//項集
	//public TreeSet trans=new TreeSet();//事務集合
	public ItemSet next=null;//下一個項集
	
	public ItemSet(boolean flag)
	{
		this.flag=flag;
		if(flag)
		{
			item=0;// 某項集
			
			supports=0;//項集的支持度
			
			items=new BitSet(ItemSize+1);
			trans=new BitSet(TransSize+1);
		}
	}
}
對mushroom.dat的頻繁模式挖掘結果如下



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章