Mapreduce -- PageRank
PageRank 简单理解为网页排名,但是网页是根据什么排名的,接下来就简单介绍一下。
举例:
假设网页 A 的内容中有网页 B,C 和 D 的链接,并且 A 的 PageRank的值为0.25。
那接下里我们就可以计算在网页 A 中的其他网页的PageRank的值了。我们拿网页 B 来进行说明,
在网页 A 中的网页 B 的 PageRank 为 0.25 * (1/n) 其中n为网页 A 中网页链接数,结果则为 0.25*(1/3)。
可以简单理解为A的PageRank被B,C 和 D 平分了,B分到了0.25的三分之一。
然后将所有网页中的关于网页B的pagerank值求出来,就是网页B真实的pagerank了。
但是上面的例子没有考虑到如下的特殊情况:
1 网页A中只有指向自己的网页链接。
2 网页A中没有任何链接。
如果出现以上情况,会导致pagerank结果不准确。
所以出现了下面的公式:
result = sum * n + (1-n)/N
sum 为上面计算出来的,如网页B在所有网页中的pagerank值的总和。
n 可以理解为停留在当前网页继续进行网页跳转浏览的概率
1-n 可以理解为不访问当前网页的任何链接,从浏览器的地址栏输入,转去其他网页的概率。
N 为网页的数量
下面介绍通过MapReduce实现PageRank
简单的流程分析:
Map
取一行数据进行说明
A B C D
网页A中有网页B,C,D的链接;
刚开始给网页A一个默认的pagerank值,然后根据这个值计算其他网页链接在网页A中的PageRank。处理后的数据如下:
A 0.25 B C D
B 0.25*(/)
C 0.25*(/)
D 0.25*(/)
Reduce
然后通过 Reduce 计算出各个网页在其他网页中的 PageRank 的总和 sum,然后代入公式计算实际的PageRank,并更新 A 0.25 B C D 中的数据,这里将0.25更新为计算出来真实的 PageRank。
重复计算各个网页的 PageRank 的值,直到 PageRank 的结果收敛,值趋于稳定。
A 0.25 B C D =>A ? B C D
测试数据:
A B C D
B A D
C C
D B C
测试代码:
RunJob.java
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.KeyValueTextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; import java.io.IOException; /**
* Created by Edward on 2016/7/13.
*/
public class RunJob { public static enum ValueEnum{
CLOSURE_VALUE;
} public static void main(String[] args)
{ //access hdfs's user
System.setProperty("HADOOP_USER_NAME","root"); Configuration conf = new Configuration();
conf.set("fs.defaultFS", "hdfs://node1:8020"); try {
int i = 0;
while(true) {
i++;
conf.setInt("count", i); FileSystem fs = FileSystem.get(conf);
Job job = Job.getInstance(conf);
job.setJarByClass(RunJob.class);
job.setMapperClass(MyMapper.class);
job.setReducerClass(MyReducer.class); //需要指定 map out 的 key 和 value
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Text.class); //设置输入类的
job.setInputFormatClass(KeyValueTextInputFormat.class);
if(i==1)
FileInputFormat.addInputPath(job, new Path("/test/pagerank/input"));
else
FileInputFormat.addInputPath(job, new Path("/test/pagerank/output/pr"+(i-1))); Path path = new Path("/test/pagerank/output/pr"+i);
if (fs.exists(path))//如果目录存在,则删除目录
{
fs.delete(path, true);
}
FileOutputFormat.setOutputPath(job, path); boolean b = job.waitForCompletion(true);
if (b) {
long closure =job.getCounters().findCounter(ValueEnum.CLOSURE_VALUE).getValue();
double avg= closure/4000.0;//计算收敛的平均值,浮动小于0.001则认为收敛
System.out.println("执行第"+i+"次, closure="+closure+",avg="+avg);
if(avg < 0.001){
System.out.println("总共执行了"+i+"次,之后收敛");
break;
}
}
} } catch (Exception e) {
e.printStackTrace();
}
} public static class MyMapper extends Mapper<Text, Text, Text, Text> {
@Override
protected void map(Text key, Text value, Context context) throws IOException, InterruptedException {
AdjacentNodes adjacentNodes = new AdjacentNodes();
int count = context.getConfiguration().getInt("count", 1); if(count == 1)
{
AdjacentNodes firstAdj = new AdjacentNodes();
firstAdj.setValue(1.0);
firstAdj.setNodes(value.toString().split("\t"));
adjacentNodes = firstAdj;
}
else
{
//格式化 value: 1.0 B C D
adjacentNodes.formatInfo(value.toString());
}
//A 1.0 B C D
context.write(key, new Text(adjacentNodes.toString())); double pagerank = adjacentNodes.getValue()/adjacentNodes.getNum();
for(int i=0; i<adjacentNodes.getNum(); i++)
{
String node = adjacentNodes.getNodes()[i];
//B 0.333
context.write(new Text(node), new Text(pagerank+""));
}
}
} public static class MyReducer extends Reducer<Text, Text, Text, Text> {
@Override
protected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException { AdjacentNodes adjacentNodes = new AdjacentNodes(); Double sum = 0.0;
for(Text adj : values)
{
String str = adj.toString();
if(str.split("\t").length>1)
{
adjacentNodes.formatInfo(str);
}
else{
sum += Double.parseDouble(str); //对节点的 pagerank 求和,
}
} //计算pagerank
double n = 0.80;
double pagerank = sum * n + (1-n)/4.0;// 计算pagerank 公式 sum * n + (1-n)/N //计算收敛的差值
int closure =(int)(Math.abs(pagerank - adjacentNodes.getValue()) * 1000);
//通过context.getCounter(ENUM)方法,每次执行reduce将closure的值进行累加,结果传递给主函数, context.getCounter(ValueEnum.CLOSURE_VALUE).increment(closure); adjacentNodes.setValue(pagerank);
context.write(key, new Text(adjacentNodes.toString()));
}
}
}
AdjacentNodes.java
/**
* Created by Edward on 2016/7/14.
*/
public class AdjacentNodes { double value = 0.0;
int num = 0;
String[] nodes = null; public void formatInfo(String str)
{
String[] val = str.split("\t");
this.setValue(Double.parseDouble(val[0]));
this.setNum(val.length-1); if(this.num != 0)
this.nodes = new String[this.num]; for(int i=1; i<val.length; i++)
{
this.nodes[i-1] = val[i];
}
} public boolean isEmpty()
{
if(this.num == 0)
return true;
else
return false;
} public void setNodes(String[] nodes) {
this.nodes = nodes;
this.num = nodes.length;
} public void setNum(int num) {
this.num = num;
} public void setValue(double value) {
this.value = value;
} public double getValue() {
return value;
} public int getNum() {
return num;
} public String[] getNodes() {
return nodes;
} @Override
public String toString() { StringBuffer stringBuffer = new StringBuffer(this.value+""); for(int i=0; i<this.num; i++)
{
stringBuffer.append("\t"+this.nodes[i]);
} return stringBuffer.toString();
}
}
结果数据:
A 0.10135294176208584 B C D
B 0.12838069628609527 A D
C 0.6560527651143326 C
D 0.12838069628609527 B C
总共执行了24次,之后收敛;
PageRank值越高,越值得推荐。
Mapreduce -- PageRank的更多相关文章
- Hadoop实战训练————MapReduce实现PageRank算法
		
经过一段时间的学习,对于Hadoop有了一些了解,于是决定用MapReduce实现PageRank算法,以下简称PR 先简单介绍一下PR算法(摘自百度百科:https://baike.baidu.co ...
 - PageRank算法简介及Map-Reduce实现
		
PageRank对网页排名的算法,曾是Google发家致富的法宝.以前虽然有实验过,但理解还是不透彻,这几天又看了一下,这里总结一下PageRank算法的基本原理. 一.什么是pagerank Pag ...
 - mapReduce编程之google pageRank
		
1 pagerank算法介绍 1.1 pagerank的假设 数量假设:每个网页都会给它的链接网页投票,假设这个网页有n个链接,则该网页给每个链接平分投1/n票. 质量假设:一个网页的pagerank ...
 - mapreduce 实现pagerank
		
输入格式: A 1 B,C,D B 1 C,Dmap: B A 1/3 C A 1/3 D A 1/3 A |B,C,D C B 1/2 D B 1/2 B |C,Dreduce: B (1-0.85 ...
 - PageRank算法MapReduce实现
		
如果你现在需要计算网页的排名只有4一:数据如下面的: baidu 10.00 google,sina,nefu google 10.00 baidu sina 10.00 google nefu 10 ...
 - MapReduce实现PageRank算法(邻接矩阵法)
		
前言 之前写过稀疏图的实现方法,这次写用矩阵存储数据的算法实现,只要会矩阵相乘的话,实现这个就很简单了.如果有不懂的可以先看一下下面两篇随笔. MapReduce实现PageRank算法(稀疏图法) ...
 - MapReduce实现PageRank算法(稀疏图法)
		
前言 本文用Python编写代码,并通过hadoop streaming框架运行. 算法思想 下图是一个网络: 考虑转移矩阵是一个很多的稀疏矩阵,我们可以用稀疏矩阵的形式表示,我们把web图中的每一个 ...
 - 【Hadoop学习之十一】MapReduce案例分析三-PageRank
		
环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 hadoop-3.1.1 什么是pagerank?算法原理- ...
 - Google的PageRank及其Map-reduce应用(日志五)
		
上一篇:Hadoop的安装(日志四) 1,算法的原理解释: 如下图所示,G就是传说中的谷歌矩阵,这个矩阵是n*n型号的,n表示共计有n个网页. 如矩阵中所示: 11位置处的元素,是表示第一个网页指向的 ...
 
随机推荐
- Intellij idea Cannot start internal HTTP server.
			
错误提示:Cannot start internal HTTP server. Git integration, JavaScript debugger and LiveEdit may operat ...
 - vue与原生混合开发
			
前段时间,做了一个混合开发的项目,主要是以vue框架开发h5页面,使用cordova作为中间沟通桥梁,实现了h5与安卓.iOS的混合开发,由于从事iOS开发,h5也是刚接触不久,很多深入原理还不太清楚 ...
 - Leetcode题解之Valid Palindrome II
			
1.题目描述 2.问题分析 使用两个下标,检测下标对应的字符是否相等,若不相等,则考察子串. 3.代码 bool validPalindrome(string s) { , j = s.size()- ...
 - [原创]RedHat 安装MySQL数据库
			
朋友购买了阿里云的服务器,服务器上自带有CentOS操作系统,但是开发软件需要自己安装,接下来将介绍本地RedHat Linux 5.10虚拟机上搭建Mysql数据库. 一.软件准备 (1)jdk-6 ...
 - idea 2017破解方法
			
http://blog.csdn.net/zx110503/article/details/78734428
 - [Spark SQL_3] Spark SQL 高级操作
			
0. 说明 DataSet 介绍 && Spark SQL 访问 JSON 文件 && Spark SQL 访问 Parquet 文件 && Spark ...
 - 安装 Scala
			
0. 说明 Scala 安装(Windows) & Scala 安装(Linux) 1. Scala 安装(Windows) 1.0 下载 Scala 下载地址 1.1 运行 Scala ...
 - mysql数据库管理工具(navicat for mysql) 10.1.7 绿色中文版
			
Navicat for MySQL:Navicat for MySQL 是一套专为 MySQL 设计的高性能数据库管理及开发工具.它可以用于任何版本 3.21 或以上的 MySQL 数据库服务器,并支 ...
 - Qt在控件未显示时如何获取正确的控件尺寸
			
因为打算全屏显示一个对话框,而对话框内有几个QLabel的尺寸要在确定QLabel可用的最大尺寸后,再根据内容调整一次,所以在对话框构造函数内就想确定QLabel的最大尺寸,但因为QWidget::u ...
 - [WPF]启动参数
			
在App.xaml.cs中重写方法OnStartup protected override void OnStartup(StartupEventArgs e) { //e.Args为命令行参数 // ...