【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 ...
随机推荐
- TensorFlow环境
vps cenots7自带的python2.7各种毛病,浪费了不少时间,装了pyhton3一下就搞定了 mac上有些依赖库需要sudo安装 vps上是基于Anaconda搭建的,感谢极客学院的教程ht ...
- linux之无公网ip的自动登录
场景 对于有公网ip的链接方式我们都比较清楚了,但是有些服务器不允许直接登录或者没有直接登录的公网ip,所以只能通过一个可以直接登录的堡垒机跳转.这时需要你手动去敲ssh远程链接命令(例如:ssh r ...
- win10下切换多个jdk版本
1.每次切换时,修改JAVA_HOME变量 2.编辑path环境变量,如图所示,将%JAVA_HOME%\jre\bin和%JAVA_HOME%\bin移到最上边 3.在控制面板中打开java控制面板 ...
- C# 解构
我们以前用ref或者out在一定程度上可以解决方法只有一个返回值的问题.在C#7.0中新增了一个新元组(ValueTuple),他可以让我们返回多个值.话不多说,先上代码: 我们可以看到可以用隐式推断 ...
- 【Python全栈-后端开发】嵩天老师-Django
嵩天老师-Python云端系统开发入门教程(Django) 视频地址:https://www.bilibili.com/video/av19801429 课前知识储备: 一.课程介绍: 分久必合.合久 ...
- python3安装ipython 过程以及问题
由于需要再python3的环境下运行demo,因此安装了python3的ipython notebook,过程如下: sudo pip3 install ipython[all]这样就安装了pytho ...
- linux 查看系统负载:uptime
uptime命令用于查看系统负载,跟 w 命令的输出内容一致 [root@mysql ~]# uptime :: up days, :, user, load average: 1.12, 0.97, ...
- 前端 CSS 三种引入方式
CSS三种引入方式 行内样式 内接样式 外部样式 链接式 导入式 行内样式 就是在标签加上style属性设置样式 <!DOCTYPE html> <html lang="e ...
- Laravel创建产品-CRUD之Create and Store
上一篇说了laravel用crud之index列出产品items,我们现在试着添加产品,用到CRUD的 Create 和 Store 方法,打开/app/Http/Controllers/ItemCo ...
- laravel用crud之index列出产品items
前面我们说了laravel用crud修改产品items-新建resource controller和routing,现在我们要把产品items罗列出来,需要修改路由和模板,一起随ytakh来看看把 1 ...