【Hadoop学习之十一】MapReduce案例分析三-PageRank
环境
虚拟机: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的更多相关文章
- Hadoop学习笔记—20.网站日志分析项目案例(三)统计分析
网站日志分析项目案例(一)项目介绍:http://www.cnblogs.com/edisonchou/p/4449082.html 网站日志分析项目案例(二)数据清洗:http://www.cnbl ...
- Hadoop学习笔记—20.网站日志分析项目案例(一)项目介绍
网站日志分析项目案例(一)项目介绍:当前页面 网站日志分析项目案例(二)数据清洗:http://www.cnblogs.com/edisonchou/p/4458219.html 网站日志分析项目案例 ...
- Hadoop学习笔记—20.网站日志分析项目案例(二)数据清洗
网站日志分析项目案例(一)项目介绍:http://www.cnblogs.com/edisonchou/p/4449082.html 网站日志分析项目案例(二)数据清洗:当前页面 网站日志分析项目案例 ...
- [b0013] Hadoop 版hello word mapreduce wordcount 运行(三)
目的: 不用任何IDE,直接在linux 下输入代码.调试执行 环境: Linux Ubuntu Hadoop 2.6.4 相关: [b0012] Hadoop 版hello word mapred ...
- MySQL CPU %sys 高的案例分析(三)
[现象] 最近有台服务器晚上CPU告警,系统抓取的故障期间的snapshot显示CPU %sys较高,同时context switch在300K以上. 是否过高的context switch引起的%s ...
- 【Hadoop学习之十二】MapReduce案例分析四-TF-IDF
环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 hadoop-3.1.1 概念TF-IDF(term fre ...
- 【Hadoop学习之十三】MapReduce案例分析五-ItemCF
环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 hadoop-3.1.1 推荐系统——协同过滤(Collab ...
- 【Hadoop学习之十】MapReduce案例分析二-好友推荐
环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 hadoop-3.1.1 最应该推荐的好友TopN,如何排名 ...
- 【Hadoop学习之九】MapReduce案例分析一-天气
环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 hadoop-3.1.1 找出每个月气温最高的2天 1949 ...
随机推荐
- 2017-2018-2 20165336 实验四《Android开发基础》实验报告
20165336 实验四 Android程序设计 一.实验报告封面 课程:Java程序设计 班级:1653班 姓名:康志强 学号:20165336 指导教师:娄嘉鹏 实验日期:2018年5月14日 实 ...
- 去除html
/// <summary> /// 将HTML去除 /// </summary> /// <param name="Htmlstring">&l ...
- InnoDB Next-Key Lock
InnoDB有三种行锁的算法: 1,Record Lock:单个行记录上的锁 2,Gap Lock:间隙锁,锁定一个范围,但不包括记录本身 3,Next-Key Lock:Record Lock + ...
- 下载pywinauto
1.下载pywinauto 链接:http://pywinauto.github.io/ 2.将安装包放到D:python36\script,进入pywinauto目录,按shift+右键,进入命令窗 ...
- w97常用功能代码
1,onclick中添加日期控件 2,onpicked事件即是点击控件后触发的事件 3,dp.cal.getNewDateStr()即是点击到的日期字符串 <script> functio ...
- resful规范
1.简介 什么是resful resful是一个规范,说白了就是面向资源编程,把网络中所有的东西,想象成资源 2.规范 10条规范 1)API与用户的通信协议,总是用HTTPS协议:HTTPS比htt ...
- box-shadow outline 实现双边框 阴影
文字阴影 text-shadow box-shadow 格式:text-shadow:x y blur color, … 参数 x 横向偏移 y 纵向偏移 blur ...
- Java通过jxl读取Excel
package com.hd.all.test.testjava; import java.io.File; import java.io.IOException; import java.util. ...
- 块结构在文件中的表示IOB【转载】
转自:http://www.coderjie.com/blog/43b3601e0a2411e7841d00163e0c0e36 1.块在内存中以树的形式存储,分好块的文本在文件中用IOB标记存储: ...
- js抽红包分配
将 50000元随机分给10个人,其中3个人必须分到百位数,4个人分到千位数,3个人分到万位数,每个人所得金额 <!DOCTYPE html> <html lang="zh ...