环境
  虚拟机:VMware 10
  Linux版本:CentOS-6.5-x86_64
  客户端:Xshell4
  FTP:Xftp4
  jdk8
  hadoop-3.1.1

什么是pagerank?
算法原理-1
PageRank是Google提出的算法,用于衡量特定网页相对于搜索引擎索引中的其他网页而言的重要程度。
算法原理:思考超链接在互联网中的作用?
入链 =投票
  PageRank让链接来“投票“,到一个页面的超链接相当于对该页投一票,比如A网页有一个指向B网页的链接,那么B网页就得到A的1个投票。
入链数量
  如果一个页面节点接收到的其他网页指向的入链数量越多,那么这个页面越重要。就是有很多网页指向B网页。
入链质量
  指向页面B的入链质量不同,质量高的页面会通过链接向其他页面传递更多的权重。所以越是质量高的页面指向页面B,则页面B越重要。
  就是考虑指向B网页的源网页自身的入链数量,如果源网页入链很低,那么塔指向B的价值也同样很低。

算法原理-2
初始值
  Google的每个页面设置相同的PR值
  pagerank算法给每个页面的PR初始值为1。
迭代计算(收敛)
  Google不断的重复计算每个页面的PageRank。那么经过不断的重复计算,这些页面的PR值会趋向于稳定,也就是收敛的状态。
  在具体企业应用中怎么样确定收敛标准?
  1、每个页面的PR值和上一次计算的PR相等
  2、设定一个差值指标(0.0001)。当所有页面和上一次计算的PR差值平均小于该标准时,则收敛。
  3、设定一个百分比(99%),当99%的页面和上一次计算的PR相等

算法原理-3
站在互联网的角度:
  只出,不入:PR会为0
  只入,不出:PR会很高
  直接访问网页
修正PageRank计算公式:增加阻尼系数
  在简单公式的基础上增加了阻尼系数(damping factor)d
  一般取值d=0.85。
完整PageRank计算公式


  d:阻尼系数
  M(i):指向i的页面集合
  L(j):页面的出链数
  PR(pj):j页面的PR值
  n:所有页面数

如何设计MR?

PR计算是一个迭代的过程,首先考虑一次计算
思考:
--页面包含超链接
--每次迭代将pr值除以链接数后得到的值传递给所链接的页面
--so:每次迭代都要包含页面链接关系和该页面的pr值
--mr:相同的key为一组的特征
map:
  1,读懂数据:第一次附加初始pr值
  2,映射k:v
    1,传递页面链接关系,key为该页面,value为页面链接关系
    2,计算链接的pr值,key为所链接的页面,value为pr值
reduce:
  *,按页面分组
  1,两类value分别处理
  2,最终合并为一条数据输出:key为页面&新的pr值,value为链接关系

具体数据分析:

A B D
B C
C A B
D B C

第一轮迭代:
map:
  A:BD
  B:1/2
  D:1/2
  A:1/2
reduce:
  A:1/2 B D

第二轮迭代:
map:
  A: 1/2, B D
  B:1/4
  C:1/4
  A:3/4
reduce:
  //A: 1/2, B D
  //A:3/4
  A: 3/4,B,D

package test.mr.pagerank;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
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; public class RunJob { public static enum Mycounter {
my
} public static void main(String[] args) { Configuration conf = new Configuration(true);
//配置:在windows单机运行 从HDFS上读取文件 结果写回HDFS
//异构平台的支撑 会识别操作系统 可以支持Windows 默认false 在Linux上运行
conf.set("mapreduce.app-submission.corss-paltform", "true");
//如果分布式运行,必须打jar包
//这个配置,只属于,切换分布式到本地单进程模拟运行的配置 这种方式不是分布式,所以不用打jar包
conf.set("mapreduce.framework.name", "local"); double d = 0.0000001;
int i = 0;
while (true)
{
i++;
try
{
conf.setInt("runCount", i);
FileSystem fs = FileSystem.get(conf);
Job job = Job.getInstance(conf);
job.setJarByClass(RunJob.class);
job.setJobName("pr" + i);
job.setMapperClass(PageRankMapper.class);
job.setReducerClass(PageRankReducer.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(Text.class); //使用了新的输入格式化类
job.setInputFormatClass(KeyValueTextInputFormat.class); //输入输出路径 上一次的输出作为下一次的输入
Path inputPath = new Path("/root/pagerank/input/");
if (i > 1) {
inputPath = new Path("/root/pagerank/output/pr" + (i - 1));
}
FileInputFormat.addInputPath(job, inputPath);
Path outpath = new Path("/root/pagerank/output/pr" + i);
if (fs.exists(outpath)) {
fs.delete(outpath, true);
}
FileOutputFormat.setOutputPath(job, outpath); boolean f = job.waitForCompletion(true);
if (f) {
System.out.println("success.");
//计数器
long sum = job.getCounters().findCounter(Mycounter.my).getValue();
System.out.println(sum);
double avgd = sum / 4000.0;
if (avgd < d)
{
break;
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
} static class PageRankMapper extends Mapper<Text, Text, Text, Text>
{
protected void map(Text key, Text value, Context context) throws IOException, InterruptedException
{
int runCount = context.getConfiguration().getInt("runCount", 1); //A B D
//K:A
//V:B D
//K:A
//V:0.5 B D
String page = key.toString();
Node node = null;
if (runCount == 1)
{
node = Node.fromMR("1.0" , value.toString());
}
else
{
node = Node.fromMR(value.toString());
}
// A:1.0 B D 传递老的pr值和对应的页面关系
context.write(new Text(page), new Text(node.toString())); if (node.containsAdjacentNodes())
{
double outValue = node.getPageRank() / node.getAdjacentNodeNames().length;
for (int i = 0; i < node.getAdjacentNodeNames().length; i++) {
String outPage = node.getAdjacentNodeNames()[i];
// B:0.5
// D:0.5 页面A投给谁,谁作为key,val是票面值,票面值为:A的pr值除以超链接数量
context.write(new Text(outPage), new Text(outValue + ""));
}
}
}
} static class PageRankReducer extends Reducer<Text, Text, Text, Text>
{
protected void reduce(Text key, Iterable<Text> iterable, Context context)
throws IOException, InterruptedException
{
//相同的key为一组
//key:页面名称比如B
//包含两类数据
//B:1.0 C //页面对应关系及老的pr值
//B:0.5 //投票值
//B:0.5 double sum = 0.0;
Node sourceNode = null;
for (Text i : iterable)
{
Node node = Node.fromMR(i.toString());
if (node.containsAdjacentNodes())
{
sourceNode = node;
}
else
{
sum = sum + node.getPageRank();
}
} // 4为页面总数
double newPR = (0.15 / 4.0) + (0.85 * sum);
System.out.println("*********** new pageRank value is " + newPR); // 把新的pr值和计算之前的pr比较
double d = newPR - sourceNode.getPageRank(); int j = (int) (d * 1000.0);
j = Math.abs(j);
System.out.println(j + "___________");
//将累加值放到计数器里
context.getCounter(Mycounter.my).increment(j); sourceNode.setPageRank(newPR);
context.write(key, new Text(sourceNode.toString()));
}
}
}
package test.mr.pagerank;

import java.io.IOException;
import java.util.Arrays; import org.apache.commons.lang.StringUtils; public class Node { private double pageRank = 1.0;
private String[] adjacentNodeNames; public static final char fieldSeparator = '\t'; public double getPageRank() {
return pageRank;
} public Node setPageRank(double pageRank) {
this.pageRank = pageRank;
return this;
} public String[] getAdjacentNodeNames() {
return adjacentNodeNames;
} public Node setAdjacentNodeNames(String[] adjacentNodeNames) {
this.adjacentNodeNames = adjacentNodeNames;
return this;
} public boolean containsAdjacentNodes() {
return adjacentNodeNames != null && adjacentNodeNames.length > 0;
} @Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(pageRank); if (getAdjacentNodeNames() != null) {
sb.append(fieldSeparator).append(
StringUtils.join(getAdjacentNodeNames(), fieldSeparator));
}
return sb.toString();
} // value =1.0 B D
public static Node fromMR(String value) throws IOException { String[] parts = StringUtils.splitPreserveAllTokens(value,fieldSeparator); if (parts.length < 1) {
throw new IOException("Expected 1 or more parts but received " + parts.length);
} Node node = new Node().setPageRank(Double.valueOf(parts[0]));
if (parts.length > 1) {
node.setAdjacentNodeNames(Arrays.copyOfRange(parts, 1, parts.length));
} return node;
} public static Node fromMR(String v1,String v2) throws IOException {
return fromMR(v1+fieldSeparator+v2);
//1.0 B D
}
}

【Hadoop学习之十一】MapReduce案例分析三-PageRank的更多相关文章

  1. Hadoop学习笔记—20.网站日志分析项目案例(三)统计分析

    网站日志分析项目案例(一)项目介绍:http://www.cnblogs.com/edisonchou/p/4449082.html 网站日志分析项目案例(二)数据清洗:http://www.cnbl ...

  2. Hadoop学习笔记—20.网站日志分析项目案例(一)项目介绍

    网站日志分析项目案例(一)项目介绍:当前页面 网站日志分析项目案例(二)数据清洗:http://www.cnblogs.com/edisonchou/p/4458219.html 网站日志分析项目案例 ...

  3. Hadoop学习笔记—20.网站日志分析项目案例(二)数据清洗

    网站日志分析项目案例(一)项目介绍:http://www.cnblogs.com/edisonchou/p/4449082.html 网站日志分析项目案例(二)数据清洗:当前页面 网站日志分析项目案例 ...

  4. [b0013] Hadoop 版hello word mapreduce wordcount 运行(三)

    目的: 不用任何IDE,直接在linux 下输入代码.调试执行 环境: Linux  Ubuntu Hadoop 2.6.4 相关: [b0012] Hadoop 版hello word mapred ...

  5. MySQL CPU %sys 高的案例分析(三)

    [现象] 最近有台服务器晚上CPU告警,系统抓取的故障期间的snapshot显示CPU %sys较高,同时context switch在300K以上. 是否过高的context switch引起的%s ...

  6. 【Hadoop学习之十二】MapReduce案例分析四-TF-IDF

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 hadoop-3.1.1 概念TF-IDF(term fre ...

  7. 【Hadoop学习之十三】MapReduce案例分析五-ItemCF

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 hadoop-3.1.1 推荐系统——协同过滤(Collab ...

  8. 【Hadoop学习之十】MapReduce案例分析二-好友推荐

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 hadoop-3.1.1 最应该推荐的好友TopN,如何排名 ...

  9. 【Hadoop学习之九】MapReduce案例分析一-天气

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 hadoop-3.1.1 找出每个月气温最高的2天 1949 ...

随机推荐

  1. SQL常用语法大全

    一. Table 增加列 1.增加列:alter table tableName add columnName varchar(30) 1.2. 修改列类型:alter table tableName ...

  2. Python一个文件调用另外一个文件的方法

    from common.Log import MyLog as Log 写法不完善修改为 import common.Log.MyLog as Log 即可

  3. NOIP2009靶形数独

    题目描述: 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教,Z 博士拿出了他最近发明的“ ...

  4. vue.cli项目中src目录每个文件夹和文件的用法

    assets文件夹是放静态资源:components是放组件:router是定义路由相关的配置:view视图:app.vue是一个应用主组件:main.js是入口文件:

  5. win10安装pycharm及汉化包

    PyCharm 是一款功能强大的 Python 编辑器,带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具,那么如何安装pycharm呢?都是英文看不懂有没有汉化版呢?跟ytkah一起 ...

  6. 用A标签实现页面内容定位 点击链接跳到具体位置

    经常在维基百科等网站看到目录列表,点击链接会跳到具体的位置,小美眉一直在问是怎么做到的,其实挺简单的,用A标签实现页面内容定位就行了.实例参考微信营销理论手册的目录. 首先用A标签定义目录的链接. & ...

  7. RadioButton使用

    RadioButton和CheckBox差不多,这里只写一个,因为我本身不是学andorid,所以就当给自己留一个备份,省的每次用到都需要代码敲一次,很麻烦 1.如果想选中时想改变颜色可以设置一个xm ...

  8. ros 运行rviz时出现 QXcbConnection: XCB error: 148 错误 解决方法

    出现上述问题的原因: 1.由于使用了nvc远程控制下位机: 2.rviz是一个基于opengl开发的图形插件,需要使用理论的屏幕参数(thetis' screen),由于使用了teamviewer会导 ...

  9. 20170719 Mysql 配置远端Mysql访问,增加表/存储过程

    -- 1 .在windows 环境中安装Mysql 会按照到默认的C盘当中,如何修改呢--? -- 2. 如何只安装客户端不安装Mysql 数据库服务  --? -- 3. 表的特殊列,默认采用函数值 ...

  10. 一、程序设计与C语言

    @程序:用特殊的编程语言编写的代码,用于表达如何解决问题. @编程语言的作用:编程语言不是用来和计算机交谈的,而是用它来描述要求计算机如何解决问的过程或方法.计算机只能执行(懂得)机器语言. @辗转相 ...