hadoop2.5.2学习12-MR之PageRank

来源:互联网 发布:plsql导出数据库dmp 编辑:程序博客网 时间:2024/06/05 05:23

一、PageRank是什么

  PageRank的Page可是认为是网页,表示网页排名,也可以认为是Larry Page(google 产品经理),因为他是这个算法的发明者之一,还是google CEO(^_^)。PageRank算法计算每一个网页的PageRank值,然后根据这个值的大小对网页的重要性进行排序。它的思想是模拟一个悠闲的上网者,上网者首先随机选择一个网页打开,然后在这个网页上呆了几分钟后,跳转到该网页所指向的链接,这样无所事事、漫无目的地在网页上跳来跳去,PageRank就是估计这个悠闲的上网者分布在各个网页上的概率

二、PageRank原理

入链==投票

  PageRank让链接来进行”投票”, 到一个页面的超链接相当于对该页面投一票

入链的数量

  果一个页面节点接收到其他页面指向的入链越多,那么这个页面越重要

入链的质量

  指向A页面的入链质量不同,质量越高的页面指向A, 会传递更高的权重,如在董事会中, 核心董事成员可能一票相当于10票, 核心董事成员的一票肯定比普通董事成员一票更重要。
PageRank算法刚开始赋予每个网页相同的重要性得分,通过迭代递归计算来更新每个页面节点的PageRank得分,直到得分稳定为止

网络上的各个页面的链接图

这里写图片描述
PageRank的计算步骤:

  1)在初始阶段:网页通过链接关系构建起链接图,每个页面设置相同的PageRank值,通过若干轮的计算,会得到每个页面所获得的最终PageRank值。随着每一轮的计算进行,网页当前的PageRank值会不断得到更新。

  2)在一轮中更新页面PageRank得分的计算方法:在一轮更新页面PageRank得分的计算中,每个页面将其当前的PageRank值平均分配到本页面包含的出链上,这样每个链接即获得了相应的权值。而每个页面将所有指向本页面的入链所传入的权值求和,即可得到新的PageRank得分。当每个页面都获得了更新后的PageRank值,就完成了一轮PageRank计算。
这里写图片描述

PageRank的收敛

这里写图片描述

这里写图片描述

三、算法实现

原始数据为:

当前节点      出链节点1  出链节点2 A   B   D

通过迭代计算每个节点的PR值

A   0.9    B      D

3.1、设置节点对象,

每个节点包含内容:

  • PR值
  • 出链的节点

所以创建一个节点类,具有的属性:

    //每个页面的出事pr值为1.0    private double pageRank=1.0;    //该节点的出链指向的节点    private String[] adjacentNodeNames;

我们为了使用数据输出格式化, 创建一个分割符

    //各个节点的分隔符    public static final char fieldSeparator = '\t';

重写头String(), 打印Node的节点信息, 输出成一个字符串
每个节点打印信息:PageRank值 出链节点1 出链节点2 …

    @Override    public String toString() {//每个节点打印信息:PageRank值       出链节点1      出链节点2   ...        StringBuilder sb = new StringBuilder();        sb.append(pageRank);        if (getAdjacentNodeNames() != null) {            sb.append(fieldSeparator)            .append(StringUtils                    .join(getAdjacentNodeNames(), fieldSeparator));        }        return sb.toString();    }

同时提供一个方法,通过PR值,及出链节点,将字符串信息恢复成一个Node对象。
给定的字符串:PR值 出链节点1 出链节点

    /**     * @param value  给定一个字符串  value =1.0    B   D      * @return      将这个字符串1封装成Node对象。     */    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;    }

节点的完整类Node:

package com.chb.pagerank;import java.io.IOException;import java.util.Arrays;import org.apache.commons.lang.StringUtils;public class Node {    //每个页面的出事pr值为1.0    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() {//每个节点打印信息:PageRank值       出链节点1      出链节点2   ...        StringBuilder sb = new StringBuilder();        sb.append(pageRank);        if (getAdjacentNodeNames() != null) {            sb.append(fieldSeparator)            .append(StringUtils                    .join(getAdjacentNodeNames(), fieldSeparator));        }        return sb.toString();    }    /**     * @param value  给定一个字符串  value =1.0    B   D      * @return      将这个字符串1封装成Node对象。     */    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;    }}
0 0