【算法】PageRank

一、引言

        PageRank是由谷歌创始人拉里·佩奇和谢尔盖·布林在斯坦福大学读研究生时发明的一种算法,用于衡量网页的重要性。它基于一个简单的假设:更重要的网页会有更多的链接指向它。

二、算法原理

        PageRank算法的核心思想是,一个网页的重要性可以通过链接到它的其他网页的数量和质量来衡量。算法通过迭代计算每个页面的PageRank值,直到收敛。

  • 初始化:每个页面的PageRank值初始化为相等值。
  • 迭代计算:每个页面的PageRank值是链接到它的页面的PageRank值的加权和。
  • 归一化:在每次迭代后对所有页面的PageRank值进行归一化处理。
  • 收敛:当PageRank值的变化小于某个阈值或达到预定的迭代次数时,算法停止。

三、数据结构

        PageRank算法涉及的数据结构包括:

  • :表示网页和它们之间的链接关系的图结构。
  • 邻接矩阵:用于存储每个页面的入链和出链信息。
  • PageRank向量:存储每个页面的PageRank值。
  • 优先队列(可选):用于优化收敛过程,专注于重要性较高的页面。

四、算法使用场景

        PageRank算法适用于:

  • 搜索引擎:用于网页排名,提高搜索结果的相关性。
  • 社交网络分析:评估用户或内容的影响力。
  • 推荐系统:推荐相关的内容或产品。
  • 文档相似性:基于引用关系进行文档分析和筛选。

五、算法实现

  •  初始化:为每个网页分配一个初始的PageRank值,通常为1/N(N为网页总数)。

  • 迭代计算:对于每个网页i,其PageRank值PR(i)由以下公式计算:

    PR(i)=1−dN+d∑j∈B(i)PR(j)L(j)PR(i)=N1−d​+d∑j∈B(i)​L(j)PR(j)​

其中,d是阻尼因子(通常为0.85),B(i)是链接到i的所有网页集合,L(j)是网页j指向的网页总数。

  • 收敛:迭代直到所有网页的PageRank值变化小于某个阈值。

        伪代码:

function PageRank(pages, d, num_iterations):
n = number of pages
Init PR(p) = 1/n for all pages p
for i = 0 to num_iterations:
for each page p:
new_PR = (1 - d) / n
for each page q that links to p:
new_PR += d * PR(q) / number of outbound links from q
PR(p) = new_PR
return PR

六、其他同类算法对比

与PageRank算法相比,其他链接分析算法包括:

  • HITS算法(Hyperlink-Induced Topic Search)

    • HITS算法将页面分为“权威”页面和“hub”页面,评估方式不同于PageRank。
    • 更加关注内容和链接的主题。
  • Salton的TF-IDF算法

    • 通过词频和逆文档频率来评估文档的重要性,侧重于内容而非链接。
  • TrustRank

    • 在PageRank的基础上引入信任度,量化页面的可信度。

七、多语言代码实现

Java

import java.util.*;public class PageRank {
private Map<String, List<String>> edges;
private Map<String, Double> pageRanks;
private int numIterations;
private double d;public PageRank(Map<String, List<String>> edges, int numIterations, double d) {
this.edges = edges;
this.numIterations = numIterations;
this.d = d;
this.pageRanks = new HashMap<>();
}public void calculate() {
int numPages = edges.size();
for (String page : edges.keySet()) {
pageRanks.put(page, 1.0 / numPages);
}for (int i = 0; i < numIterations; i++) {
Map<String, Double> newRanks = new HashMap<>();
for (String page : edges.keySet()) {
newRanks.put(page, (1 - d) / numPages);
for (String src : edges.keySet()) {
if (edges.get(src).contains(page)) {
newRanks.put(page, newRanks.get(page) + d * (pageRanks.get(src) / edges.get(src).size()));
}
}
}
pageRanks = newRanks;
}
}public Map<String, Double> getPageRanks() {
return pageRanks;
}
}

Python

class PageRank:
def __init__(self, edges, num_iterations=100, d=0.85):
self.edges = edges
self.num_iterations = num_iterations
self.d = d
self.page_ranks = {}def calculate(self):
num_pages = len(self.edges)
for page in self.edges:
self.page_ranks[page] = 1 / num_pagesfor _ in range(self.num_iterations):
new_ranks = {}
for page in self.edges:
new_ranks[page] = (1 - self.d) / num_pages
for src in self.edges:
if page in self.edges[src]:
new_ranks[page] += self.d * (self.page_ranks[src] / len(self.edges[src]))
self.page_ranks = new_ranksreturn self.page_ranks

C++

#include <iostream>
#include <unordered_map>
#include <vector>
#include <string>class PageRank {
public:
PageRank(std::unordered_map<std::string, std::vector<std::string>> edges, int num_iterations = 100, double d = 0.85)
: edges(edges), num_iterations(num_iterations), d(d) {
for (const auto& pair : edges) {
pageRanks[pair.first] = 1.0 / edges.size();
}
}void calculate() {
int num_pages = edges.size();
for (int i = 0; i < num_iterations; ++i) {
std::unordered_map<std::string, double> newRanks;
for (const auto& pair : edges) {
newRanks[pair.first] = (1 - d) / num_pages;
for (const auto& src : edges) {
if (std::find(src.second.begin(), src.second.end(), pair.first) != src.second.end()) {
newRanks[pair.first] += d * (pageRanks[src.first] / src.second.size());
}
}
}
pageRanks = newRanks;
}
}void printRanks() {
for (const auto& rank : pageRanks) {
std::cout << rank.first << ": " << rank.second << std::endl;
}
}private:
std::unordered_map<std::string, std::vector<std::string>> edges;
std::unordered_map<std::string, double> pageRanks;
int num_iterations;
double d;
};

八、实际服务应用场景代码框架

应用场景:网页搜索引擎

        在构建一个简单的网页搜索引擎时,可以通过PageRank算法重排搜索结果,使用户更容易找到重要的网页。整个代码框架的设计思路,包括了PageRank计算的部分,还需要实现内容索引、搜索接口等。

- main.py (入口文件)
- pagerank.py (PageRank算法实现)
- index.py (负责索引网页内容)
- search.py (处理用户搜索请求)
- models/
- webpage.py (网页数据模型)

main.py

from pagerank import PageRank
from index import Indexer
from search import Searcherif __name__ == "__main__":
indexer = Indexer()
indexer.index_webpages() # 负责初始化并索引网页searcher = Searcher(indexer)
user_query = input("请输入搜索内容: ")results = searcher.search(user_query)
print("搜索结果:")
for result in results:
print(result)

pagerank.py

class PageRank:
def __init__(self, edges, num_iterations=100, d=0.85):
self.edges = edges
self.num_iterations = num_iterations
self.d = d
self.page_ranks = {}def calculate(self):
num_pages = len(self.edges)
for page in self.edges:
self.page_ranks[page] = 1 / num_pagesfor _ in range(self.num_iterations):
new_ranks = {}
for page in self.edges:
new_ranks[page] = (1 - self.d) / num_pages
for src in self.edges:
if page in self.edges[src]:
new_ranks[page] += self.d * (self.page_ranks[src] / len(self.edges[src]))
self.page_ranks = new_ranksreturn self.page_ranks

index.py

class Indexer:
def __init__(self):
self.edges = {} # 存储网页链接关系def index_webpages(self):
# 加载网页,并创建对应的边和节点关系
# 示例:
self.edges = {
"A": ["B", "C"],
"B": ["C"],
"C": ["A"],
}
pagerank = PageRank(self.edges)
ranks = pagerank.calculate()
print("PageRank值:", ranks)

search.py

class Searcher:
def __init__(self, indexer):
self.indexer = indexerdef search(self, query):
# 根据查询结果返回相关网页
# 实际实现将根据PageRank和内容进行过滤
ranked_edges = {k: v for k, v in sorted(self.indexer.edges.items(), key=lambda item: item[1])}
return ranked_edges.keys() # 返回网页链接

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1523141.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

沸点 | LDBC 第18届 TUC 会议召开,专家孙宇熙受邀参加并发表演讲

图数据管理领域国际权威组织LDBC&#xff08;Linked Data Benchmark Council&#xff09;于8月30日至31日在广州举办了第18届LDBC TUC会议。作为图数据库领域的创新引领者&#xff0c;嬴图受邀参加此次盛会&#xff0c;国际高性能计算与存储系统专家、大数据专家、图专家及嬴图…

【从零开始学爬虫】采集58同城房源数据

本文以采集北京市58同城房源数据为例进行演示&#xff1a; l 采集网站 【场景描述】采集58同城房源数据。 【使用工具】前嗅ForeSpider数据采集系统 http://www.forenose.com/view/commodity/forespider.html 【入口网址】 https://bj.58.com/xiaoqu/?PGTID0d000000-000…

三、数组————相关概念详解

数组 前言一、数据理论基础二、数组常用操作2.1 初始化数组2.2 访问数组中的元素2.3 插入元素2.4 删除元素 三、数组扩展3.1 遍历数组3.2 数组扩容 总结1、数组的优点2、数组的不足 前言 在数据结构中&#xff0c;数组可以算得上最基本的数据结构。数组可以用于实现栈、队列、…

YoloV10改进策略:卷积篇|基于PConv的二次创新|附结构图|性能和精度得到大幅度提高(独家原创)

文章目录 摘要论文指导PConv在论文中的描述改进YoloV10的描述改进代码与结构图改进方法测试结果总结摘要 在PConv的基础上做了二次创新,创新后的模型不仅在精度和速度上有了质的提升,还可以支持Stride为2的降采样。 改进方法简单高效,需要发论文的同学不要错过! 论文指导…

机器学习实战篇——肿瘤良性/恶性分类器(二元逻辑回归)

机器学习之实战篇——肿瘤良性/恶性分类器&#xff08;二元逻辑回归&#xff09; 前言数据集和实验文件下载相关文章推荐实验过程导入相关模块数据预处理手写二元逻辑回归模型&#xff08;小批量梯度下降&#xff09;sklearn逻辑回归器 前言 实验中难免有许多缺陷和错误&#…

Mac M1安装Hive

一、下载解压Hive 1.官网地址 https://dlcdn.apache.org/hive/ 2.选择对应版本进行下载&#xff0c;这里我以3.1.3为例&#xff1b; 3.下载好后&#xff0c;进行解压&#xff0c;并重命名为hive-3.1.3&#xff0c;放到资源库目录下&#xff1b; 二、配置系统环境 1.打开~/…

Hack The Box-Infiltrator【更新中】

信息收集&端口利用 nmap -sSVC infiltrator.htbStarting Nmap 7.94SVN ( https://nmap.org ) at 2024-09-02 09:17 CST Nmap scan report for infiltrator.htb Host is up (0.61s latency). Not shown: 987 filtered tcp ports (no-response) PORT STATE SERVICE …

C++竞赛初阶L1-15-第六单元-多维数组(34~35课)551: T456501 计算矩阵边缘元素之和

题目内容 输入一个整数矩阵&#xff0c;计算位于矩阵边缘的元素之和。 所谓矩阵边缘的元素&#xff0c;就是第一行和最后一行的元素以及第一列和最后一列的元素。 输入格式 第 1 行包含两个整数&#xff0c;分别为行数 m 和列数 n&#xff0c;两个整数之间空格隔开。 第 2 …

【单调栈 】2289. 使数组按非递减顺序排列

本文涉及的基础知识点 单调栈分类、封装和总结 LeetCode2289. 使数组按非递减顺序排列 给你一个下标从 0 开始的整数数组 nums 。在一步操作中&#xff0c;移除所有满足 nums[i - 1] > nums[i] 的 nums[i] &#xff0c;其中 0 < i < nums.length 。 重复执行步骤&a…

Sobel算子,Scharr算子和Laplacian算子

图像边缘检测大幅度地减少了数据量&#xff0c;并且剔除了可以认为不相关的信息&#xff0c;保留了图像重要的结构属性。有许多方法用于边缘检测&#xff0c; 绝大部分可以划分为两类&#xff1a;基于搜索和基于零穿越。 基于搜索:通过寻找图像一阶导数中的最大值来检测边界&am…

4.1 数据分析-excel 基本操作

第四节&#xff1a;数据分析-excel 基本操作 课程目标 学会excel 基本操作 课程内容 数据伪造 产生一份招聘数据 import pandas as pd from faker import Faker import random import numpy as np# 创建一个Faker实例&#xff0c;用于生成假数据&#xff0c;指定中文本地…

c# 笔记 winform添加右键菜单,获取文件大小 ,多条件排序OrderBy、ThenBy,list<double>截取前5个

Winform右键菜单‌ 要在C# Winform应用程序中添加右键菜单&#xff0c;‌你可以按照以下步骤操作&#xff1a;‌ 1.‌创建菜单项‌ 在Form的构造函数或加载事件中&#xff0c;‌创建ContextMenuStrip控件的实例&#xff0c;‌并为其添加菜单项。‌ 2.‌绑定到控件‌ 将Con…

踩坑记录(序列化与反序列化)

问题描述 实体类中设定字段名称为 sValue和yValue 返回给前段后,变成了svalue,yvalue 字段设置 测试结果:与字段不符,匹配失败 解决方法 在字段上添加JsonProperty("字段名")注解

报告 | 以消费者为中心,消费品零售行业数字化建设持续深化

​2024年是“消费促进年”&#xff0c;国内消费市场稳步复苏。在消费需求多样化、国家政策的推动下&#xff0c;“数字化转型”仍是消费品零售行业的年度主题词&#xff0c;是品牌方获取核心竞争力的必要途径。消费品零售行业的数字化转型重心有所调整&#xff0c;从线上渠道布…

虚拟系统VS

定义 虚拟系统VS&#xff08;Virtual System&#xff09;是指将一台物理设备PS&#xff08;Physical System&#xff09;虚拟成多个相互隔离的逻辑系统。每个VS独立工作&#xff0c;在业务功能上等同于一台独立的传统物理设备&#xff0c;如图2-1所示。 目的 随着网络规模的不…

macos OneNote 2016 for Mac 官方pkg下载地址 - macos 10.15 Catalion 可用Onenote版本官方下载地址

macos 10.15 Catalion 版本的系统已经无法正常从应用商店下载到可用的Onenote 应用,原因是版本不受支持, 而且onenote官方链接的应用商店地址https://apps.apple.com/us/app/microsoft-onenote/id784801555?mt12在中国地区也无法访问, 所以中国地区用户如果想使用onenote应用…

C语言 | Leetcode C语言题解之第394题字符串解码

题目&#xff1a; 题解&#xff1a; #define N 2000typedef struct {int data[30];;int top; } Stack;void push(Stack *s, int e) { s->data[(s->top)] e; }int pop(Stack *s) { return s->data[--(s->top)]; }//多位数字串转换成int int strToInt(char *s) {cha…

Charles抓包全流程(Mac端+iOS端)

文章目录 与其他抓包软件的对比FiddlerWireShark Charles下载安装及配置Charles抓包实践小结 Charles Proxy是一个广泛使用的网络调试代理工具&#xff0c;它允许开发者监控和分析所有经过计算机的HTTP和SSL/HTTPS网络流量信息。 与其他抓包软件的对比 Fiddler Charles 支持多…

Leetcode3250. 单调数组对的数目 I

Every day a Leetcode 题目来源&#xff1a;3250. 单调数组对的数目 I 解法1&#xff1a;记忆化搜索 题目输入一个数组nums。 假设有两个数组A和B&#xff0c;A递增&#xff0c;B递减&#xff0c;且 Ai Bi numsi ​ 问有多少对(A,B)数组对。 解法&#xff1a; 代码&…

自动回复的客服系统-支持关键词回复或AI智能回复

用户咨询量很大的时候&#xff0c;迫切需要一个自动回复的工具 对于公域流量&#xff0c;非常推荐大家使用网页版在线客服系统&#xff0c;与访客沟通。 既能实现自动回复&#xff0c;又能人工后台即时回复 \/x : llike620