编程环境:

Ubuntu16.4 uklin

Hadoop3.2.0

openjdk version "1.8.0_191"

spark 2.3.0 ( 集群环境 )

完整代码已经更新至GitHub,欢迎fork~GitHub链接

声明:创作不易,未经授权不得复制转载

statement:No reprinting without authorization

一、算法思想介绍:

PageRank的核心思想其实十分简单,概括如下:

1、如果一个网页被很多其它网页链接到,说明这个网页很重要,它的PageRank值也会相应较高;

2、如果一个PageRank值很高的网页链接到另外某个网页,那么那个网页的PageRank值也会相应地提高。

使用随机浏览模型的PageRank公式:

image.png

也可将(1-d)换为(1-d/N)N为总网页数

二、hadoop上利用mapreduce框架实现pagerank算法:

1、设计思路:

源数据格式为起始网页+\t+用逗号,分割的起始网页所连接指向的其它网页列表,eg:A B,D,F......

所以考虑首先读入一遍全体数据,先初始化每个网页的权重为1.0,并在往后的每一次迭代中更新这个记录每个网页权重pr值,每次将上一轮更新后的pr值表传给下一次迭代计算新的pr值。

具体在map时将每一行源数据拆分,首先读取到A的pr值,而后统计A后一共的出链数目num,将A指向的每个网页名作为一个key,value设为pr/num,表示A对该网页的贡献量,如上例中的一行数据经 过mapper后将得到的是:、、......

而后在reducer端接受到的将是同一个key为网页,value是其它所有网页对它pr值贡献量的值列表,eg:>,所以reducer要做的便是利用公式将列表中值相加得到sum值,而后将sum乘以权重d再加上(1-d)便得到更新后的网页B的pr值:

image.png

2、难点

如何设计一个共享的变量来保存所有网页的pr值:

查询后发现hadoop对数据传递和共享变量没有什么特别好的接口,主要是因为hadoop是基于分布式的节点计算,要想实现数据共享传递主要是依赖对文件的操作,以及自带的Configuration中设置属性值,考虑到频繁的文件io操作带来的低效性,我采用了后一种方法:

//初始化configuration后,使用

conf.set("propertyName“,properyValue);

//在mapper或reducer中,

Configuration conf = context.getConfiguration();

String g = conf.get("propertyName");

补充其它方式:

image.png

而后在每一次迭代前,先读取上一次迭代的输出文件(part-r-00000), 将网页的pr值封装进一个String的字符串中,用“,”进行分割,用lastWeights保存,用在mapper中读取到后进行计算即可,不需要考虑到在每个reducer节点进行遍历更新(会很慢),转换为一次的文件io操作即可,极大增加了运行效率。

三、具体迭代实现的mapper和reducer的代码:

Mapper:

public static class pageMapper extends Mapper{

private static Text keyInfo = new Text();

private static DoubleWritable valueInfo = new DoubleWritable();

private static String[] lastWeightsInfo;

@Override

protected void setup(Context context)

throws IOException, InterruptedException {

try {

//从全局配置获取配置参数

Configuration conf = context.getConfiguration();

lastWeightsInfo = conf.get("lastWeights").split(","); //这样就拿到了

} catch (Exception e) {

e.printStackTrace();

}

}

@Override

protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {

//分离邻接链表

String[] line = value.toString().split("\t");

if(line.length==2){

String curPageName = line[0];

String[] outPages = line[1].split(",");

double outNum = outPages.length;

double ww = 0.0;

for(int i = 0;i

if(curPageName.equals(lastWeightsInfo[i])){

ww = Double.valueOf(lastWeightsInfo[i+1].toString())/outNum;

break;

}

}

for (int i=0;i

keyInfo.set(outPages[i]);

valueInfo.set(ww);

context.write(keyInfo,valueInfo);

}

}

}

}

Reducer:

public static class pageReducer extends Reducer{

private static DoubleWritable info = new DoubleWritable();

//private static int totalNum;

/* @Override

protected void setup(Context context)

throws IOException, InterruptedException {

try {

//从全局配置获取配置参数

Configuration conf = context.getConfiguration();

//totalNum = conf.getInt("totalNum", 0);

} catch (Exception e) {

e.printStackTrace();

}

} */

@Override

protected void reduce(Text key, Iterable values, Context context) throws IOException, InterruptedException {

double sum = 0.0;// 统计PR

for (DoubleWritable value : values) {

sum += value.get();

}

sum = 0.85*sum + 0.15;

info.set(sum);

context.write(key, info);

}

}

四、实现标准输出:

标准输出如下:

(recovered_factory,1.3220451459)

(AbboT,1.3123762223)

(Abbess,1.2992692277)

(Martin_Scorsese,1.2820462602)

(Asteropaeus,1.2775443371)

(Best_Adapted_Screenplay,1.2755708599)

(For_Your_Consideration,1.2743701080)

(Whittaker_Chambers,1.2633760889)

(capitalism,1.2620055989)

方案:

额外增加设置一次jop,单独设计mapper和reducer,将每个网页的pr值设定为key,按照降序传递到reducer端,并保留十位小数进行输出,主要利用的是重写比较器WritableComparator:

public static class IntWritableDecreasingComparator extends IntWritable.Comparator {

public int compare(WritableComparable a, WritableComparable b) {

return -super.compare(a, b);

}

public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {

return -super.compare(b1, s1, l1, b2, s2, l2);

}

}

新的Mapper和Reduder:

public static class pageOutMapper extends Mapper{

private static DoubleWritable keyInfo = new DoubleWritable();

private static Text valueInfo = new Text();

@Override

protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {

//super.map(key, value, context);

//若A能连接到B,则说明B是A的一条出链

if(!value.toString().equals("")){

String[] line = value.toString().split("\t");

String curPageName = line[0];

double pr = Double.valueOf(line[1]);

DecimalFormat df = new DecimalFormat("0.0000000000");

String Prvalue = df.format(pr);

String vout = "("+curPageName+","+Prvalue+")";

valueInfo.set(vout);

keyInfo.set(pr);

context.write(keyInfo, valueInfo);

}

}

}

public static class pageOutReducer extends Reducer{

private static Text info = new Text();

@Override

protected void reduce(DoubleWritable key, Iterable values, Context context) throws IOException, InterruptedException {

for(Text value:values){

info.set(value.toString());

context.write(NullWritable.get(),info);

}

}

}

五、在spark上完成pagerank

spark下的scala编程简单很多,直接在集群上的spark-shell上几行代码就可以搞定:

image.png

六、实验代码设计漏洞:

1、:在邻接链表右边未出现过的,左边出现,会出现异常,输出少一个page

2、:没有进行检查链接到自己的网页筛选

还可以进一步优化。

pagerank算法c语言,在hadoop的map-reduce框架下实现经典的pagerank算法相关推荐

  1. 深度学习框架下群组行为识别算法综述

    源自:电子学报       作者:邓海刚  王传旭  李成伟  林晓萌 摘 要 群组行为识别目前是计算机视觉领域的一个研究热点,在智能安防监控.社会角色理解和体育运动视频分析等方面具有广泛的应用价值. ...

  2. python 最优化算法库_哈工大硕士生用?Python 实现了 11 种经典数据降维算法,源代码库已开放...

    雷锋网 AI 开发者按:网上关于各种降维算法的资料参差不齐,同时大部分不提供源代码.这里有个 GitHub 项目整理了使用 Python 实现了 11 种经典的数据抽取(数据降维)算法,包括:PCA. ...

  3. 激光振镜误差校正算法C语言,动态聚焦激光振镜扫描系统的误差分析及图形校正算法.pdf...

    动态聚焦激光振镜扫描系统的误差分析及图形校正算法.pdf 份态象金激疙非在镜扫描系统份钱差令祈怠⑤荷乡镇正算法 文世峰,史玉升,谢 军 (华中科技大学材料学院塑性成形模拟及模具技术国家重点实验室,湖北 ...

  4. 卫星跟踪算法c语言,以SoC FPGA为设计平台的北斗卫星信号跟踪算法的设计

    0 引言 全球导航卫星系统(Global Navigaon Satellite System,GNSS)是维护国家安全.发展经济的重要基础设施,是体现国家综合国力以及现代化大国国际影响力的重要标志 . ...

  5. [ZZ]Map/Reduce hadoop 细节

    转自:Venus神庙原文:http://www.cnblogs.com/duguguiyu/archive/2009/02/28/1400278.html 分布式计算(Map/Reduce) 分布式计 ...

  6. MapReduce框架下的FP Growth算法详解

    转载自:http://blog.sina.com.cn/s/blog_68ffc7a40100uebk.html Sharding 这一步没什么好讲的,将数据库分成连续的大小相等的几个块,放置在不同的 ...

  7. Hadoop Map/Reduce教程

    Hadoop Map/Reduce教程 目的     先决条件     概述     输入与输出     例子:WordCount v1.0         源代码         用法        ...

  8. 一步一步跟我学习hadoop(5)----hadoop Map/Reduce教程(2)

    Map/Reduce用户界面 本节为用户採用框架要面对的各个环节提供了具体的描写叙述,旨在与帮助用户对实现.配置和调优进行具体的设置.然而,开发时候还是要相应着API进行相关操作. 首先我们须要了解M ...

  9. C语言包含字母的2D面板中搜索给定的单词的算法(附完整源码)

    C语言包含字母的2D面板中搜索给定的单词的算法 C语言包含字母的2D面板中搜索给定的单词的算法完整源码(定义,实现,main函数测试) C语言包含字母的2D面板中搜索给定的单词的算法完整源码(定义,实 ...

最新文章

  1. Github Pages页面重定向到新网址,实现域名跳转
  2. leetcode算法题--两两交换链表中的节点★
  3. 暗杀TIME-WAIT
  4. 财税、管理知识,离您那么远吗?
  5. :批量制作档案表,要从excel表格中将每个人的数据导入到docx档案
  6. HDU1754 —— I Hate It 线段树 单点修改及区间最大值
  7. Python urllib爬取百度首页
  8. linux 实现秒级定时任务
  9. Jmeter压力测试简单教程(包括服务器状态监控)
  10. 设置IIS指向另一台机器上的共享目录(动易sw)遇到的问题
  11. 《刷新》精髓:微软第三任CEO萨提亚•纳德拉重新发现微软灵魂的传奇历程,给了我们普通人哪些启示?
  12. B站狂神说JavaWeb学习笔记
  13. YY工作总结—为人处事
  14. python 报 KeyError: ('coupon_type', 'occurred at index act_code')故障
  15. 产业区块链的“道”与“术”:区块链技术的价值解读
  16. 第45期:动态规划-背包问题
  17. 二维数组实现n阶方阵
  18. 舒米,又夺冠了。。。。。
  19. 10 直线方程—— 一般式、 参数式、向量式、点向式(标准式)、两点式,直线方程互换
  20. Pandas 学习笔记

热门文章

  1. 关于使用map,for等遍历数组获取其中每一项的值在调用接口只取到最后一个值的问题
  2. elasticsearch bulk数据--ES批量导入json数据
  3. Python django 个人博客系统源码
  4. 北京第三家面试录音总结
  5. 孜然导航系统V2.5.5_站长导航系统源码_网址导航源码
  6. 局域网断网攻击 (arp攻击)
  7. QT下使用QCamera录像和保存功能
  8. 电力缴费系统-台区同期线损管理系统_系统结构图_ER图_数据字典
  9. Java制作计算器实现加减乘除
  10. SpringBoot后端统计网站的IP访问次数及地区