说明:参考Mahout FP算法相关相关源码。
算法工程可以在FP关联规则计算置信度下载:(只是单机版的实现,并没有MapReduce的代码)
使用FP关联规则算法计算置信度基于下面的思路:
1. 首先使用原始的FP树关联规则挖掘出所有的频繁项集及其支持度;这里需要注意,这里是输出所有的频繁项集,并没有把频繁项集合并,所以需要修改FP树的相关代码,在某些步骤把所有的频繁项集输出;(ps:参考Mahout的FP树单机版的实现,进行了修改,暂不确定是否已经输出了全部频繁项集)
为举例简单,可以以下面的数据为例(原始事务集):
牛奶,鸡蛋,面包,薯片 鸡蛋,爆米花,薯片,啤酒 鸡蛋,面包,薯片 牛奶,鸡蛋,面包,爆米花,薯片,啤酒 牛奶,面包,啤酒 鸡蛋,面包,啤酒 牛奶,面包,薯片 牛奶,鸡蛋,面包,黄油,薯片 牛奶,鸡蛋,黄油,薯片
0,2,3=4 2,4=3 0,1,2,3=3 3=6 2=7 1,2=5 1=7 0=7 0,3=5 0,2=6 0,1=5 4=4 0,1,2=4 0,1,3=4 1,3=5 1,4=3上面的频繁项集中,等号后面的是支持度;每条频繁项集显示的是经过编码的,编码的规则如下:{薯片=0, 牛奶=3, 鸡蛋=2, 面包=1, 啤酒=4}。同时,可以看到上面的频繁项集中的编码是按照顺序排列的(从小到大);
计算每条频繁项集的置信度(只计算2项和2项以上的频繁项集):
1) 对于频繁n项集,查找其前向(前向定义为前面n-1项集,比如频繁项集:0,2,3那么其前向为0,2)的支持度,如果频繁n项集存在,那么其前向(频繁n-1项集)必然存在(如果频繁项集是所有的频繁项集的话,这个规则一定是成立的);
2)使用n项集的支持度除以n项集的前向的支持度即可得到n项集的置信度;
3. 按照2中的计算方法是可以计算所有的频繁项集的置信度的,但是这里有个问题:只能计算比如0,2,3这个频繁项集的置信度,而不能计算0,3,2这个频繁项集的置信度(FP算法中频繁项集0,2,3和0,3,2是一样的频繁项集,但是计算置信度的时候就会不一样);
4. 针对3的问题,可以给出下面的解决方案;
// generateTopKFrequentPatterns(new TransactionIterator<A>( // transactionStream, attributeIdMapping), attributeFrequency, // minSupport, k, reverseMapping.size(), returnFeatures, // new TopKPatternsOutputConverter<A>(output, reverseMapping), // updater);修改为下面的代码:
generateTopKFrequentPatterns(new TransactionIterator<A>( transactionStream, attributeIdMapping), attributeFrequency, minSupport, k, reverseMapping.size(), returnFeatures,reverseMapping );这种修改在FPTree里面有很多,就不一一赘述,详情参考本文源码下载的工程;
addFrequentPatternMaxHeap(frequentPatterns);
/** * 存储所有频繁项集 * @param patternsOut */ private static void addFrequentPatternMaxHeap(FrequentPatternMaxHeap patternsOut){ String[] pStr=null; // 这里的Pattern有问题,暂时使用字符串解析 for(Pattern p:patternsOut.getHeap()){ pStr=p.toString().split("-"); if(pStr.length<=0){ continue; } // 对字符串进行下处理,这样可以减少存储 pStr[0]=pStr[0].replaceAll(" ", ""); pStr[0]=pStr[0].substring(1,pStr[0].length()-1); if(patterns.containsKey(pStr[0])){ if(patterns.get(pStr[0])<p.support()){// 只取支持度最大的 patterns.remove(pStr[0]); patterns.put(pStr[0], p.support()); } }else{ patterns.put(pStr[0], p.support()); } } }这里假定这样的操作可以得到所有的频繁项集,并且存入到了patterns静态map变量中。
/** * 根据排序频繁相机支持度 生成多频繁项集支持度 */ public void generateFatPatterns(){ int[] patternInts=null; for(String p :patterns.keySet()){ patternInts = getIntsFromPattern(p); if(patternInts.length==1){// 针对频繁一项集 fatPatterns.put(String.valueOf(patternInts[0]), patterns.get(p)); }else{ putInts2FatPatterns(patternInts,patterns.get(p)); } } } /** * 把数组中的每一项作为后向进行输出,添加到fatpatterns中 * @param patternInts * @param support */ private void putInts2FatPatterns(int[] patternInts, Long support) { // TODO Auto-generated method stub String patternStr =Ints2Str(patternInts); fatPatterns.put(patternStr, support);// 处理最后一个后向 for(int i=0;i<patternInts.length-1;i++){// 最后一个后向在前面已经处理 // 不能使用同一个数组 patternStr=Ints2Str(swap(patternInts,i,patternInts.length-1)); fatPatterns.put(patternStr, support); } }
public void savePatterns(String output,Map<String,Long> map){ // 清空patternsMap patternsMap.clear(); String preItem=null; for(String p:map.keySet()){ // 单项没有前向,不用找 if(p.lastIndexOf(",")==-1){ continue; } // 找出前向 preItem = p.substring(0, p.lastIndexOf(",")); if(map.containsKey(preItem)){ // patterns.get(p) 支持度,patterns.get(preItem)前向支持度 patternsMap.put(p, map.get(p)*1.0/map.get(preItem)); } } FPTreeDriver.createFile(patternsMap, output); }由于把频繁项集和支持度都放入了Map中,所以这样计算比较简单。
分享,成长,快乐
转载请注明blog地址:http://blog.csdn.net/fansy1990