【大數據】MapReduce 編程-- PageRank--網頁排名算法,用于衡量網頁“重要性”-排序網頁

PageRank 是 Google 創始人拉里·佩奇(Larry Page)和謝爾蓋·布林(Sergey Brin)在 1998 年提出的一種網頁排名算法,用于衡量網頁“重要性”的一種方式。它是搜索引擎中用于排序網頁的一種基礎算法

一個網頁越是被其他重要網頁鏈接,它就越重要

PageRank 的計算流程

  1. 初始化:假設總共 N 個網頁,每個網頁初始 PR 值為 1/N。

  2. 迭代計算:通過 MapReduce 不斷迭代更新 PR 值,直到值趨于穩定。

  3. 結果輸出:PR 值越大,說明該網頁越重要,排名越靠前



A 0.25 B C D
B 0.25 A D
C 0.25 C
D 0.25 B C
  • 第一列:網頁編號(如 A)

  • 第二列:初始 PageRank 值(例如 0.25)

  • 后續列:該網頁鏈接到的其他網頁

迭代的計算PageRank值,每次MapReduce 的輸出要和輸入的格式是一樣的,這樣才能使得Mapreduce 的輸出用來作為下一輪MapReduce 的輸入


Map過程

解析輸入行,提取:

  • 當前網頁 ID

  • 當前網頁的 PR 值

  • 當前網頁鏈接的其他網頁列表

計算出要鏈接到的其他網友的個數,然后求出當前網頁對其他網頁的貢獻值。

第一種輸出的< key ,value>中的key?表示其他網頁,value?表示當前網頁對其他網頁的貢獻值

為了區別這兩種輸出

出鏈網頁貢獻值(標記為 @):<出鏈網頁, @貢獻值>

第二種輸出的< key ,value>中的key?表示當前網頁,value?表示所有其他網頁。

網頁鏈接列表(標記為 &):<當前網頁, &鏈接網頁列表>
?

B @0.0833
C @0.0833
D @0.0833
A &B C D

import java.io.IOException;
import java.util.StringTokenizer;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;/*map過程*/
public class MyMapper extends Mapper<Object,Text,Text,Text>{        private String id;private float pr;       private int count;private float average_pr;       public void map(Object key,Text value,Context context)throws IOException,InterruptedException{            StringTokenizer str = new StringTokenizer(value.toString());//對value進行解析id =str.nextToken();//id為解析的第一個詞,代表當前網頁pr = Float.parseFloat(str.nextToken());//pr為解析的第二個詞,轉換為float類型,代表PageRank值count = str.countTokens();//count為剩余詞的個數,代表當前網頁的出鏈網頁個數average_pr = pr/count;//求出當前網頁對出鏈網頁的貢獻值String linkids ="&";//下面是輸出的兩類,分別有'@'和'&'區分while(str.hasMoreTokens()){String linkid = str.nextToken();context.write(new Text(linkid),new Text("@"+average_pr));//輸出的是<出鏈網頁,獲得的貢獻值>linkids +=" "+ linkid;}       context.write(new Text(id), new Text(linkids));//輸出的是<當前網頁,所有出鏈網頁>}       
}

輸入數據格式(value):網頁ID ?PageRank值 ?出鏈網頁1 ?出鏈網頁2 ...

輸出鍵值對:

  1. <出鏈網頁ID, "@貢獻值">(表示這個網頁從別的網頁獲得了多少貢獻)

  2. <當前網頁ID, "& 出鏈網頁列表">(保留網頁結構)

String id; ? ? ? ? // 當前網頁ID
float pr; ? ? ? ? ?// 當前網頁的PageRank值
int count; ? ? ? ? // 出鏈網頁的數量
float average_pr; ?// 當前網頁對每個出鏈網頁的平均貢獻值
StringTokenizer str = new StringTokenizer(value.toString());是把整行字符串(比如 "A 1.0 B C D")按照空格分割成一個個小單元(token)

id = str.nextToken(); ?// 第一個token是當前網頁ID------取出第一個單詞(比如 A),表示當前正在處理的網頁 ID,賦值給 id

pr = Float.parseFloat(str.nextToken()); ? // 第二個token是當前網頁的PageRank值
取出第二個單詞(比如 "1.0"),將其轉為 float 類型,就是當前網頁的 PageRank 值,賦值給 pr

count = str.countTokens();// 剩下的token是出鏈網頁數量----統計剩余 token 的數量
average_pr = pr / count; //把當前網頁的 PageRank 值平均分配給所有它鏈接的網頁

貢獻值輸出:

while(str.hasMoreTokens()) {String linkid = str.nextToken(); // B, 然后 C, 然后 Dcontext.write(new Text(linkid), new Text("@" + average_pr));linkids += linkid + " "; // 把 B、C、D 加入 linkids 中
}

str.hasMoreTokens()?只要還有未讀取的 token(即還有出鏈網頁沒處理完),就繼續執行循環體

網頁結構輸出(帶 & 開頭):

String linkids記錄當前網頁的所有出鏈網頁 ID?

context.write(new Text(id), new Text(linkids));


Shuffle 是指 Map 階段輸出的數據按照 key 進行分組,并將具有相同 key 的數據發送到同一個 Reduce 任務中處理的過程?

每個網頁 Map 階段都會:

  • 向它出鏈的網頁發 PageRank 貢獻(加@前綴)

  • 自己保留一份出鏈結構

Shuffle 階段:按網頁ID歸并聚合

  • 對 Map 輸出的 key(網頁 ID)進行排序

  • 將相同 key 的所有 value 合并成一個列表

Reducer 接收到的格式為:<網頁ID, [貢獻值, 出鏈結構]>

<網頁ID, 列表[@貢獻1, @貢獻2, ..., &出鏈結構]>


Reduce過程

  • 求每個網頁的新 PageRank 值

  • 保留該網頁的出鏈結構

  • 輸出格式為網頁ID 新的PR值 出鏈網頁列表

shuffule的輸出也即是reduce的輸入。

reduce輸入的key?直接作為輸出的key

reduce輸入的value?進行解析,它是一個列表

a.若列表里的值里包含`@`,就把該值`@`后面的字符串轉化成`float`型加起來

b.若列表里的值里包含`&`,就把該值`&`后面的字符串提取出來

c.把所有貢獻值的加總,和提取的字符串進行連接,作為`reduce`的輸出`value`

public class MyReducer extends Reducer<Text,Text,Text,Text>{

繼承 Hadoop 提供的 Reducer 類,泛型參數說明:

  • Text, Text:輸入的 key 和 value 類型

  • Text, Text:輸出的 key 和 value 類型

public void reduce(Text key, Iterable<Text> values, Context context)
? ? ? ? throws IOException, InterruptedException {
為每一個網頁 key 傳入一個 values 列表,里面是 Shuffle 過程收集到的所有值

import java.io.IOException;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;/*** Reduce過程:計算每個網頁的新PageRank值,并保留出鏈網頁結構。* 輸入:<網頁ID, [@貢獻值, @貢獻值, ..., &出鏈網頁列表]>* 輸出:<網頁ID, 新PageRank值 + 出鏈網頁列表>*/
public class MyReducer extends Reducer<Text, Text, Text, Text> {public void reduce(Text key, Iterable<Text> values, Context context)throws IOException, InterruptedException {String lianjie = ""; // 用于保存當前網頁的出鏈網頁列表(結構信息)float pr = 0;        // 用于累加當前網頁從其他網頁獲得的PageRank貢獻值// 遍歷所有傳入的值:包含兩類信息,分別通過首字符判斷for (Text val : values) {String strVal = val.toString(); // 當前值轉換為字符串if (strVal.substring(0, 1).equals("@")) {// 以@開頭,表示這是從其他網頁傳來的PageRank貢獻值// 取出@后面的數值并累加pr += Float.parseFloat(strVal.substring(1));} else if (strVal.substring(0, 1).equals("&")) {// 以&開頭,表示這是本網頁的出鏈結構信息// 將&后面的網頁列表保留下來lianjie += strVal.substring(1); // 注意可能是多個網頁用空格分隔}}// 平滑處理(加入跳轉因子d = 0.8)// 假設網頁總數為4,(1 - d) / N = 0.2 * 0.25 = 0.05// 新PageRank = d * 貢獻值總和 + (1 - d)/Npr = 0.8f * pr + 0.2f * 0.25f;// 構造輸出字符串:新PR值 + 出鏈網頁列表String result = pr + lianjie;// 輸出結果:<當前網頁ID, 新的PageRank值 + 出鏈網頁列表>context.write(key, new Text(result));}
}

遍歷所有值,分類處理

pr += Float.parseFloat(val.toString().substring(1));

如果是 @ 開頭,就從第 1 個字符開始截取字符串(去掉 @),再把它轉換成浮點數,并累加到 pr

lianjie += val.toString().substring(1);

如果是 & 開頭,就把 & 后面的出鏈網頁字符串加到變量 lianjie

  • @ 開頭:表示來自其他網頁的 PageRank 貢獻值,提取并累加。

  • & 開頭:表示這是該網頁自身的 出鏈網頁結構,保留下來。

pr = 0.8f * pr + 0.2f * 0.25f;

?PageRank 中的阻尼系數模型

  • 0.8f:阻尼系數 d(表示 80% 用戶點擊鏈接)

  • 0.2f:1 - d,有 20% 用戶會隨機跳轉

  • 0.25f:假設網頁總數是 4 個,隨機跳轉概率均分為 0.25

PR(A) = d × 所有貢獻值之和 + (1 - d) / N
?



import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
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.output.FileOutputFormat;
import java.util.Scanner;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystem;
import java.net.URI;public class MyRunner {public static void main(String[] args)throws IOException, ClassNotFoundException, InterruptedException {// 創建 Hadoop 配置對象Configuration conf = new Configuration();// 使用控制臺輸入獲取初始輸入路徑和輸出路徑Scanner sc = new Scanner(System.in);System.out.print("inputPath:");String inputPath = sc.next();      // 第一次輸入的 HDFS 輸入路徑,如:/pagerank/inputSystem.out.print("outputPath:");String outputPath = sc.next();     // 第一次輸出的 HDFS 路徑,如:/pagerank/output// 進行 PageRank 的迭代計算,這里迭代 5 次for (int i = 1; i <= 5; i++) {// 創建新的 MapReduce 作業Job job = Job.getInstance(conf);// 設置 Job 的主類,用于打包 Jarjob.setJarByClass(MyRunner.class);// 設置 Map 和 Reduce 的處理類job.setMapperClass(MyMapper.class);job.setReducerClass(MyReducer.class);// 設置 Map 階段輸出鍵值對類型job.setMapOutputKeyClass(Text.class);job.setMapOutputValueClass(Text.class);// 設置 Reduce 階段輸出鍵值對類型(最終輸出)job.setOutputKeyClass(Text.class);job.setOutputValueClass(Text.class);// 設置輸入數據路徑(每輪迭代輸入路徑是上一輪的輸出)FileInputFormat.setInputPaths(job, new Path("hdfs://master:9000" + inputPath));// 設置輸出數據路徑(每輪迭代輸出不同路徑)FileOutputFormat.setOutputPath(job, new Path("hdfs://master:9000" + outputPath));// 更新下一輪迭代的輸入輸出路徑inputPath = outputPath;        // 當前輸出變為下一輪的輸入outputPath = outputPath + i;   // 每次輸出加上數字以區分路徑(如 output1, output2,...)// 提交作業并等待執行完成job.waitForCompletion(true);}// 讀取最終輸出文件內容并打印到控制臺try {// 獲取 Hadoop 文件系統FileSystem fs = FileSystem.get(new URI("hdfs://master:9000"), new Configuration());// 拼接最終輸出文件的路徑(最后一輪輸出的 part-r-00000)Path srcPath = new Path(outputPath.substring(0, outputPath.length() - 1) + "/part-r-00000");// 打開輸出文件FSDataInputStream is = fs.open(srcPath);// 打印最終結果到控制臺System.out.println("Results:");while (true) {String line = is.readLine(); // 讀取一行結果if (line == null) break;     // 如果到文件末尾,結束循環System.out.println(line);    // 打印當前行}is.close(); // 關閉輸入流} catch (Exception e) {e.printStackTrace(); // 如果讀取輸出失敗,打印錯誤}}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/81785.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/81785.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/81785.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

React Flow 數據持久化:Django 后端存儲與加載的最佳實踐(含詳細代碼解析)

在構建 React Flow 應用時&#xff0c;前端呈現的節點與連線構成的可視化流程只是冰山一角&#xff0c;其背后的數據持久化與靈活調取才是確保應用穩定運行、支持用戶數據回溯與協作的關鍵。因此&#xff0c;后端存儲與加載 React Flow 信息的環節&#xff0c;就如同整個應用的…

深度學習中的歸一化:提升模型性能的關鍵因素

&#x1f4cc; 友情提示&#xff1a; 本文內容由銀河易創AI&#xff08;https://ai.eaigx.com&#xff09;創作平臺的gpt-4-turbo模型輔助完成&#xff0c;旨在提供技術參考與靈感啟發。文中觀點或代碼示例需結合實際情況驗證&#xff0c;建議讀者通過官方文檔或實踐進一步確認…

Pandas:Series和DataFrame的概念、常用屬性和方法

本文目錄&#xff1a; 一、Series和Dataframe的概念二、創建Series對象三、創建Dataframe對象&#xff08;一&#xff09;Series1.Series的常用屬性總結如下&#xff1a;2.Series的常用方法總結如下&#xff1a; &#xff08;二&#xff09;Dataframe1.Dataframe的常用屬性2.Da…

數據中心Overlay解決方案

文檔圍繞數據中心 Overlay 解決方案展開,指出數據中心向大集中、虛擬化、云業務演進,傳統架構存在網絡規劃復雜、彈性不足、業務擴展受限等問題。Overlay 網絡在物理網絡上構建虛擬網絡,實現名址分離、網絡與物理解耦,支持業務靈活部署。方案采用VXLAN 技術(如 SDN 控制模…

SpringBoot 項目實現操作日志的記錄(使用 AOP 注解模式)

本文是博主在做關于如何記錄用戶操作日志時做的記錄&#xff0c;常見的項目中難免存在一些需要記錄重要日志的部分&#xff0c;例如權限和角色設定&#xff0c;重要數據的操作等部分。 博主使用 Spring 中的 AOP 功能&#xff0c;結合注解的方式&#xff0c;對用戶操作過的一些…

以太聯 - Intellinet 閃耀臺北 SecuTech 國際安全科技應用博覽會

2025 年 5 月 7 日至 9 日&#xff0c;臺北 SecuTech 國際安全科技應用博覽會現場熱鬧非凡&#xff0c;以太聯 - Intellinet 攜旗下前沿產品與解決方案精彩亮相&#xff0c;成為展會上一道亮麗的風景線&#xff0c;吸引了眾多業內人士的目光&#xff0c;收獲了廣泛關注與高度認…

【華為鴻蒙電腦】首款鴻蒙電腦發布:MateBook Fold 非凡大師 MateBook Pro,擎云星河計劃啟動

文章目錄 前言一、HUAWEI MateBook Fold 非凡大師&#xff08;一&#xff09;非凡設計&#xff08;二&#xff09;非凡顯示&#xff08;三&#xff09;非凡科技&#xff08;四&#xff09;非凡系統&#xff08;五&#xff09;非凡體驗 二、HUAWEI MateBook Pro三、預熱&#xf…

OSA快速上手

我第一次接觸OSA&#xff0c;第一感覺就是龐雜&#xff0c;相關的文檔和資料基本都是英文&#xff0c;運行下示例場景&#xff0c;效果和效率確實很香。本文僅針對初次接觸OSA、望而卻步的朋友們進行快速運用的引導。 首先&#xff0c;找個安裝包&#xff0c;導入項目后&#…

RK3568下編譯解決未定義符號而報錯終止鏈接

現象&#xff1a;我從rk3568板子上導出來了一個 libsqlite3.so 然后編譯連接就會報這樣的錯誤 解決辦法有多種&#xff0c;以前我遇到這種情況&#xff0c;我都是使用sqlite3源碼從新編譯一份使用&#xff0c;并替換到板子上。 現在我是用另一種方法&#xff1a;增加編譯參數 …

LSTM-Attention混合模型:美債危機與黃金對沖效率研究

摘要&#xff1a;本文依托多維度量化分析框架&#xff0c;結合自然語言處理&#xff08;NLP&#xff09;技術對地緣文本的情緒挖掘&#xff0c;構建包含宏觀因子、風險溢價因子及技術面因子的三階定價模型&#xff0c;對當前黃金市場的波動特征進行歸因分析。實證結果顯示&…

Spring Boot 多參數統一加解密方案詳解:從原理到實戰

Spring Boot 多參數統一加解密方案詳解:從原理到實戰 一、前言:為什么需要參數加解密? 在現代Web開發中,數據安全傳輸是基本要求。特別是涉及敏感數據(如用戶隱私、支付信息等)時,僅靠HTTPS還不夠,我們需要對關鍵參數進行二次加密。本文將詳細介紹Spring Boot中實現多…

【css】【面試提問】css經典問題總結

第一章 CSS基礎相關提問 1.1 選擇器問題 1.1.1 選擇器優先級疑問 1. 優先級規則 內聯樣式&#xff1a;直接寫在 HTML 標簽的 style 屬性中的樣式&#xff0c;優先級最高。例如&#xff1a; <p style"color: red;">這是一段紅色文字</p>這里文字的顏…

Linux服務器配置深度學習環境(Pytorch+Anaconda極簡版)

前言&#xff1a; 最近做橫向需要使用實驗室服務器跑模型&#xff0c;之前用師兄的賬號登錄服務器跑yolo&#xff0c;3張3090一輪14秒&#xff0c;我本地一張4080laptop要40秒&#xff0c;效率還是快很多&#xff0c;&#xff08;這么算一張4080桌面版居然算力能比肩3090&#…

【嵌入式】I2S音頻接口3分鐘入門

1. I2S接口入門 I2S&#xff08;Inter-IC Sound&#xff09;是一種專門用于數字音頻數據傳輸的串行通信接口。以下是其核心要點&#xff1a; 1.1 基本概念 I2S是飛利浦公司開發的一種音頻接口標準主要用于數字音頻設備之間的數據傳輸采用串行通信方式 1.2 主要特點 支持立…

java spring -framework -mvc

工程demo&#xff1a;myapp011工程下“_05mvcboot01” model 目錄 1、Spring MVC和MVC 2、創建項目&#xff1a; 3、處理請求 4、HTTP協議 超文本傳輸協議 4.1、 HTTP和HTTPS的區別 4.2、SSL證書 4.3、請求和響應 4.3.1、請求 4.3.2、響應 5、數據的傳遞與接收 5.1、客戶端傳…

沒有屋檐的房子-038—田鼠的酷刑

秋天是收獲的季節&#xff0c;收獲之后的田野里不再是濕漉漉的。水稻此時已經了卻了此生&#xff0c;他們的后代稻谷已經被搬進了打谷場&#xff0c;被蛻變成了大米&#xff0c;住進了生產隊的糧倉然后又進入各家的糧食口袋或者米柜中。稻田里視野逐漸開闊&#xff0c;收割完水…

IntelliJ IDEA打開項目后,目錄和文件都不顯示,只顯示pom.xml,怎樣可以再顯示出來?

檢查.idea文件夾 如果項目目錄中缺少.idea文件夾&#xff0c;可能導致項目結構無法正確加載。可以嘗試刪除項目根目錄下的.idea文件夾&#xff0c;然后重新打開項目&#xff0c;IDEA會自動生成新的.idea文件夾和相關配置文件&#xff0c;從而恢復項目結構。 問題解決&#xff0…

Harmony開發 List、Grid拖動自定義排序實現

1. Harmony開發 List、Grid拖動自定義排序實現 1.1. List拖動功能 本示例基于顯式動畫、List組件實現了ListItem的上下拖動、ListItem切換以及ListItem插入的效果。 ??實現思路:List手勢拖動 @Entry @Component struct ListDragPage {@State private arr: string[] = [0, …

Jules 從私有預覽階段推向全球公測

每周跟蹤AI熱點新聞動向和震撼發展 想要探索生成式人工智能的前沿進展嗎&#xff1f;訂閱我們的簡報&#xff0c;深入解析最新的技術突破、實際應用案例和未來的趨勢。與全球數同行一同&#xff0c;從行業內部的深度分析和實用指南中受益。不要錯過這個機會&#xff0c;成為AI領…

ubuntu上安裝mysql

sudo apt update查看可用版本&#xff1a; apt-cache policy mysql-server返回&#xff1a; mysql-server: 已安裝&#xff1a;(無) 候選&#xff1a; 8.0.42-0ubuntu0.24.04.1 版本列表&#xff1a; 8.0.42-0ubuntu0.24.04.1 500 500 http://cn.archive.ubuntu.com/ubuntu no…