Weka 學習 Apriori 附一 AprioriTID算法

       如果看了《Fast Algorithms for Mining Association Rules in Large Databases》,會發現對於 findLargeItemSets 來說,有兩種算法。第一種就是Weka用的 apriori,另外一種叫做AprioriTid.兩者殊途同歸,最後得到相同的結果。往下深究,會發現其實區別僅僅在對新產生的集合每一項的Support更新上面。我下面簡單介紹兩者之前的不同點。

Apriori:每一步生成的Candidate。用Database(或者說是Instances)來更新Support。對於每一個Instance,如果它所包含的子集存在於Candidate中,那麼就對Candidate該項+1 。(論文裏說 對每一個Item hash。其實就是這個意思)。

AprioriTid:Database(Instances)只會用到一次。這裏,對於每一個instance。會產生一個集合的集合。比如instance={i1,i2,i3}那麼會產生{{i1},{i2},{i3}}.然後可以用一個數組或者一個Map將<TID,SetOfItemSet>存放起來,由於TID一般爲數字,因此我的算法裏用的是一個數組TIDs。我對於算法的理解是:對於每一個TID,維持一個和CandidateK同步的K-SetOfItemSet,如果對於K-SetOfItemSet中的ItemSet存在於CandidateK中,那麼ItemSet.count++。這裏有一個提高算法速度的方法,將<TID,SetOfItemSet>中Suport<m_support的刪除,因爲這些項不可能產生與LargeK中。總結起來,也就是說對於每一個<TID,SetOfItemSet>,它維護的是LargeK的子集。(哈,這也是我邊寫邊總結出來的)。之所以這和Apriori殊途同歸是因爲:首先對於每一個<TID,SetOfItemSet>,她每一次產生的集合都是Instances[TID]的子集。而它每次刪除的都是一定不會出現在LargeK中的ItemSet。綜上得證。

下面是我實現的AprioriTid,經測試與Weka產生的結果一樣。

 if(!m_car){
        // Find large itemsets and rules
    	//findLargeItemSets();
        findLargeItemSetsTID();


 

 

public void findLargeItemSetsTID() throws Exception
  {
	  FastVector kMinusOneSets, kSets;
	  FastVector kMinusOneTids,kTids;
	  FastVector kCandidateSets;
	    Hashtable hashtable;
	    int necSupport, necMaxSupport,i = 0;
	    
	    
	    
	    // Find large itemsets

	    // minimum support
	    necSupport = (int)(m_minSupport * (double)m_instances.numInstances()+0.5);
	    necMaxSupport = (int)(m_upperBoundMinSupport * (double)m_instances.numInstances()+0.5);
	    kSets = AprioriItemSet.singletons(m_instances);
	    AprioriItemSet.upDateCounters(kSets,m_instances);
	    kTids=AprioriItemSet.singletonsTID(m_instances);//利用database生成1-Tids
	    kSets = AprioriItemSet.deleteItemSets(kSets, necSupport, m_instances.numInstances());
	    if (kSets.size() == 0)
	      return;
	    do {
	      m_Ls.addElement(kSets);
	      kMinusOneSets = kSets;
	      kMinusOneTids=kTids;

	      /**
	       * 下面四行代碼生成了論文裏的Ck。
	       */
	      kMinusOneTids=AprioriItemSet.pruneItemSetsTID(kMinusOneTids, kMinusOneSets);//根據kMinusOneSets刪除kMinusOneTids中不是Large的項
	      kSets = AprioriItemSet.mergeAllItemSets(kMinusOneSets, i, m_instances.numInstances());
	      hashtable = AprioriItemSet.getHashtable(kMinusOneSets, kMinusOneSets.size());
	      m_hashtables.addElement(hashtable);
	      kSets = AprioriItemSet.pruneItemSets(kSets, hashtable);
	      
	      AprioriItemSet.upDateCountersTID(kSets,kMinusOneTids,kTids,i,m_instances.numInstances());//用的是論文裏的AprioriTID
	    //  AprioriItemSet.upDateCounters(kSets, m_instances);//這用的是論文裏的Apriori。 
	      kSets = AprioriItemSet.deleteItemSets(kSets, necSupport, m_instances.numInstances());
	      i++;
	    } while (kSets.size() > 0);
  }


 

 

 

 

public static FastVector singletonsTID(Instances instances) throws Exception {
	
	
	  FastVector setOfItemSets = new FastVector();
	   
	  Enumeration enu=instances.enumerateInstances();
	  while(enu.hasMoreElements())
	  {
		  Instance instance=(Instance) enu.nextElement();
		  FastVector tid=new FastVector();
		  /**
		   * 對於每一個TID,把所有出現的Item都生成一個集合存在 FastVector tid 中。
		   */
		 for(int i=0;i<instance.numAttributes();i++)
		 {
			  ItemSet current;
			  current = new AprioriItemSet(instances.numInstances());
			  current.m_items = new int[instances.numAttributes()];
			  for(int j=0;j<current.m_items.length;j++) current.m_items[j]=-1;
			  current.m_items[i]=(int) instance.value(i);
			  tid.addElement(current);
		 }
		  setOfItemSets.addElement(tid);
	  }
	   
	    return setOfItemSets;
}


public static void upDateCountersTID(FastVector kSets,
		FastVector kMinusOneTids, FastVector kTids,int i,int totalTrans) {
	  FastVector newSets = AprioriItemSet.mergeAllItemSetsTID(kMinusOneTids, i, totalTrans);
	  Enumeration enu=newSets.elements();
	  while(enu.hasMoreElements())
	  {
		  FastVector tid=(FastVector) enu.nextElement();
		  FastVector newTid=new FastVector();
		  Enumeration enuTID=tid.elements();
		  while(enuTID.hasMoreElements())
		  {
		  ItemSet cur=(ItemSet) enuTID.nextElement();
		  for(int j=0;j<kSets.size();j++)
		  {
			  ItemSet item=(ItemSet) kSets.elementAt(j);
			  if(cur.equals(item))
			  {
				  item.m_counter++;
				  cur.m_counter++;
				newTid.addElement(cur);
				  break;
			  }
		  }
		  
		  }
		  if(newTid.size()>0)kTids.addElement(newTid);
	  }
	
}


以上就不一一解釋了。太晚了。該睡覺了。相信看了之前我對Apriori和AprioriTid的差別的分析。代碼很容易理解。



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