java实现fp

本文参考韩家炜《数据挖掘-概念与技术》一书第六章,前提条件要理解 apriori算法。

另外一篇写得较好的文章在此推荐:

http://hi.baidu.com/nefzpohtpndhovr/item/9d5c371ba2dbdc0ed1d66dca

0.实验数据集:user2items.csv

I1,I2,I5I2,I4I2,I3I1,I2,I4 I1,I3 I2,I3I1,I3I1,I2,I3,I5I1,I2,I3

1.算法原理构造FPTree 1、首先读取数据库中所有种类的项和这些项的支持度计数。存入到itTotal链表中。 2、将itTotal链表按照支持度计数从大到小排序 3、将itTotal链表插入到ItemTb表中 4、第二便读取数据库中的事务,将事务中的项按照支持度计数由大到小的顺序插入到树中。 5、遍历树,将属于同一项的结点通过bnode指针连接起来。 本程序中,FP-tree中存储了所有的项集,没有考虑最小支持度。只是在FP-growth中挖掘频繁项集时考虑最小支持度

/** *  * @param records 构建树的记录,如I1,I2,I3 * @param header 韩书中介绍的表头 * @return 返回构建好的树 */public TreeNode2 builderFpTree(LinkedList<LinkedList<String>> records,List<TreeNode2> header){   TreeNode2 root;   if(records.size()<=0){   return null;   }   root=new TreeNode2();   for(LinkedList<String> items:records){   itemsort(items,header);  addNode(root,items,header);}String dd="dd";String test=dd;return root;}//当已经有分枝存在的时候,判断新来的节点是否属于该分枝的某个节点,或全部重合,递归public  TreeNode2 addNode(TreeNode2 root,LinkedList<String> items,List<TreeNode2> header){if(items.size()<=0)return null;String item=items.poll();//当前节点的孩子节点不包含该节点,那么另外创建一支分支。TreeNode2 node=root.findChild(item);if(node==null){            node=new TreeNode2();node.setName(item);node.setCount(1);node.setParent(root);root.addChild(node);//加将各个同名的节点加到链头中 for(TreeNode2 head:header){if(head.getName().equals(item)){while(head.getNextHomonym()!=null){head=head.getNextHomonym();}head.setNextHomonym(node);break;}}//加将各个节点加到链头中}else{node.setCount(node.getCount()+1);} addNode(node,items,header);return root;}

FP_growth算法: 从一棵FPTree的ItemTb表中取得第一个项I1。如果该项的支持度计数满足最小支持度计数{ 1、把该项I1加入到存储挖掘到的频繁项集的数据结构ItemSet中 2、得到该项I1在目前FPTree中的条件模式基,即该项在树中的结点的前缀路径(路径中不再包括该项)。 注意该项I1的条件模式基中各个项的支持度计数相等,等于该项I1的支持度计数 3、每条路径看作一个事务,用这些路径建造该项的条件FPTree,然后递归调用FP_growth算法。 在递归调用FP_growth算法时,那些大于支持度计数的项作为项I1的孩子结点存储在ItemSet中。 }本人觉得要想更好的理解,或者有不明之处应该参考http://hi.baidu.com/nefzpohtpndhovr/item/9d5c371ba2dbdc0ed1d66dca这篇文章的这个地方,见下图。

public void fpgrowth(LinkedList<LinkedList<String>> records,String item){//保存新的条件模式基的各个记录,以重新构造FP-treeLinkedList<LinkedList<String>> newrecords=new LinkedList<LinkedList<String>>();//构建链头LinkedList<TreeNode2> header=buildHeaderLink(records);//创建FP-TreeTreeNode2 fptree= builderFpTree(records,header);//结束递归的条件if(header.size()<=0||fptree==null){System.out.println("-----------------");return;}//打印结果,输出频繁项集if(item!=null){//寻找条件模式基,从链尾开始for(int i=header.size()-1;i>=0;i--){TreeNode2 head=header.get(i);String itemname=head.getName();Integer count=0;while(head.getNextHomonym()!=null){head=head.getNextHomonym();//叶子count等于多少,就算多少条记录count=count+head.getCount();}//打印频繁项集System.out.println(head.getName()+","+item+"\t"+count);}}//寻找条件模式基,从链尾开始for(int i=header.size()-1;i>=0;i--){TreeNode2 head=header.get(i);String itemname;//再组合if(item==null){itemname=head.getName();}else{itemname=head.getName()+","+item;}while(head.getNextHomonym()!=null){head=head.getNextHomonym();//叶子count等于多少,就算多少条记录Integer count=head.getCount();for(int n=0;n<count;n++){   LinkedList<String> record=new LinkedList<String>();   toroot(head.getParent(),record);   newrecords.add(record);}}//System.out.println("-----------------");//递归之,以求子FP-Treefpgrowth(newrecords,itemname);}    }

2.tree的结构 private String name; // 节点名称 private Integer count; // 计数 private TreeNode2 parent; // 父节点 private List<TreeNode2> children; // 子节点 private TreeNode2 nextHomonym; // 下一个同名节点详见下面的TreeNode2类3.完整的源码:共两份.java文件,直接贴到eclipse中即可以执行。

package mysequence.machineleaning.association.fpgrowth;import java.io.BufferedReader;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.Collections;import java.util.HashMap;import java.util.LinkedList;import java.util.List;import java.util.Map;import java.util.Set;public class Myfptree2 {public static final int  support = 2; // 设定最小支持频次为2 //保存第一次的次序public Map<String,Integer> ordermap=new HashMap<String,Integer>();public LinkedList<LinkedList<String>> readF1() throws IOException {      LinkedList<LinkedList<String>> records=new LinkedList<LinkedList<String>>();//String filePath="scripts/clustering/canopy/canopy.dat";String filePath="datafile/association/user2items.csv";BufferedReader br = new BufferedReader(new InputStreamReader(        new FileInputStream(filePath)));        for (String line = br.readLine(); line != null; line = br.readLine()) {            if(line.length()==0||"".equals(line))continue;        String[] str=line.split(",");           LinkedList<String> litm=new LinkedList<String>();        for(int i=0;i<str.length;i++){        litm.add(str[i].trim());        }            records.add(litm);                     }        br.close();        return records;    }//创建表头链public LinkedList<TreeNode2> buildHeaderLink(LinkedList<LinkedList<String>> records){LinkedList<TreeNode2> header=null;if(records.size()>0){header=new LinkedList<TreeNode2>();}else{return null;}Map<String, TreeNode2> map = new HashMap<String, TreeNode2>();for(LinkedList<String> items:records){for(String item:items){//如果存在数量增1,不存在则新增if(map.containsKey(item)){map.get(item).Sum(1);}else{TreeNode2 node=new TreeNode2();node.setName(item);node.setCount(1);map.put(item, node);}             }} // 把支持度大于(或等于)minSup的项加入到F1中        Set<String> names = map.keySet();        for (String name : names) {            TreeNode2 tnode = map.get(name);            if (tnode.getCount() >= support) {            header.add(tnode);            }        }        sort(header);        String test="ddd";return header;}//选择法排序,如果次数相等,则按名字排序,字典顺序,先小写后大写public List<TreeNode2> sort(List<TreeNode2> list){int len=list.size();for(int i=0;i<len;i++){for(int j=i+1;j<len;j++){TreeNode2 node1=list.get(i);TreeNode2 node2=list.get(j);if(node1.getCount()<node2.getCount()){TreeNode2 tmp=new TreeNode2();tmp=node2;list.remove(j);//list指定位置插入,原来的>=j元素都会往下移,不会删除,所以插入前要删除掉原来的元素list.add(j,node1);list.remove(i);list.add(i,tmp);}//如果次数相等,则按名字排序,字典顺序,先小写后大写if(node1.getCount()==node2.getCount()){String name1=node1.getName();String name2=node2.getName();int flag=name1.compareTo(name2);if(flag>0){TreeNode2 tmp=new TreeNode2();tmp=node2;list.remove(j);//list指定位置插入,原来的>=j元素都会往下移,不会删除,所以插入前要删除掉原来的元素list.add(j,node1);list.remove(i);list.add(i,tmp);}}}}return list;}//选择法排序,降序,如果同名按L 中的次序排序public   List<String> itemsort(LinkedList<String> lis,List<TreeNode2> header){//List<String> list=new ArrayList<String>();//选择法排序int len=lis.size();for(int i=0;i<len;i++){for(int j=i+1;j<len;j++){String key1=lis.get(i);String key2=lis.get(j);Integer value1=findcountByname(key1,header);if(value1==-1)continue;Integer value2=findcountByname(key2,header);if(value2==-1)continue;if(value1<value2){String tmp=key2;lis.remove(j);lis.add(j,key1);lis.remove(i);lis.add(i,tmp);}if(value1==value2){int v1=ordermap.get(key1);int v2=ordermap.get(key2);if(v1>v2){String tmp=key2;lis.remove(j);lis.add(j,key1);lis.remove(i);lis.add(i,tmp);}}     }}return lis;}public Integer findcountByname(String itemname,List<TreeNode2> header){Integer count=-1;for(TreeNode2 node:header){if(node.getName().equals(itemname)){count= node.getCount();}}return count;}/** *  * @param records 构建树的记录,如I1,I2,I3 * @param header 韩书中介绍的表头 * @return 返回构建好的树 */public TreeNode2 builderFpTree(LinkedList<LinkedList<String>> records,List<TreeNode2> header){   TreeNode2 root;   if(records.size()<=0){   return null;   }   root=new TreeNode2();   for(LinkedList<String> items:records){   itemsort(items,header);  addNode(root,items,header);}String dd="dd";String test=dd;return root;}//当已经有分枝存在的时候,判断新来的节点是否属于该分枝的某个节点,或全部重合,递归public  TreeNode2 addNode(TreeNode2 root,LinkedList<String> items,List<TreeNode2> header){if(items.size()<=0)return null;String item=items.poll();//当前节点的孩子节点不包含该节点,那么另外创建一支分支。TreeNode2 node=root.findChild(item);if(node==null){            node=new TreeNode2();node.setName(item);node.setCount(1);node.setParent(root);root.addChild(node);//加将各个节点加到链头中 for(TreeNode2 head:header){if(head.getName().equals(item)){while(head.getNextHomonym()!=null){head=head.getNextHomonym();}head.setNextHomonym(node);break;}}//加将各个节点加到链头中}else{node.setCount(node.getCount()+1);} addNode(node,items,header);return root;}//从叶子找到根节点,递归之public void toroot(TreeNode2 node,LinkedList<String> newrecord){if(node.getParent()==null)return;String name=node.getName();newrecord.add(name);toroot(node.getParent(),newrecord);}//对条件FP-tree树进行组合,以求出频繁项集public void combineItem(TreeNode2 node,LinkedList<String> newrecord,String Item){if(node.getParent()==null)return;String name=node.getName();newrecord.add(name);toroot(node.getParent(),newrecord);}//fp-growthpublic void fpgrowth(LinkedList<LinkedList<String>> records,String item){//保存新的条件模式基的各个记录,以重新构造FP-treeLinkedList<LinkedList<String>> newrecords=new LinkedList<LinkedList<String>>();//构建链头LinkedList<TreeNode2> header=buildHeaderLink(records);//创建FP-TreeTreeNode2 fptree= builderFpTree(records,header);//结束递归的条件if(header.size()<=0||fptree==null){System.out.println("-----------------");return;}//打印结果,输出频繁项集if(item!=null){//寻找条件模式基,从链尾开始for(int i=header.size()-1;i>=0;i--){TreeNode2 head=header.get(i);String itemname=head.getName();Integer count=0;while(head.getNextHomonym()!=null){head=head.getNextHomonym();//叶子count等于多少,就算多少条记录count=count+head.getCount();}//打印频繁项集System.out.println(head.getName()+","+item+"\t"+count);}}//寻找条件模式基,从链尾开始for(int i=header.size()-1;i>=0;i--){TreeNode2 head=header.get(i);String itemname;//再组合if(item==null){itemname=head.getName();}else{itemname=head.getName()+","+item;}while(head.getNextHomonym()!=null){head=head.getNextHomonym();//叶子count等于多少,就算多少条记录Integer count=head.getCount();for(int n=0;n<count;n++){   LinkedList<String> record=new LinkedList<String>();   toroot(head.getParent(),record);   newrecords.add(record);}}//System.out.println("-----------------");//递归之,以求子FP-Treefpgrowth(newrecords,itemname);}    }//保存次序,此步也可以省略,为了减少再加工结果的麻烦而加public void orderF1(LinkedList<TreeNode2> orderheader){for(int i=0;i<orderheader.size();i++){TreeNode2 node=orderheader.get(i);ordermap.put(node.getName(), i);}}public static void main(String[] args) throws IOException {// TODO Auto-generated method stub/*String s1="i1";int flag=s1.compareTo("I1");System.out.println(flag);*///读取数据Myfptree2 fpg=new Myfptree2();LinkedList<LinkedList<String>> records=fpg.readF1();LinkedList<TreeNode2> orderheader=fpg.buildHeaderLink(records);fpg.orderF1(orderheader);        fpg.fpgrowth(records,null);}}

树的结构:

package mysequence.machineleaning.association.fpgrowth;import java.util.ArrayList;import java.util.List;public class TreeNode2 implements Comparable<TreeNode2>{    private String name; // 节点名称    private Integer count; // 计数    private TreeNode2 parent; // 父节点    private List<TreeNode2> children; // 子节点    private TreeNode2 nextHomonym; // 下一个同名节点      public TreeNode2() {      }public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getCount() {return count;}public void setCount(Integer count) {this.count = count;}public void Sum(Integer count) {this.count =this.count+count;}public TreeNode2 getParent() {return parent;}public void setParent(TreeNode2 parent) {this.parent = parent;}public List<TreeNode2> getChildren() {return children;}public void setChildren(List<TreeNode2> children) {this.children = children;}public TreeNode2 getNextHomonym() {return nextHomonym;}public void setNextHomonym(TreeNode2 nextHomonym) {this.nextHomonym = nextHomonym;}    /**     * 添加一个节点     * @param child     */    public void addChild(TreeNode2 child) {        if (this.getChildren() == null) {            List<TreeNode2> list = new ArrayList<TreeNode2>();            list.add(child);            this.setChildren(list);        } else {            this.getChildren().add(child);        }    }    /**    *  是否存在着该节点,存在返回该节点,不存在返回空    * @param name    * @return    */    public TreeNode2 findChild(String name) {        List<TreeNode2> children = this.getChildren();        if (children != null) {            for (TreeNode2 child : children) {                if (child.getName().equals(name)) {                    return child;                }            }        }        return null;    }    @Override    public int compareTo(TreeNode2 arg0) {        // TODO Auto-generated method stub        int count0 = arg0.getCount();        // 跟默认的比较大小相反,导致调用Arrays.sort()时是按降序排列        return count0 - this.count;    }}

感受不同地域不一样的节奏与表象。

java实现fp

相关文章:

你感兴趣的文章:

标签云: