算法分析:http://ikeycn.iteye.com/blog/700740
算法实现:
/**
* FPGrowth算法的主要思想:
* 1. 构造频繁1项集:遍历初始数据集构造频繁1项集,并作为项头表,建立将指向fpTree节点对应元素的引用
* 2. 构造FPTree:再次遍历初始数据集,对于每一条事务中的元素,根据频繁1项集中元素的顺序排序,
* 由此建立FPTree,记录每条事务的节点在同一条路径上出再的节点次数;
* 3. 逆序遍历在步骤1中构造的项头表,根据其提供的引用指针,找出fpTree中由该节点到根节点的路径,
* 即生成每个频繁元素的条件模式基
* 4. 根据每个频繁元素对应的条件模式基,生成其对应的条件fpTree,并删除树中节点记数不满足给定的最小支持度的节点
* 5. 对于每一颗条件fpTree,生成所有的从根节点到叶子节点的路径,由路径中的集合生成其所有非空子集
* 所有这些非空子集和每一个频繁1项集中的元素共同构成了原始数据集中的频繁集
*
*/
package com.ustc.fpGrowth;
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 com.ustc.fpGrowth;
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;
}
}
分享到:
相关推荐
本文将通过图解的方式深入解析FPGrowth算法的原理和实现过程。 **二、关联规则挖掘** 关联规则挖掘是数据挖掘的一个重要分支,其目的是发现数据库中项集之间的有趣关系,如“购买尿布的顾客也经常购买啤酒”。FP...
《FPGrowth算法详解与代码实现》 在数据挖掘领域,关联规则学习是一种探索数据中项集之间有趣关系的重要方法。其中,FPGrowth(Frequent Pattern Growth)算法因其高效性和内存效率,成为了关联规则挖掘中的热门...
本文将深入探讨FP-growth算法的原理、Python实现以及如何在实际数据集中应用。 **FP-growth算法原理** FP-growth算法由Hineman和Han在2000年提出,其核心思想是避免了传统Apriori算法的多次扫描数据库,通过构建一...
总之,Python中的FPGrowth算法实现为数据挖掘者提供了便利,使得在Python环境中进行大规模关联规则学习成为可能。通过理解和应用这些工具,我们可以更有效地从数据中提取有价值的信息,为决策提供依据。在实际项目中...
在这个场景中,我们关注的是C语言实现的FP-growth算法。C语言以其高效性和灵活性,成为实现这种算法的理想选择,尤其是在处理大数据量时。 首先,我们要了解FP-growth的基本原理。它是由Han、Pei和Jia在2000年提出...
总的来说,这个压缩包提供了一个全面的FP-growth算法实现,涵盖了C++、C#和MATLAB三种不同的编程环境,适合于不同背景和需求的开发者或研究者。通过这些源代码,学习者可以深入理解FP-growth算法的细节,同时也可以...
下面将详细介绍FP Growth算法的基本原理、Python实现的关键点以及如何下载和运行提供的源码。 **FP Growth算法介绍** FP Growth算法的核心思想是通过构建一个前缀树(FP树)结构,然后通过这个树结构来避免对数据...
在提供的文件中,`www.pudn.com.txt`可能包含了数据集,而`fpgrowth`可能是一个源代码文件,实现了FP-Growth算法。阅读和理解这个源代码,可以深入学习如何在实际项目中应用C++实现的FP-Growth算法。 **应用场景** ...
接着,"算法源码的讲解"部分将带你了解FP_Growth算法的具体实现。算法主要包括两个主要步骤:首先,通过一次遍历交易数据构建FP_tree;然后,从树中递归地挖掘频繁项集。这个过程可以通过剪枝操作进一步减少计算量,...
包含两个文件,一个是刚构造好FP-tree的代码,另一个是FP-Growth算法python实现的完全代码。更多的介绍请见博客:http://blog.csdn.net/bone_ace/article/details/46746727
在提供的压缩包文件`fpgrowth`中,很可能包含了FP-Growth算法的实现代码,这可能是用Python、Java或其他编程语言编写的。代码通常会包括上述步骤的函数或类,如`build_fp_tree`、`mine_frequent_patterns`和`...
C++是广泛应用的编程语言,能够提供高效的性能,因此C++实现FP-Growth算法具有很高的实用价值。 FP-Growth的核心思想是通过构建一个FP树(Frequent Pattern tree)来存储频繁项集,并利用这个树结构来挖掘出所有的...
本文将深入探讨FPGrowth算法的原理,并详细介绍其在Java编程语言中的具体实现。 一、FPGrowth算法简介 FPGrowth算法的核心思想是通过构建FP树(Frequent Pattern Tree)来避免对所有可能的项集进行全集扫描,从而...
综上所述,这个压缩包很可能包含了一个使用C#编写的FP Growth算法实现,这个实现可能是为了在JavaScript(jQuery)环境下使用,例如在Web应用中进行数据分析或者推荐系统。用户可能需要解压文件,阅读源代码,理解...
在提供的Python实现`fp-growth-0.1.3`中,可能包含了FP-growth算法的Python代码库,用于在实际项目中进行关联规则挖掘。这个库通常会提供函数,如`fp_growth`,用于构建FP树、挖掘频繁项集以及生成关联规则。用户...
**FPGrowth算法原理:** `FPGrowth`(Frequent Pattern Growth)算法由Hao Chen和Jiawei Han等人于2000年提出,它的主要创新在于避免了频繁项集生成过程中大量的候选集生成和测试,从而提高了效率。`FPGrowth`通过...
一个简单的fpgrwoth的实现,一个简单的fpgrwoth的实现,
FPGrowth 算法的 Java 实现 用法 创建一个 jar 并运行它: git clone git@github.com:relekang/fpgrowth.git && cd fpgrowth mvn assembly:assembly java -jar target/FPGrowth-jar-with-dependencies.jar < path>...