基于FP-Tree的关联规则FP-Growth推荐算法Java实现

package edu.test.ch8;

import java.util.ArrayList;
import java.util.List;

public class Item implements Comparable {

    private String value;
    private Item preItem; // 前继节点Item
    private List<Item> nextItem = new ArrayList<Item>(); // 后续节点Item

    private Item sibling; // 关联节点

    private int counter;

    public Item() {

    }

    public Item(String value) {
        this.value = value;
    }

    public void addCounter() {
        this.counter += 1;
    }

    public Item getSibling() {
        return sibling;
    }

    public void setSibling(Item sibling) {
        this.sibling = sibling;
    }

    public void addNextItem(Item item) {
        this.nextItem.add(item);
    }

    public List<Item> getNextItem() {

        return this.nextItem;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public Item getPreItem() {
        return preItem;
    }

    public void setPreItem(Item preItem) {
        this.preItem = preItem;
    }

    public int getCounter() {
        return counter;
    }

    public void setCounter(int counter) {
        this.counter = counter;
    }

    public int compareTo(Object o) {
        int value;
        Item i = (Item) o;

        if (this.counter > i.counter) {
            value = -1;
        } else if (this.counter == i.counter) {
            value = 0;
        } else {
            value = 1;
        }
        return value;
    }

}

package edu.test.ch8;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class FPGrowth {

    private int minSup;

    /**
     * @param args
     */
    public static void main(String[] args) {
        FPGrowth fpg = new FPGrowth();
        fpg.setMinSup(1000);
        List<String> data = fpg.buildData("retail.dat");
        Item[] f1Items = fpg.buildF1Items(data);

        Map<String, List<String>> condBase;
        //Item fpTree = fpg.buildFPTree(data, f1Items);
        fpg.buildFPTree(data, f1Items);
        // fpg.fpGrowth();
/*
        fpg.printFPTree(fpTree);
        fpg.printF1Items(f1Items);*/
        condBase = fpg.buildCondBase(f1Items);
    //  fpg.printCondBase(condBase);
        Map<String, Item> condFPTree = fpg.buildCondFPTree(condBase);
    //  fpg.printCondFPTree(condFPTree);
        //输出频繁子集
        Map<String, List<List<String>>> fpSetMap = fpg.fpGrowth(condFPTree);
        fpg.printFPSet(fpSetMap);

    }
    /**
     * 输出频繁集
     */
    public void printFPSet(Map<String, List<List<String>>> fpSetMap){
        List<List<String>> fpSet;

        Set<String> items = fpSetMap.keySet();
        for(String item : items){
            System.out.println(item);
            fpSet = fpSetMap.get(item);
            for (int i = 0; i < fpSet.size(); i++) {
                for (String str : fpSet.get(i)) {
                //  if(str != null && str.length() > 0){
                        System.out.print(str + ", ");
                //  }

                }
                System.out.println(item);
            }
        }
    }

    // 输出fpTree
    public void printFPTree(Item root) {
        System.out.print(root.getValue() + ", " + root.getCounter() + " "
                + root.getNextItem().size() + ": ");
        List<Item> subItems = root.getNextItem();
        if (subItems.size() != 0) {
            for (int i = 0; i < subItems.size(); i++) {
                printFPTree(subItems.get(i));
            }
            System.out.println();
        }

    }

    // 输出频繁1项集
    public void printF1Items(Item[] f1Items) {
        for (Item item : f1Items) {

            while ((item = item.getSibling()) != null) {
                System.out.print("item: " + item.getValue() + ": "
                        + item.getCounter() + " ,");
                if (item.getPreItem() != null) {
                    System.out.println(item.getPreItem().getValue());
                }
            }
            System.out.println();
        }
    }

    // 输出条件模式基
    public void printCondBase(Map<String, List<String>> condBaseMap) {

        Set<String> items = condBaseMap.keySet();
        List<String> conBase;
        for (String item : items) {
            System.out.print("Item: " + item);
            conBase = condBaseMap.get(item);
            System.out.println(", " + conBase.size());
            for (String str : conBase) {
                System.out.println(str + " ");
            }
        }
    }

    // 输出条件fp树
    public void printCondFPTree(Map<String, Item> condFPTreeMap) {
        Set<String> items = condFPTreeMap.keySet();
        for (String item : items) {
            System.out.println("Item: " + item);
            this.printFPTree(condFPTreeMap.get(item));
        }
    }

    /**
     * 1.构造数据集
     */
    public List<String> buildData(String...fileName) {

        List<String> data = new ArrayList<String>();
        if(fileName.length !=0){
            File file = new File(fileName[0]);
            try {
                BufferedReader reader = new BufferedReader(new FileReader(file));
                String line;
                while( (line = reader.readLine()) != null){
                    data.add(line);
                }

            } catch (FileNotFoundException e) {

                e.printStackTrace();
            } catch (IOException e) {

                e.printStackTrace();
            }
        }else{

            data.add("I1 I2 I5");
            data.add("I2 I4");
            data.add("I2 I3");
            data.add("I1 I2 I4");
            data.add("I1 I3");
            data.add("I2 I3");
            data.add("I1 I3");
            data.add("I1 I2 I3 I5");
            data.add("I1 I2 I3");
        }
        return data;
    }

    /**
     * 2.构造频繁1项列表,同时作为树的项头表
     */
    public Item[] buildF1Items(List<String> data) {
        List<Item> itemList = new ArrayList<Item>();
        Map<String, Item> resultMap = new HashMap<String, Item>();
        for (String trans : data) {

            String[] items = trans.trim().split(" ");
            int i;
            for (String item : items) {

                if(resultMap.get(item) == null){
                    Item newItem = new Item();
                    newItem.setValue(item);
                    newItem.setCounter(1);
                    resultMap.put(item, newItem);
                }else{
                    resultMap.get(item).addCounter();
                }
            }
        }
        Set<String> keySet = resultMap.keySet();
        for(String key : keySet){
            itemList.add(resultMap.get(key));
        }
        List<Item> result = new ArrayList<Item>();
        // 把支持度小于minSup的项从列表中删除
        for (int i = 0; i < itemList.size(); i++) {
            if (itemList.get(i).getCounter() >= this.minSup) {
                result.add(itemList.get(i));
            }
        }

        // 对列表进行排序
        Item[] f1Items = result.toArray(new Item[0]);
        Arrays.sort(f1Items);

        return f1Items;
    }

    /**
     * 3. 构造fpTree
     */
    public Item buildFPTree(List<String> data, Item[] f1Items) {

        Item fpTree = new Item();
        List<Item> subItems;
        // 对每一条事务进行处理
        for (String trans : data) {

            // 得出每条事件中涉及的元素项
            String[] items = trans.trim().split(" ");
            // 对items中的元素按其在频繁1项集中出现次数排序
            items = sortItem(items, f1Items);
            // 把items的值加入到fpTree中
            subItems = fpTree.getNextItem();

            if (subItems.size() == 0) {
                this.addLeaf(fpTree, items, f1Items);
            } else {
                Item temp = null;

                for (int i = 0; i < items.length; i++) {
                    int j = 0;
                    int size = subItems.size();
                    for (; j < subItems.size(); j++) {
                        if (subItems.get(j).getValue().equals(items[i])) {
                            temp = subItems.get(j);
                            temp.addCounter();
                            subItems = temp.getNextItem();
                            break;
                        }
                    }

                    if (j == size) {
                        if (temp == null) {
                            this.addLeaf(fpTree, Arrays.copyOfRange(items, i,
                                    items.length), f1Items);
                        } else {
                            this.addLeaf(temp, Arrays.copyOfRange(items, i,
                                    items.length), f1Items);
                        }
                        break;
                    }
                }
            }

        }
        return fpTree;
    }

    /**
     * 3.1 对元素数组根据其在f1中出面的频繁进行排序
     *
     * @param items
     * @return
     */
    public String[] sortItem(String[] items, Item[] f1Items) {

        String[] temp = new String[f1Items.length];
        int i;
        for (String item : items) {
            for (i = 0; i < f1Items.length; i++) {
                if (item.equals(f1Items[i].getValue())) {
                    temp[i] = item;
                }
            }
        }
        List<String> list = new ArrayList<String>();
        int j = 0;
        for (i = 0; i < temp.length; i++) {
            if (temp[i] != null) {
                list.add(temp[i]);
            }
        }

        return list.toArray(new String[0]);
    }

    /**
     * 3.2 给FPTree的节点添加子节点序列
     *
     * @param preItem
     * @param items
     */
    public void addLeaf(Item preItem, String[] items, Item[] f1Items) {
        if (items.length > 0) {
            Item item = new Item(items[0]);
            item.setCounter(1);
            item.setPreItem(preItem);
            preItem.addNextItem(item);

            for (Item i : f1Items) {
                if (i.getValue().equals(items[0])) {
                    Item temp = i;
                    while (temp.getSibling() != null) {
                        temp = temp.getSibling();
                    }
                    temp.setSibling(item);
                    break;
                }
            }
            if (items.length > 1) {
                addLeaf(item, Arrays.copyOfRange(items, 1, items.length),
                        f1Items);
            }
        }

    }

    // 4.生成条件模式基
    public Map<String, List<String>> buildCondBase(Item[] f1Items) {

        Item item = null; // 横向处理时的当前节点
        Item preItem = null; // 横向处理的当前节点对应的纵向节点
        int counter = 0;
        StringBuffer data;

        Map<String, List<String>> condBaseMap = new HashMap<String, List<String>>();
        List<String> conditionBase; // 条件模式基
        // 逆向遍历频繁1项集(但不需处理其第一项)
        for (int i = f1Items.length - 1; i > 0; i--) {

            conditionBase = new ArrayList<String>();
            item = f1Items[i].getSibling();
            while (item != null) { // 横向处理

                counter = item.getCounter();
                preItem = item.getPreItem();
                data = new StringBuffer();
                while (preItem.getValue() != null) { // 纵向处理
                    data.append(preItem.getValue() + " ");
                    preItem = preItem.getPreItem();
                }
                for (int j = 0; j < counter; j++) {
                    if (data.toString().trim() != ""
                            && data.toString().trim().length() > 0) {
                        conditionBase.add(data.toString().trim());
                    }
                }
                item = item.getSibling();
            }
            condBaseMap.put(f1Items[i].getValue(), conditionBase);
        }

        return condBaseMap;
    }

    // 5.生成条件FP树
    public Map<String, Item> buildCondFPTree(
            Map<String, List<String>> condBaseMap) {

        Map<String, Item> condFPTreeMap = new HashMap<String, Item>();
        List<String> condBase;
        Item condFPTree;
        Set<String> items = condBaseMap.keySet();
        for (String item : items) {
            condBase = condBaseMap.get(item);
            condFPTree = this
                    .buildFPTree(condBase, this.buildF1Items(condBase));
            // 删除condFPTree树中节点出现次数少于最小支持度的点
            this.delLTminSup(condFPTree);
            condFPTreeMap.put(item, condFPTree);
        }

        return condFPTreeMap;
    }

    /**
     * 5.1  删除树中节点计数小于最小支持度的节点
     *
     * @param root
     */
    public void delLTminSup(Item root) {
        List<Item> subItems = root.getNextItem();
        if (subItems.size() != 0) {
            for (int i = 0; i < subItems.size(); i++) {
                if (subItems.get(i).getCounter() < this.minSup) {
                    subItems.remove(i);
                } else {
                    delLTminSup(subItems.get(i));
                }
            }
        }
    }

    /**
     * 6.产生频繁模式 根据前面生成的条件FP树,分别产生相应元素相关的频繁模式
     */
    public Map<String,List<List<String>>> fpGrowth(Map<String, Item> condFPTreeMap) {

        List<List<String>> result;
        Map<String, List<List<String>>> resultMap = new HashMap<String, List<List<String>>>();
        Set<String> items = condFPTreeMap.keySet();
        Item condFPTree = null;
        List<String> pathList; // 一个条件fp树中所有的路径
        List<String> stack = new ArrayList<String>();

        for (String item : items) {

            pathList = new ArrayList<String>();
            condFPTree = condFPTreeMap.get(item);
            buildPath(stack, condFPTree, pathList);

            for(String str : pathList){
                result = new ArrayList<List<String>>();
                if(str.trim().length() != 0){
                    String[] temp = str.trim().split(" ");
                    List<String> nodeList = new ArrayList<String>();
                    for(String t : temp){
                        nodeList.add(t);
                    }

                    buildSubSet(nodeList, result);

                    if(resultMap.get(item) == null){
                        resultMap.put(item, result);
                    }else{
                        List<List<String>> list = resultMap.get(item);
                        for( int  i = 0; i < result.size(); i++){
                            list.add(result.get(i));
                        }
                        resultMap.put(item, list);
                    }
                }
            }
        }

        return resultMap;
    }

    // 6.1 生成树的每一条路径
    public void buildPath(List<String> stack, Item root, List<String> pathList) {

        if (root != null) {
            stack.add(root.getValue());
            if (root.getNextItem().size() == 0) {
                changeToPath(stack, pathList); // 把值栈中的值转化为路径
            } else {
                List<Item> items = root.getNextItem();
                for (int i = 0; i < items.size(); i++) {
                    buildPath(stack, items.get(i), pathList);
                }
            }
            stack.remove(stack.size() - 1);
        }
    }

    /**
     * 6.1.1 把值栈中的值转化为路径
     *
     * @param path
     * @param pathList
     */
    public void changeToPath(List<String> path, List<String> pathList) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < path.size(); i++) {
            if (path.get(i) != null) {
                sb.append(path.get(i) + " ");
            }

        }
        pathList.add(sb.toString().trim());

    }
    /**
     * 6.2 生成子集
     * @param sourceSet
     * @param result
     */
    public void buildSubSet(List<String> sourceSet, List<List<String>> result) {

        if (sourceSet.size() == 1) {
            List<String> set = new ArrayList<String>();
            set.add(sourceSet.get(0));
            result.add(set);
        } else if (sourceSet.size() > 1) {

            buildSubSet(sourceSet.subList(0, sourceSet.size() - 1), result);
            int size = result.size();

            List<String> single = new ArrayList<String>();
            single.add(sourceSet.get(sourceSet.size() - 1));
            result.add(single);

            List<String> clone;
            for (int i = 0; i < size; i++) {
                clone = new ArrayList<String>();
                for (String str : result.get(i)) {
                    clone.add(str);
                }
                clone.add(sourceSet.get(sourceSet.size() - 1));

                result.add(clone);
            }
        }
    }
    public void setMinSup(int minSup) {
        this.minSup = minSup;
    }
}

基于FP-Tree的关联规则FP-Growth推荐算法Java实现的更多相关文章

  1. 基于用户的协同过滤的电影推荐算法(tensorflow)

    数据集: https://grouplens.org/datasets/movielens/ ml-latest-small 协同过滤算法理论基础 https://blog.csdn.net/u012 ...

  2. 机器学习-FP Tree

    接着是上一篇的apriori算法: FP Tree数据结构 为了减少I/O次数,FP Tree算法引入了一些数据结构来临时存储数据.这个数据结构包括三部分,如下图所示 第一部分是一个项头表.里面记录了 ...

  3. FP Tree算法原理总结

    在Apriori算法原理总结中,我们对Apriori算法的原理做了总结.作为一个挖掘频繁项集的算法,Apriori算法需要多次扫描数据,I/O是很大的瓶颈.为了解决这个问题,FP Tree算法(也称F ...

  4. 用Spark学习FP Tree算法和PrefixSpan算法

    在FP Tree算法原理总结和PrefixSpan算法原理总结中,我们对FP Tree和PrefixSpan这两种关联算法的原理做了总结,这里就从实践的角度介绍如何使用这两个算法.由于scikit-l ...

  5. FP Tree算法原理总结(转载)

    FP Tree算法原理总结 在Apriori算法原理总结中,我们对Apriori算法的原理做了总结.作为一个挖掘频繁项集的算法,Apriori算法需要多次扫描数据,I/O是很大的瓶颈.为了解决这个问题 ...

  6. 基于storm的在线关联规则

    基于storm的在线视频推荐算法.算法根据youtube的推荐算法  算法相对简单,能够觉得是关联规则仅仅挖掘频繁二项集.以下给出与storm的结合实如今线实时算法 , 关于storm见这里.首先给出 ...

  7. 基于Azure构建PredictionIO和Spark的推荐引擎服务

    基于Azure构建PredictionIO和Spark的推荐引擎服务 1. 在Azure构建Ubuntu 16.04虚拟机 假设前提条件您已有 Azure 帐号,登陆 Azure https://po ...

  8. 【笔记3】用pandas实现矩阵数据格式的推荐算法 (基于用户的协同)

    原书作者使用字典dict实现推荐算法,并且惊叹于18行代码实现了向量的余弦夹角公式. 我用pandas实现相同的公式只要3行. 特别说明:本篇笔记是针对矩阵数据,下篇笔记是针对条目数据. ''' 基于 ...

  9. 美团网基于机器学习方法的POI品类推荐算法

    美团网基于机器学习方法的POI品类推荐算法 前言 在美团商家数据中心(MDC),有超过100w的已校准审核的POI数据(我们一般将商家标示为POI,POI基础信息包括:门店名称.品类.电话.地址.坐标 ...

随机推荐

  1. jquery mobile -role

    jquery mobile -role - cc_jony - 博客园 jquery mobile -role   data-page 页面 data-header 页面的头部 data-conten ...

  2. 初探eXtreme scale

    Note: This document was based on WebSphere Extreme Scale 8.6. It doesn’t supported for lower version ...

  3. awakeFromNib小总结

    awakeFromNib 在使用IB的时候才会涉及到此方法的使用,当.nib文件被载入的时候,会发送一个awakeFromNib的消息到.nib文件里的每一个对象,每一个对象都能够定义自己的awake ...

  4. asp.net微软认证全新考试题库及答案1

    1.你创建了一个ASP.net应用程序,该程序将运行在TK公司的WEB站点上.你的应用程序包括100个WEB页面.你想配置你的应用程序,当HTTP代码发生错误时,可显示自定义的错误信息给用户.同时你想 ...

  5. 关于在打包Jar文件时遇到的资源路径问题(二)

    在关于<关于在打包Jar文件时遇到的资源路径问题(一)>中,以及描述了当资源与可执行JAr分离时的资源路径代码的编写问题,后来想了想,为什么将<Java核心技术卷一>中的程序1 ...

  6. Mysql找回管理员password

    我们使用MYSQL的时候有可能由于种种原因忘记ROOTpassword,假设是那样数据库可能就废掉了.可是今天给大家分享下找回ROOTpassword的方法或者说是在不知道rootpassword的情 ...

  7. 打破“中规中矩”,手机QQ何以萌翻众人?

        随着移动互联网的迅猛发展,越来越多的手机应用展现在了用户面前,不过,面对林林总总的手机应用,有时候我们却提不起兴趣,因为功能的同质化,UI的千篇一律已经让我们多少有些审美疲劳的感觉.     ...

  8. windows线程同步的总结

    一 线程 1)如果你正在编写C/C++代码,决不应该调用CreateThread.相反,应该使用VisualC++运行期库函数_beginthreadex,退出也应该使用_endthreadex.如果 ...

  9. 用Stack实现对多线程的管理范例

    多线程就是并发技术,当线程数量超过一定数量时,系统响应就会变慢,所以就必须对线程数量进行控制,那么采用哪种控制方法呢?采用Stack类模仿堆栈,之所以说是模仿,就是因为Stack类毕竟不是真实的堆栈, ...

  10. 定位vc运行时库问题 依赖问题,屡试不爽的一招

    用vc 菜单 文件| 打开|指定EXE或DLL,如有指定运行时库,则PE文件的资源中可以看到manifest 配置节 然后据此判断EXE依赖的运行时库, 再根据编译选项调整 运行时库设置