FP-tree的hadoop實現

FP 樹是關聯規則算法的一種,主要是用於分析數據項之間的關聯性,將關聯性大的數據項找出來,具體的一些概念見書《數據挖掘概念與技術》上介紹的頻繁項集,支持度等。

算法執行過程:

1.          掃描數據,計算一項集的計數。

2.          根據計數與支持度計算出頻繁一項集,對於頻繁一項集按照計數從大到小進行排序,並且對它們標上相應的序號後,把它們存放在 DFS 上,後面在做 MAP 或者 REDUCE 之前到 dfs 上讀取相應的項集和序號。

3.          根據劃分集合的數目將頻繁一項集劃分成 G 份,並且對每一份有個標號 GID ,把一項集映射到相應的 GID 上,同樣把這個 G-List 存放到 dfs 上,以後需要讀取。

4.          再次掃描事務數據,將事務項集轉換成項集的序號集合,並且對其進行排序,再生成相應的條件事務序號集合。將其根據 GID 收集,再對每個 GID 構造 FP 樹,然後得出條件模式基和條件 FP 樹,再得出最大的 K 個頻繁模式。

5.          將所有項集的頻繁模式收集起來,對於每個項生成最大的 K 個頻繁模式。

 

步驟代碼如下:

startParallelCounting (params);

startGroupingItems (params);

startTransactionSorting (params);

startParallelFPGrowth (params);

startAggregating (params);

 

 

對於每個項,計算它的計數。並且排序後保存到相應的分佈式文件中。

在構選 FP 樹時首先添加表頭的項以及相應的計數。

FPTree tree = new FPTree(featureSetSize);

    for ( int i = 0; i < featureSetSize; i++) {

      tree.addHeaderCount(i, attributeFrequency[i]);

}

 

然後對於每個事務項集,將其添加到 FP 樹上,即初始化 FP 樹。

while (transactions.hasNext()) {

      int [] transaction = transactions.next();

      Arrays.sort (transaction);

      //attribcount += transaction.length;

      nodecount += treeAddCount (tree, transaction, 1, minSupportMutable,

          attributeFrequency );

      i++;

      if (i % 10000 == 0) {

        log .info( "FPTree Building: Read {} Transactions" , i);

      }

}

 

事務項添加過程:

然後從根結點開始,判斷相應的每一個 attribute 是否在 Temp 結點中的子結點中,如果在,則將其計數加 1 。如果不在,則創建一個新的子結點。

for ( int attribute : myList) {

      if (attributeFrequency[attribute] < minSupport.intValue())

        return ret;

      int child;

      if (addCountMode) {

        child = tree.childWithAttribute(temp, attribute);

        if (child == -1) {

          addCountMode = false ;

        } else {

          tree.addCount(child, addCount );

          temp = child;

        }

      }

      if (!addCountMode) {

        child = tree.createNode(temp, attribute, addCount);

        temp = child;

        ret++;

      }

}

 

最後,遞歸對 FP 樹進行挖掘,從表頭的最後一項開始,得到相應的前綴路徑,形成相應的條件模式基,計算出相應的條件 FP 樹,得到最後的頻繁模式,這裏只輸出計數最大的 K 個頻繁模式。參見書《數據挖掘的概念與技術》中 158 頁。

  for ( int i = tree .getHeaderTableCount() - 1; i >= 0; i--) {

      int attribute = tree .getAttributeAtIndex(i);

      if (requiredFeatures.contains(attribute) == false )

        continue ;

      log .info( "Mining FTree Tree for all patterns with {}" , attribute);

      MutableLong minSupport = new MutableLong(minSupportValue);

      FrequentPatternMaxHeap frequentPatterns = growth(tree , minSupport, K,

           treeCache, 0, attribute);

      Patterns.put(attribute, frequentPatterns);

      outputCollector.collect(attribute, frequentPatterns);

 

      minSupportValue = Math.max (minSupportValue, minSupport.intValue() / 2);

      log .info( "Found {} Patterns with Least Support {}" , Patterns.get(

          attribute).count(), Patterns.get(attribute).leastSupport());

}

 

 

對於每個項,總結它的所有的頻繁項集以及相應的計數,並且輸出計數最大的 K 個頻繁模式。

 

例子:

 

 

 

 

實例測試:

利用 HADOOP 的命令先將數據集從本地放入 HDFS 上。

如:

bin/hadoop fs -put E:/cygwin/home/lianhui/datasets datasets

 

然後執行相應的數據處理類

bin/hadoop fs -copyFromLocal E:/cygwin/home/lianhui/datasets/mushroom.dat datasets

bin/hadoop jar mahout-examples-0.3.job org.apache.mahout.fpm.pfpgrowth.FPGrowthDriver -i datasets/mushroom.dat -o patterns -k 50 -method mapreduce -g 10 -regex [/ ] -s 2

 

查看最終的關聯結果:

即讀取分佈式文件 : patterns / frequentPatterns 文件中的內容。

try {

            Configuration conf = new Configuration();

              Path path = new Path( "hdfs://localhost:9999/user/lianhui/patterns/frequentPatterns/part-r-00000" );

            FileSystem fs = FileSystem.get (path.toUri(), conf);

            //fs = path.getFileSystem(conf);

            SequenceFile.Reader reader = new SequenceFile.Reader(fs, path, conf);

//          Text key=new Text();

//          TopKStringPatterns patterns = new TopKStringPatterns();

            Writable key=(Writable) ReflectionUtils.newInstance (reader.getKeyClass(),conf);

            Writable value=(Writable) ReflectionUtils.newInstance (reader.getValueClass(),conf);

            while (reader.next(key,value)){

                System. out .println( "key=" +key+ ",value=" +value);

                long position=reader.getPosition();

                //System.out.println("position="+position);

            }

            reader.close();

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