mahout关联规则之FPGrowthDriver源码分析part1 (二)
sentedAsList = true;
transactionSet = Lists.newArrayList();
transactionSet.add(new Pair(items, support));
}
2.3.2 ParallelFPGrowthCombiner的reduce函数:
[java]
TransactionTree cTree =new TransactionTree();
[java] view plaincopy
for (TransactionTree tr : values) {
for (Pair p : tr) {
cTree.addPattern(p.getFirst(), p.getSecond());
}
}
context.write(key, cTree.getCompressedTree());
这里可以看到新建了一个TransactionTree,然后把同一组(groupid)的记录通过addPattern方法放入到一棵TransactionTree上,最后通过getCompressedTree方法返回一个压缩了的TransactionTree并输出此TransactionTree;
TransactionTree的属性有:
[java]
int[] attribute;
int[] childCount;
int[][] nodeChildren;
long[] nodeCount;
int nodes;
boolean representedAsList;
List> transactioniSet;
比如[0,2,4,6],[0,2,4],[2,4,8]下面三条记录通过addPattern加入数中的效果如下:
第一、二条记录:
第三条记录:
通过addPattern方法加入记录,TransactionTree的representedAsList属性为false,transactionSet为null,其他属性则存储相应的值;
通过上面的方法即可以把每个id都建立一个TransactionTree,所以针对表3的数据建立了2棵TransactionTree,然后每棵TransactionTree又通过getCompressedTree把得到的两棵TrasactionTree进行压缩。压缩的方法就是把用数组表示的值用list表示,这时的representedAsList 属性为true,且transactionSet,不为null,而是下面的值:id:0,value:{([1],2)([1, 3],5)([2],1)([2, 4],1)([0, 2],1)([0, 2, 4],4)([0, 4],2)([3],2)};id:1,value:{([0, 2, 4, 6],2)([0, 2, 4, 6, 8],1)([0, 2, 6],1)([0, 4, 8],1)([0, 4, 6],1)([2, 6, 8],1)([2, 4, 8],1)([1, 5, 9],1)([1, 5, 7],1)([1, 3, 5],1)([1, 3, 5, 7],2)([1, 3, 5, 7, 9],1)([1, 3, 7],1)([3, 7, 9],1)([3, 5, 9],1)},其实上面的结果也就是表3中每个事务出现的次数而已;
2.3.3 ParalleFPGrowthReducer:
2.3.3.1 setup函数,这个函数和Mapper的setup函数的作用是一样的,都是读fList文件,但是这里是把项目读入List featureReverseMap,把相应的频度读入LongArrayList freqList;
2.3.3.2 reduce函数:首先产生一个localFList即gList,使用TransactionTree的generateFList方法,此方生成一棵TransactionTree中含有的所有项目的一个list即其相应的在这棵TransactionTree上面的频数;比如上面的两棵TransactionTree生成的gList及其相应的频数分别为: [(0,7), (1,7), (2,7), (3,7), (4,7)] 和[(1,7), (3,7), (5,7), (0,6), (2,6), (4,6), (6,6), (7,6), (8,4), (9,4)];接着调用FPGrowth的generateTopKFrequentPatterns方法;
[java]
FPGrowth fpGrowth = new FPGrowth();
fpGrowth.generateTopKFrequentPatterns()
打开FPGrowth的源码,找到下面的方法:
[java]
public final void generateTopKFrequentPatterns(Iterator,Long>> transactionStream,
Collection> frequencyList,
long minSupport,
int k,
Collection returnableFeatures,
OutputCollector,Long>>> output,
StatusUpdater updater)
这个放入首先就是把相应的fList转为gList,比如对于第二棵TransactionTree的gList:[(1,7), (3,7), (5,7), (0,6), (2,6), (4,6), (6,6), (7,6), (8,4), (9,4)],其项目按频度降序排序如下:1,3,5,0,2,4,6,7,8,9;那么本地的gList对其进行重新编码:{0=3, 1=0, 2=4, 3=1, 4=5, 5=2, 6=6, 7=7, 8=8, 9=9},所以1,3,5,0,2,4,6,7,8,9在本地就应该为:0,1,2,3,4,5,6,7,8,9;对于原来的记录:{[2,3,4,6],2}就会变为{[3,4,5,6]2};接着,该函数调用了generateTopKFrequentPatterns这个函数,第一次我以为它又调用了自身(就是上面说的理解错误的地方),往下看,有一个同名的方法,但是输入参数不一样;并且引入了FPTree,下次再分析。