apriori算法是最基本的发现频繁项集的算法,它的名字也体现了它的思想——先验,采用逐层搜索迭代的方法,挖掘任何可能的项集,k项集用于挖掘k+1项集。
先验性质
频繁项集的所有非空子集也一定是频繁的
该性质体现了项集挖掘中的反单调性,如果k项集不是频繁的,那么k+1项集一定也不是。基于这一点,算法的基本思想为:
step 1:连接
为了搜索k项集,将k-1项集自连接产生候选的k项集,称为候选集。
为了有效的实现连接,首先对每一项进行排序。其次,若满足连接的条件,则进行连接。
连接的条件,前k-2项相同,k-1项不同
step 2:剪枝
k项集的每一个k-1项子集都存在与k-1项集,并且支持度满足最小支持度阀值。
伪代码:
C:candidata itemset of size k
L:frequent itemset of size k
L<1>=frequent items
for(k=1;L!=null;k++)
C=candidates generated from L
for transaction t in dataset
increment the count of all candidates in C that are contained in t L=candidates in C with support>=min_support
return Java代码实现方式:
抽象了一个项集实体类,并实现是否可以合并的方法,这个方法最初是使用TreeSet.headSet来实现的,但是在测试时发现性能瓶颈都产生在这个方法上,并造成OOM,很是费解,待研究清楚后总结一下。
/**
*
*/
package org.waitingfortime.datamining.association;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
/**
* @author mazhiyuan
*
*/
public class Apriori {
private int minNum;// 最小支持数
private List> records;
private String output;
private List> result = new ArrayList>();
public Apriori(double minDegree, String input, String output) {
this.output = output;
init(input);
if (records.size() == 0) {
System.err.println("不符合计算条件。退出!");
System.exit(1);
}
minNum = (int) (minDegree * records.size());
}
private void init(String path) {
// TODO Auto-generated method stub
records = new ArrayList>();
try {
BufferedReader br = new BufferedReader(new FileReader(
new File(path)));
String line = null;
Set record;
while ((line = br.readLine()) != null) {
if (!"".equals(line.trim())) {
record = new TreeSet();
String[] items = line.split(" ");
for (String item : items) {
record.add(Integer.valueOf(item));
}
records.add(record);
}
}
br.close();
} catch (IOException e) {
System.err.println("读取事务文件失败。");
}
}
private List first() {
// TODO Auto-generated method stub
List first = new ArrayList();
Map _first = new HashMap();
for (Set si : records)
for (Integer i : si) {
if (_first.get(i) == null)
_first.put(i, 1);
else
_first.put(i, _first.get(i) + 1);
}
for (Integer i : _first.keySet())
if (_first.get(i) >= minNum)
first.add(new ItemSet(i, _first.get(i)));
return first;
}
private void loop(List items) { <