MapReduce实现Apriori算法
Apiroi算法在Hadoop MapReduce上的实现
输入格式:
一行为一个Bucket
1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 68 70 72 74
1 3 5 7 9 12 13 15 17 19 21 23 25 27 29 31 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 68 70 72 74
1 3 5 7 9 12 13 16 17 19 21 23 25 27 29 31 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 68 70 72 74
1 3 5 7 9 11 13 15 17 20 21 23 25 27 29 31 34 36 38 40 42 44 47 48 50 52 54 56 58 60 62 64 66 68 70 72 74
1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 34 36 38 40 42 44 46 48 51 52 54 56 58 60 62 64 66 68 70 72 74
1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 34 36 38 40 42 44 46 48 51 52 54 56 58 60 63 64 66 68 70 72 74
1 3 5 7 9 11 13 15 17 20 21 23 25 27 29 31 34 36 38 40 42 44 47 48 51 52 54 56 58 60 62 64 66 68 70 72 74
1 3 5 7 9 12 13 15 17 19 21 24 25 27 29 31 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 68 70 72 74
1 3 5 7 9 11 13 15 17 19 21 24 25 27 29 31 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 65 66 68 70 72 74
1 3 5 7 9 11 13 16 17 19 21 24 25 27 29 31 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 68 70 72 74
1 3 5 7 9 12 13 16 17 19 21 24 25 27 29 31 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 68 70 72 74
1 3 5 7 9 11 13 15 17 20 21 24 25 27 29 31 34 36 38 40 42 44 47 48 50 52 54 56 58 60 62 64 66 68 70 72 74
1 3 5 7 9 11 13 15 17 20 21 24 25 27 29 31 34 36 38 40 42 44 47 48 50 52 54 56 58 60 62 65 66 68 70 72 74
1 3 5 7 9 11 13 15 17 20 21 24 25 27 29 31 34 36 38 40 43 44 47 48 50 52 54 56 58 60 62 65 66 68 70 72 74
输出格式:
<item1,item2,...itemK, frequency>
25 2860
29 3181
3 2839
34 3040
36 3099
40 3170
48 3013
5 2971
52 3185
56 3021
代码:
package apriori; import java.io.IOException;
import java.util.Iterator;
import java.util.StringTokenizer;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Map;
import java.util.HashMap;
import java.io.*; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Mapper.Context;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.mapreduce.lib.jobcontrol.JobControl;
import org.apache.hadoop.mapreduce.lib.jobcontrol.ControlledJob;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner; class AprioriPass1Mapper extends Mapper<Object,Text,Text,IntWritable>{
private final static IntWritable one = new IntWritable(1);
private Text number = new Text(); //第一次pass的Mapper只要把每个item映射为1
public void map(Object key,Text value,Context context) throws IOException,InterruptedException{ String[] ids = value.toString().split("[\\s\\t]+");
for(int i = 0;i < ids.length;i++){
context.write(new Text(ids[i]),one);
}
}
} class AprioriReducer extends Reducer<Text,IntWritable,Text,IntWritable>{
private IntWritable result = new IntWritable(); //所有Pass的job共用一个reducer,即统计一种itemset的个数,并筛选除大于s的
public void reduce(Text key,Iterable<IntWritable> values,Context context) throws IOException,InterruptedException{
int sum = 0; int minSup = context.getConfiguration().getInt("minSup",5);
for(IntWritable val : values){
sum += val.get();
}
result.set(sum); if(sum > minSup){
context.write(key,result);
}
}
} class AprioriPassKMapper extends Mapper<Object,Text,Text,IntWritable>{
private final static IntWritable one = new IntWritable(1);
private Text item = new Text(); private List< List<Integer> > prevItemsets = new ArrayList< List<Integer> >();
private List< List<Integer> > candidateItemsets = new ArrayList< List<Integer> >();
private Map<String,Boolean> candidateItemsetsMap = new HashMap<String,Boolean>(); //第一个以后的pass使用该Mapper,在map函数执行前会执行setup来从k-1次pass的输出中构建候选itemsets,对应于apriori算法
@Override
public void setup(Context context) throws IOException, InterruptedException{
int passNum = context.getConfiguration().getInt("passNum",2);
String prefix = context.getConfiguration().get("hdfsOutputDirPrefix","");
String lastPass1 = context.getConfiguration().get("fs.default.name") + "/user/hadoop/chess-" + (passNum - 1) + "/part-r-00000";
String lastPass = context.getConfiguration().get("fs.default.name") + prefix + (passNum - 1) + "/part-r-00000"; try{
Path path = new Path(lastPass);
FileSystem fs = FileSystem.get(context.getConfiguration());
BufferedReader fis = new BufferedReader(new InputStreamReader(fs.open(path)));
String line = null; while((line = fis.readLine()) != null){ List<Integer> itemset = new ArrayList<Integer>(); String itemsStr = line.split("[\\s\\t]+")[0];
for(String itemStr : itemsStr.split(",")){
itemset.add(Integer.parseInt(itemStr));
} prevItemsets.add(itemset);
}
}catch (Exception e){
e.printStackTrace();
} //get candidate itemsets from the prev itemsets
candidateItemsets = getCandidateItemsets(prevItemsets,passNum - 1);
} public void map(Object key,Text value,Context context) throws IOException,InterruptedException{
String[] ids = value.toString().split("[\\s\\t]+"); List<Integer> itemset = new ArrayList<Integer>();
for(String id : ids){
itemset.add(Integer.parseInt(id));
} //遍历所有候选集合
for(List<Integer> candidateItemset : candidateItemsets){
//如果输入的一行中包含该候选集合,则映射1,这样来统计候选集合被包括的次数
//子集合,消耗掉了大部分时间
if(contains(candidateItemset,itemset)){
String outputKey = "";
for(int i = 0;i < candidateItemset.size();i++){
outputKey += candidateItemset.get(i) + ",";
}
outputKey = outputKey.substring(0,outputKey.length() - 1);
context.write(new Text(outputKey),one);
}
}
} //返回items是否是allItems的子集
private boolean contains(List<Integer> items,List<Integer> allItems){ int i = 0;
int j = 0;
while(i < items.size() && j < allItems.size()){
if(allItems.get(j) > items.get(i)){
return false;
}else if(allItems.get(j) == items.get(i)){
j++;
i++;
}else{
j++;
}
} if(i != items.size()){
return false;
}
return true;
} //获取所有候选集合,参考apriori算法
private List< List<Integer> > getCandidateItemsets(List< List<Integer> > prevItemsets, int passNum){ List< List<Integer> > candidateItemsets = new ArrayList<List<Integer> >(); //上次pass的输出中选取连个itemset构造大小为k + 1的候选集合
for(int i = 0;i < prevItemsets.size();i++){
for(int j = i + 1;j < prevItemsets.size();j++){
List<Integer> outerItems = prevItemsets.get(i);
List<Integer> innerItems = prevItemsets.get(j); List<Integer> newItems = null;
if(passNum == 1){
newItems = new ArrayList<Integer>();
newItems.add(outerItems.get(0));
newItems.add(innerItems.get(0));
}
else{
int nDifferent = 0;
int index = -1;
for(int k = 0; k < passNum && nDifferent < 2;k++){
if(!innerItems.contains(outerItems.get(k))){
nDifferent++;
index = k;
}
} if(nDifferent == 1){
//System.out.println("inner " + innerItems + " outer : " + outerItems);
newItems = new ArrayList<Integer>();
newItems.addAll(innerItems);
newItems.add(outerItems.get(index));
}
}
if(newItems == null){continue;} Collections.sort(newItems); //候选集合必须满足所有的子集都在上次pass的输出中,调用isCandidate进行检测,通过后加入到候选子集和列表
if(isCandidate(newItems,prevItemsets) && !candidateItemsets.contains(newItems)){
candidateItemsets.add(newItems);
//System.out.println(newItems);
}
}
} return candidateItemsets;
} private boolean isCandidate(List<Integer> newItems,List< List<Integer> > prevItemsets){ List<List<Integer>> subsets = getSubsets(newItems); for(List<Integer> subset : subsets){
if(!prevItemsets.contains(subset)){
return false;
}
} return true;
} private List<List<Integer>> getSubsets(List<Integer> items){ List<List<Integer>> subsets = new ArrayList<List<Integer>>();
for(int i = 0;i < items.size();i++){
List<Integer> subset = new ArrayList<Integer>(items);
subset.remove(i);
subsets.add(subset);
} return subsets;
}
} public class Apriori extends Configured implements Tool{ public static int s;
public static int k; public int run(String[] args)throws IOException,InterruptedException,ClassNotFoundException{
long startTime = System.currentTimeMillis(); String hdfsInputDir = args[0]; //从参数1中读取输入数据
String hdfsOutputDirPrefix = args[1]; //参数2为输出数据前缀,和第pass次组成输出目录
s = Integer.parseInt(args[2]); //阈值
k = Integer.parseInt(args[3]); //k次pass //循环执行K次pass
for(int pass = 1; pass <= k;pass++){
long passStartTime = System.currentTimeMillis(); //配置执行该job
if(!runPassKMRJob(hdfsInputDir,hdfsOutputDirPrefix,pass)){
return -1;
} long passEndTime = System.currentTimeMillis();
System.out.println("pass " + pass + " time : " + (passEndTime - passStartTime));
} long endTime = System.currentTimeMillis();
System.out.println("total time : " + (endTime - startTime)); return 0;
} private static boolean runPassKMRJob(String hdfsInputDir,String hdfsOutputDirPrefix,int passNum)
throws IOException,InterruptedException,ClassNotFoundException{ Configuration passNumMRConf = new Configuration();
passNumMRConf.setInt("passNum",passNum);
passNumMRConf.set("hdfsOutputDirPrefix",hdfsOutputDirPrefix);
passNumMRConf.setInt("minSup",s); Job passNumMRJob = new Job(passNumMRConf,"" + passNum);
passNumMRJob.setJarByClass(Apriori.class);
if(passNum == 1){
//第一次pass的Mapper类特殊对待,不许要构造候选itemsets
passNumMRJob.setMapperClass(AprioriPass1Mapper.class);
}
else{
//第一次之后的pass的Mapper类特殊对待,不许要构造候选itemsets
passNumMRJob.setMapperClass(AprioriPassKMapper.class);
}
passNumMRJob.setReducerClass(AprioriReducer.class);
passNumMRJob.setOutputKeyClass(Text.class);
passNumMRJob.setOutputValueClass(IntWritable.class); FileInputFormat.addInputPath(passNumMRJob,new Path(hdfsInputDir));
FileOutputFormat.setOutputPath(passNumMRJob,new Path(hdfsOutputDirPrefix + passNum)); return passNumMRJob.waitForCompletion(true);
} public static void main(String[] args) throws Exception{
int exitCode = ToolRunner.run(new Apriori(),args);
System.exit(exitCode);
}
}
MapReduce实现Apriori算法的更多相关文章
- 利用Apriori算法对交通路况的研究
首先简单描述一下Apriori算法:Apriori算法分为频繁项集的产生和规则的产生. Apriori算法频繁项集的产生: 令ck为候选k-项集的集合,而Fk为频繁k-项集的集合. 1.首先通过单遍扫 ...
- #研发解决方案#基于Apriori算法的Nginx+Lua+ELK异常流量拦截方案
郑昀 基于杨海波的设计文档 创建于2015/8/13 最后更新于2015/8/25 关键词:异常流量.rate limiting.Nginx.Apriori.频繁项集.先验算法.Lua.ELK 本文档 ...
- 基于Apriori算法的Nginx+Lua+ELK异常流量拦截方案 郑昀 基于杨海波的设计文档(转)
郑昀 基于杨海波的设计文档 创建于2015/8/13 最后更新于2015/8/25 关键词:异常流量.rate limiting.Nginx.Apriori.频繁项集.先验算法.Lua.ELK 本文档 ...
- 基于Hadoop的改进Apriori算法
一.Apriori算法性质 性质一: 候选的k元组集合Ck中,任意k-1个项组成的集合都来自于Lk. 性质二: 若k维数据项目集X={i1,i2,-,ik}中至少存在一个j∈X,使得|L(k-1)(j ...
- 海量数据挖掘MMDS week2: 频繁项集挖掘 Apriori算法的改进:非hash方法
http://blog.csdn.net/pipisorry/article/details/48914067 海量数据挖掘Mining Massive Datasets(MMDs) -Jure Le ...
- Apriori算法的原理与python 实现。
前言:这是一个老故事, 但每次看总是能从中想到点什么.在一家超市里,有一个有趣的现象:尿布和啤酒赫然摆在一起出售.但是这个奇怪的举措却使尿布和啤酒的销量双双增加了.这不是一个笑话,而是发生在美国沃尔玛 ...
- 数据挖掘算法(四)Apriori算法
参考文献: 关联分析之Apriori算法
- 机器学习实战 - 读书笔记(11) - 使用Apriori算法进行关联分析
前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习心得,这次是第11章 - 使用Apriori算法进行关联分析. 基本概念 关联分析(associat ...
- 关联规则挖掘之apriori算法
前言: 众所周知,关联规则挖掘是数据挖掘中重要的一部分,如著名的啤酒和尿布的问题.今天要学习的是经典的关联规则挖掘算法--Apriori算法 一.算法的基本原理 由k项频繁集去导出k+1项频繁集. 二 ...
随机推荐
- Tomcat不停机部署项目
- Qt信号槽第5个参数
1.Qt::AutoConnection: 默认值,使用这个值则连接类型会在信号发送时决定.如果接收者和发送者在同一个线程,则自动使用Qt::DirectConnection类型.如果接收者和发送者不 ...
- easyUI combobox使用方法总结
combobox,中文叫复合框,是把文本框和列表框的特性结合起来的一种控件,这个控件,既可以输入文字,也可以像列表框一样选择选项 Combobox用法和方法参数: 1. 需要引入class=" ...
- Redis 错误:Failed with result 'start-limit-hit'
Redis 错误:Failed with result 'start-limit-hit' 背景 Redis 版本为 5.0.4: 文件 /etc/systemd/system/redis.servi ...
- abap 增强查找小程序
*&---------------------------------------------------------------------* *& Report ZEXIT *& ...
- scipy插值与拟合
原文链接:https://zhuanlan.zhihu.com/p/28149195 1.最小二乘拟合 实例1 import numpy as np import matplotlib.pyplot ...
- Laravel Not Found Exceptions 取数据的一个小技巧
从 model 中取数据的时候, 用下面的方法, 而不是简单的 find(1), 或 first(), 这样如果刚好要查询的数据没有, 就会返回比较友好的 404 页面: $model = App\F ...
- aop(execution()表达式)
execution(* com.tp.soft.service..*.*(..)) 整个表达式可以分为五个部分: 1.execution(): 表达式主体. 2.第一个*号:表示返回类型,*号表示所有 ...
- y
switch(update_state) { : switch(num){ : window.progressn=num $('#h_progress_bar .ui-progress').anima ...
- 第 10 章 容器监控 - 080 - Weave Scope 容器地图
Weave Scope 容器地图 Weave Scope 的最大特点是会自动生成一张 Docker 容器地图,让我们能够直观地理解.监控和控制容器. 安装 执行如下脚本安装运行 Weave Scope ...