spark---PageRank

下面三篇博客是用mapreduce计算PageRank, 记录有算法的分析。

hadoop2.5.2学习12-MR之PageRank
hadoop2.5.2学习12-MR之PageRank01
hadoop2.5.2学习12-MR之PageRank02

一、mapreduce复习

A B D  ----> 
    A 1.0 B D 
    B 0.5
    D 0.5
===> reduce
    源: A 1.0 B D
    入链
    A 0.3
    A 0.4
    A 0.1
    新的PR = prSum = 0.3 + 0.4 + 0.1
=========>
        //计算出新的PR值
        double q = 0.85;//阻尼系数
        int N = 4;//总页面数
        double newPR = (1-q)/N + q*prSum;
        -->A newPR B D 
    计算收敛
        //对比新旧PR差值,直到数据收敛
        double d = newPR - sourceNode.getPageRank();

    为了统计所有的分组都达到收敛
        需要设置一个全局变量, 用于接收差值
        context.getCounter(MyRunJob.MyCounter.countName).increment(j);

在下次迭代前进行收敛判断
    /**
     * 因为每次的reducer中按照key进行四次计算, 每次计算增加一次j
     * reducer:
     *      context.getCounter(MyRunJob.MyCounter.countName).increment(j);
     * 所以求取平均差值。要除以4*1000.0
     *      在reducer中:int j = (int) (d*1000.0);
     */
    double avgD = sum/4000.0;
    if (avgD < d) {//达到了收敛
        break;
    }

二、Spark—PageRank

流程

源数据:
A   B
B   C
C   A
D   B
A   D
A   B

links   每个页面对应出链的集合
(B, C)
(A, (B,D))

ranks 设置初始rank值 
(B,1.0)
(A,1.0)
(C,1.0)
(D,1.0)


join, 这个是为了下一步计算新的分页面rank
(A, ((B, D), 1.0))


重新计算rank值
mapValues() ===> ((B, D), 1.0)
    计算每个页面的入链
    rank/size

    reduceByKey===>每个页面新的PR
    新的ranks

2.1、处理源数据, 将边关系(A, B),(A, C)合并成对应的映射集合(A, (B, C))

    val links = lines.map( s =>{
            val parts = s.split("\\s+")
            (parts(0), parts(1))
      }
    ).distinct()
     .groupByKey()  //分组, 生成连接表
     .cache()

2.2、在pankrank算法中,设置每个页面的初始PR值

    //设置初始值 (1,1.0) (2,1.0)..
    var ranks = links.mapValues(v => 1.0)

2.3、迭代计算每个页面新的PR

将邻接表和ranks表join, 获取 values (有了出链集合, PR), 用于计算入链的贡献PR值。
    //迭代计算PR值
    for (i <- 1 to iters) {

        // (A,((B,C,D), 1.0))
        val contribs = links.join(ranks)
            .values  //((B,C,D), 1.0)   用于计算入链的贡献PR值。
        .flatMap{ case (urls, rank) =>
            val size = urls.size
            //计算每个页面的入链值
            urls.map(url => (url, rank / size))
        }
        //新的PR值
        ranks = contribs.reduceByKey(_ + _).mapValues(0.15 + 0.85 * _)

    }

scala完整代码

package com.chb.scala

import org.apache.spark.SparkContext._
import org.apache.spark.{SparkConf, SparkContext}

/**
 * Computes the PageRank of URLs from an input file. Input file should
 * be in format of:
 * URL         neighbor URL
 * URL         neighbor URL
 * URL         neighbor URL
 * ...
 * where URL and their neighbors are separated by space(s).
 */
object SparkPageRank {
  def main(args: Array[String]) {
    val sparkConf = new SparkConf().setAppName("PageRank").setMaster("local[1]")
    val iters = 20;  //迭代次数
    val ctx = new SparkContext(sparkConf)
    val lines = ctx.textFile("page.txt")

    //根据边关系数据(A, B)(A, C)...生成 邻接表 如:(A,(B,C,C)) (B,(C,D))..
    val links = lines.map( s =>{
            val parts = s.split("\\s+")
            (parts(0), parts(1))
      }
    ).distinct()
     .groupByKey()  //分组, 生成连接表
     .cache()

    //设置初始值 (1,1.0) (2,1.0)..
    var ranks = links.mapValues(v => 1.0)



    //迭代计算PR值
    for (i <- 1 to iters) {

        // (A,((B,C,D), 1.0))
        val contribs = links.join(ranks)
            .values  //((B,C,D), 1.0)   用于计算入链的贡献PR值。
        .flatMap{ case (urls, rank) =>
            val size = urls.size
            //计算每个页面的入链值
            urls.map(url => (url, rank / size))
        }
        //新的PR值
        ranks = contribs.reduceByKey(_ + _).mapValues(0.15 + 0.85 * _)

    }


    ctx.stop()
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值