pageCount hadoop 实现

1.实现pagerank

1.1定义收敛标准

1.2每次算出新的pr-oldpr=差值,所有页面的差值累加,除以pagecount,得到avg差值,如果。小于0.01

1.2、计算总页面数,并且算出每个页面的初始pr值=1/pagecount

1.3  A0.25BD-----A0.35BD---A0.29BD----

 

 

2.了解PageRank算法

2.1什么是pageRank

–PageRank是Google专有的算法,用于衡量特定网页相对于搜索引擎索引中的其他网页而言的重要程度。

–是Google创始人拉里·佩奇和谢尔盖·布林于1997年创造的

–PageRank实现了将链接价值概念作为排名因素。

 

2.2 计算环境

–Hadoop-2.5.2

–四台主机

–两台NN的HA

–两台RM的HA

–离线计算框架MapReduce

 

2.3算法原理

–入链====投票

•PageRank让链接来“投票“,到一个页面的超链接相当于对该页投一票。

–入链数量

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

–入链质量

•指向页面A的入链质量不同,质量高的页面会通过链接向其他页面传递更多的权重。所以越是质量高的页面指向页面A,则页面A越重要。

 

2.4网络上各个页面的连接图

 

算法原理2

–初始值

•每个页面设置相同的PR值

•Google的pagerank算法给每个页面的PR初始值为1。

–迭代递归计算(收敛)

•Google不断的重复计算每个页面的PageRank。那么经过不断的重复计算,这些页面的PR值会趋向于稳定,也就是收敛的状态。

•在具体企业应用中怎么样确定收敛标准?

–1、每个页面的PR值和上一次计算的PR相等

–2、设定一个差值指标(0.0001)。当所有页面和上一次计算的PR差值平均小于该标准时,则收敛。

–3、设定一个百分比(99%),当99%的页面和上一次计算的PR相等

 

算法原理3

修正PageRank计算公式

•由于存在一些出链为0,也就是那些不链接任何其他网页的网,也称为孤立网页,使得很多网页能被访问到。因此需要对PageRank公式进行修正,即在简单公式的基础上增加了阻尼系数(damping factor)q,q一般取值q=0.85。

–完整PageRank计算公式

 

 

3.hadoop源码分析

 

 

 

package pagerank;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.KeyValueTextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;

/**
 * Created by root on 2017/1/8 0008.
 */
public class JobPageRank {

    public enum DifferenceCounter{
        DIFFERENCE_COUNTER
    }
    /**
     *
     1、定义收敛标准
     每次算出新的pr-oldpr=差值 ,所有页面的差值累加 ,除以pagecount,得到avg差值 ,如果。小于0.01
     2、计算总页面数,并且算出每个页面的初始pr值=1/pagecount
     3、
     A  0.25 B  D ----- A  0.35 B D--- A  0.29 B D----
     */
    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
        Configuration conf = new Configuration();
        conf.set("fs.defaultFS","hdfs://node1:8020");
        conf.set("yarn.resourcemanager.hostname","node1");

        double d = 0.001;
        int i = 0;
        while(true){
           i++;
            // 记录计算的次数
            conf.setInt("runCount", i);
            Job job = Job.getInstance(conf);
            job.setJarByClass(JobPageRank.class);
            job.setJobName("jobName"+i);

            job.setMapOutputKeyClass(Text.class);
            job.setMapOutputValueClass(Text.class);

            job.setMapperClass(PageRankMapper.class);
            job.setReducerClass(PageRankReducer.class);


            job.setInputFormatClass(KeyValueTextInputFormat.class);

            Path inputPath = new Path("/input/pagerank.txt");
            if(i >1){                                               //2
                inputPath = new Path("/output/pr"+(i-1));     //1
            }
            FileInputFormat.setInputPaths(job,inputPath);

            Path outPath = new Path("/output/pr"+i);
            FileSystem fs = FileSystem.get(conf);
            if(fs.exists(outPath)){
                fs.delete(outPath,true);
            }
            FileOutputFormat.setOutputPath(job,outPath);
            boolean flag = job.waitForCompletion(true);

            if(flag){

                //从自定义的计数器中获取所有页面前后的总差值
                double  sum = job.getCounters().findCounter(DifferenceCounter.DIFFERENCE_COUNTER).getValue();
                //总差值除以页面数再缩小1000倍。
                double avg = sum/4000;
                System.out.println("success ---- "+i+"avg"+avg );
                if(avg<d){
                    break;
                }
            }
        }
    }
}

  

package pagerank;

import org.apache.commons.lang.StringUtils;

import java.io.IOException;
import java.util.Arrays;

/**
 * Created by root on 2017/1/8 0008.
 * function : convert the string to node: 1.0 b c d
 * a b c
 * a 1.0 b c
 *
 */
public class Node {

    private double pageRank;

    //相邻节点
    private String[] adjecentNodes;

    //分割符号
    private static final char FIELD_SEPARATE='\t';

    public double getPageRank(){
        return this.pageRank;
    }

    public Node setPageRank(double pageRank){
        this.pageRank = pageRank;
        return this;
    }

    public String[] getAdjecentNodes(){
        return this.adjecentNodes;
    }

    public Node setAdjecentNodeName(String[] adjecentNodes){
        this.adjecentNodes = adjecentNodes;
        return this;
    }

    public boolean contanisAdjecentNodes() {
        return  (adjecentNodes != null && adjecentNodes.length >0);
    }

    @Override
    public String toString(){
        // value =1.0 B D
        StringBuilder sb = new StringBuilder();
        sb.append(this.pageRank);
        if(this.contanisAdjecentNodes()){
           sb.append(FIELD_SEPARATE).append(
                   StringUtils.join(this.getAdjecentNodes(),FIELD_SEPARATE));

        }
        return sb.toString();
    }
    //value = 1.0 b c d
    public static Node fromRM(String value) throws IOException {
        String[] parts= StringUtils.splitPreserveAllTokens(value,FIELD_SEPARATE);
        if(parts.length<1){
            throw new IOException("Expected 1 or more parts but received " + parts.length);
        }
        Node node = new Node().setPageRank(Double.parseDouble(parts[0]));
        if(parts.length>1){
            node.setAdjecentNodeName(Arrays.copyOfRange(parts,1,parts.length));
        }
        return node;
    }
}

  

package pagerank;

import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

import java.io.IOException;

/**
 * Created by root on 2017/1/8 0008.
 */
public class PageRankMapper extends Mapper<Text,Text,Text,Text> {

    @Override
    public void map(Text key,Text value,Context context) throws
            IOException, InterruptedException{
        int runCount = context.getConfiguration().getInt("runCount", 1);
        // A	B	D
        String page = key.toString();
        Node node = new Node();
        if(runCount ==1){
            node =  Node.fromRM("1.0" + "\t"+ value.toString());
        }else{
            node =   Node.fromRM(value.toString());
        }
        context.write(new Text(key),new Text(node.toString()));
        System.out.println("key"+key+"   "+"node:"+node.toString());

        if(node.contanisAdjecentNodes()){
            double outValue = node.getPageRank()/node.getAdjecentNodes().length;
             for(String adjNode:node.getAdjecentNodes()){
                context.write(new Text(adjNode),new Text(outValue+""));
                 System.out.println("adjNode"+adjNode+"   "+"outValue:"+outValue);
             }
        }
    }
}

  

package pagerank;

import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

import java.io.IOException;

/**
 * Created by root on 2017/1/8 0008.
 */
public class PageRankReducer extends Reducer<Text,Text,Text,Text> {


    @Override
    //	A:1.0 B D  ---> key: value(sourceNode)
    //	D:0.5 node
    public void reduce(Text key ,Iterable<Text> value,Context context) throws IOException, InterruptedException {
        double sum = 0.0;
        Node sourceNode = new Node();
        for(Text text: value) {
            Node node = Node.fromRM(text.toString());
            // 计算前的数据 // A:1.0 B D
            if (node.contanisAdjecentNodes()) {
                sourceNode = node;
            } else {
                sum = sum + node.getPageRank();
            }
        }
            //计算新的页面的PR值
            double newPR = (0.15 / 4.0) + (0.85 * sum);
            System.out.println("key"+ key+":"+newPR);
            System.out.println("*********** new pageRank value is " + newPR);

            double oldPR = sourceNode.getPageRank();

            // 把新的pr值和计算之前的pr比较
            int d =(int)(Math.abs(newPR -oldPR)*1000);
            System.out.println(d + "___________");

            // 将每一个页面的差值存入自定义的计数器中
            context.getCounter(JobPageRank.DifferenceCounter.DIFFERENCE_COUNTER).increment(d);
            sourceNode.setPageRank(newPR);
            context.write(key,new Text(sourceNode.toString()));



    }
}

  

 

posted @ 2017-01-09 00:14  瓦肯船长  阅读(158)  评论(0)    收藏  举报