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的更多相关文章

  1. Hadoop实战训练————MapReduce实现PageRank算法

    经过一段时间的学习,对于Hadoop有了一些了解,于是决定用MapReduce实现PageRank算法,以下简称PR 先简单介绍一下PR算法(摘自百度百科:https://baike.baidu.co ...

  2. PageRank算法简介及Map-Reduce实现

    PageRank对网页排名的算法,曾是Google发家致富的法宝.以前虽然有实验过,但理解还是不透彻,这几天又看了一下,这里总结一下PageRank算法的基本原理. 一.什么是pagerank Pag ...

  3. mapReduce编程之google pageRank

    1 pagerank算法介绍 1.1 pagerank的假设 数量假设:每个网页都会给它的链接网页投票,假设这个网页有n个链接,则该网页给每个链接平分投1/n票. 质量假设:一个网页的pagerank ...

  4. 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 ...

  5. PageRank算法MapReduce实现

    如果你现在需要计算网页的排名只有4一:数据如下面的: baidu 10.00 google,sina,nefu google 10.00 baidu sina 10.00 google nefu 10 ...

  6. MapReduce实现PageRank算法(邻接矩阵法)

    前言 之前写过稀疏图的实现方法,这次写用矩阵存储数据的算法实现,只要会矩阵相乘的话,实现这个就很简单了.如果有不懂的可以先看一下下面两篇随笔. MapReduce实现PageRank算法(稀疏图法) ...

  7. MapReduce实现PageRank算法(稀疏图法)

    前言 本文用Python编写代码,并通过hadoop streaming框架运行. 算法思想 下图是一个网络: 考虑转移矩阵是一个很多的稀疏矩阵,我们可以用稀疏矩阵的形式表示,我们把web图中的每一个 ...

  8. 【Hadoop学习之十一】MapReduce案例分析三-PageRank

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 hadoop-3.1.1 什么是pagerank?算法原理- ...

  9. Google的PageRank及其Map-reduce应用(日志五)

    上一篇:Hadoop的安装(日志四) 1,算法的原理解释: 如下图所示,G就是传说中的谷歌矩阵,这个矩阵是n*n型号的,n表示共计有n个网页. 如矩阵中所示: 11位置处的元素,是表示第一个网页指向的 ...

随机推荐

  1. <Android 基础(三十三)> TabHost ~ 仿微信底部菜单

    简介 Container for a tabbed window view. This object holds two children: a set of tab labels that the ...

  2. Maven学习(五)使用Maven构建多模块项目

    使用Maven构建多模块项目 一般的web项目构成: 建立解决方案目录parent 首先使用命令进入到我们需要建立maven项目的目录: mvn archetype:generate -DgroupI ...

  3. 如何获取listview里面的edittext或者RadioGroup的值,涉及到引发的混乱现象

    最近要实现从数据库读数据,该数据对应listview的item布局里面的RadioButton值,并且item布局里面还有EditText的控件. 如何将每一条对应的listview对应值获取出来呢? ...

  4. JAVA 实现 QQ 邮箱发送验证码功能(不局限于框架)

    JAVA 实现 QQ 邮箱发送验证码功能(不局限于框架) 本来想实现 QQ 登录,有域名一直没用过,还得备案,好麻烦,只能过几天再更新啦. 先把实现的发送邮箱验证码更能更新了. 老规矩,更多内容在注释 ...

  5. 《ECMAScript6标准入门》第三版--读书笔记

    2015年6月,ECMAScript 6正式通过,成为国际标准.尽管在目前的工作中还没有使用ES6,但是每项新技术出来总是忍不住想尝尝鲜,想知道ES6能为前端开发带来哪些变化?对自己的工作有哪些方面可 ...

  6. WebAPI返回时间数据不带T

    最近一段时间项目里面使用WebAPI比较多,但是在返回时间数据的时候回默认带上T,就像这样子 "2016-04-21T13:26:17.4701811+08:00", 这样的数据在 ...

  7. 另开一篇 https

    https 流程 1.加密传输:对称加密传输信息 2.身份认证:非对称加密.通过证书来保障客户端给服务器的密钥唯一性. 因为中间层要是伪装公钥和证书,但是又无法解密原有的发送的数据,那么发给服务器的数 ...

  8. 把php session 会话保存到redis

    php的session会话默认时以文件形式保存在php.ini配置文件设置的会话缓存目录,文件保存会话的效率很低,每当每个用户登录一次就会在服务器上生成一个唯一的session_id文件,当用户登录量 ...

  9. Scala学习之路 (十)Scala的Actor

    一.Scala中的并发编程 1.Java中的并发编程 ①Java中的并发编程基本上满足了事件之间相互独立,但是事件能够同时发生的场景的需要. ②Java中的并发编程是基于共享数据和加锁的一种机制,即会 ...

  10. C#启动另一个应用程序并传参数

    第一个程序: try { ProcessStartInfo startInfo = new ProcessStartInfo(); startInfo.FileName = "Windows ...