数据挖掘Java——PageRank算法的实现

news2024/9/21 3:17:46

一、PageRank算法的前置知识

PageRank算法:计算每一个网页的PageRank值,然后根据这个值的大小对网页的重要性进行排序。

从用户角度来看,一个网站就是若干页面组成的集合。然而,对于网站的设计者来说,这些页面是经过精心组织的,是通过页面的链接串联起来的一个整体。因此,Web的结构挖掘主要是对网站中页面链接结构的发现。例如:在设计搜索引擎等服务时,对Web页面的链接结构进行挖掘可以得出有用的知识来提高检索效率和质量。
一般来说,Web页面的链接类似学术上的引用,因此,一个重要的页面可能会有很多页面的链接指向它。也就是说,如果有很多链接指向一个页面,那么它一定是重要的页面。同样地,假如一个页面能链接到很多页面,它也有其重要的价值

设u为一个Web页,Bu为所有指向u的页面的集合,Fu为所有u指向的页面的集合,c(<1)为一个归一化的因子,那么u页面的等级R(u)被定义为:R(u)=c∑_(v∈Bu)▒(R(v))/(|Fv|),很显然,基本的页面分级方法主要考虑一个页面的入度,即通过进入该页面的页面等级得到。同时,在将一个页面的等级值传递时,采用平均分配方法传递到所有它所指向的页面,即每个从它链接处的页面等分它的等级值。

PageRank算法的核心部分可以从一个有向图开始。最典型的方法是根据有向图构造一个邻接矩阵来进行处理。邻接矩阵A=(ai,j)中的元素ai,j(∈[0,1])表示从页面j指向页面i的概率。

二、PageRank算法的基本思想

基本的PageRank算法在计算等级值时,每个页面都将自己的等级值平均地分配给其引用的页面节点。假设一个页面的等级值为1,该页面上共有n个超链接,其分配给每个超链接页面的等级值就是1/n,那么就可以理解为该页面以1/n的概率跳转到任意一个其所引用的页面上。
一般地,把邻接矩阵A转换成所谓的转移概率矩阵M来实现PageRank算法:M=(1-d)Q+dA,其中,Q是一个常量矩阵,最常用的是Q=(qi,j),qi,j=1/n,转移概率矩阵M可以作为一个向量变换矩阵来帮助完成页面等级值向量R的迭代计算:Ri+1=M*R

三、PageRank算法的例子

PageRank算法例子
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、PageRank算法的实现过程

实验内容
互联网中的网页的链接可以看作是有向图,如A、B、C、D四个网页,请采用PageRank算法对网页进行分级排序
在这里插入图片描述
实验思路
(1)定义Score分数类,在Score分数类中包含分子son和分母mom属性,还包含静态方法simplify()用于对分子分母进行约分,静态方法getAdd()用于分数相加并化简结果,静态方法getMultiply()用于分数相乘并调用simplify()对结果进行化简。
(2)定义初始数据集dataList,定义转移矩阵的每一项Score分数类对象,调用InitData()方法对数据集进行初始化。
(3)定义Score类对象v0Score并对其实例化,v0Score对象表示分数值1/4,表示最初人们对点击A,B,C,D四个网页的概率都是相同的1/4。定义一维数组V0存放4个v0Score,初始的PageRank也赋值成V0。
(4)进入while循环,调用getPageRank()方法获取PageRank矩阵。在getPageRank()方法体内部定义pageRankList集合存放最终的PageRank值,遍历dataList数据集中每一项数据dataItem,使用for循环遍历dataItem,使得dataItem和Vk完成矩阵乘法,并将矩阵乘法后每一项的结果保存在itemSum当中,当遍历dataItm结束后,将itemSum添加到pageRankList集合当中,在遍历数据集dataList集合结束后,将pageRankList转换成数组后返回。
(5)调用isRankEqual()方法判断新得到的PageRank矩阵值是否和上次得到的PageRank矩阵值相同,若不相同则继续迭代,若相同则不再迭代。isRankEqual()方法主要是判断形参V1和形参V2的PageRank矩阵内的值是否相等,返回boolean类型的值,方法体内部对数组V1进行遍历,比较V1中每一项的分子和V2中每一项的分子是否相同,若有不相同的则返回false,若遍历结束后没有不同的则返回true。
(6)若新得到的PageRank矩阵值不与上次得到的PageRank矩阵值相同,则将新得到的PageRank矩阵值赋值给最终要输出的pageRank变量,输出每一次得到的PageRank值。

实现源码

Score类
package com.data.mining.entity;

import lombok.Data;

@Data
public class Score {
    private int son;
    private int mom;

    public Score(){}

    public Score(int s, int m){
        son = s;
        mom = m;
    }

    /**
     * 分数相加并调用simplify方法进行约分
     * @param s1
     * @param s2
     * @return
     */
    public static Score getAdd(Score s1, Score s2){
        if (s1.getMom() == 0 || s2.getMom() == 0) return s1.getMom() == 0 ? s2 : s1;
        int commonMom = s1.getMom() * s2.getMom();
        int commonSon = s1.getSon() * s2.getMom() + s2.getSon() * s1.getMom();
        Score addResult = simplify(commonSon, commonMom);
        return addResult;
    }

    /**
     * 分数相乘并调用simplify方法进行约分
     * @param s1
     * @param s2
     * @return
     */
    public static Score getMultiply(Score s1, Score s2){
        int tempMom = s1.getMom() * s2.getMom();
        int tempSon = s1.getSon() * s2.getSon();
        Score simplifyResult = simplify(tempSon, tempMom);
        return simplifyResult;
    }

    /**
     * 对分子分母进行约分
     * @param s
     * @param m
     * @return
     */
    private static Score simplify(int s, int m){
        int common = getCommon(s, m);
        s = s / common;
        m = m / common;
        Score result = new Score(s, m);
        return result;
    }

    /**
     * 找分子分母的最大公约数
     * @param s
     * @param m
     * @return
     */
    private static int getCommon(int s, int m){
        for (int i = s; i >= 1; i--) {
            if (m%i==0 && s%i==0){
                return i;
            }
        }
        return 1;
    }
}

PageRank算法实现代码
package com.data.mining.main;

import com.data.mining.entity.Score;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class PageRank {
    //定义转移矩阵
    public static List<Score[]> dataList = new ArrayList<>();
    //定义转移矩阵中的每一项
    public static Score s00,s01,s02,s03,s10,s11,s12,s13,s20,s21,s22,s23,s30,s31,s32,s33;

    public static void main(String[] args) {
        initData();
        Score voScore = new Score(1, 4);
        Score[] V0 = {voScore, voScore, voScore, voScore};
        Score[] pageRank = V0;
        while (true){
            Score[] tmpVk = getPageRank(pageRank);
            if (isRankEqual(pageRank, tmpVk)) break; //新得到的PageRank矩阵和上次得到的PageRank矩阵不相同,则继续迭代,相同则不再迭代
            pageRank = tmpVk;
            System.out.println(Arrays.toString(pageRank));
        }
        System.out.println(Arrays.toString(pageRank));
    }

    /**
     * 判断V1和V2的PageRank矩阵内的值是否相等
     * @param V1
     * @param V2
     * @return
     */
    public static boolean isRankEqual(Score[] V1, Score[] V2){
        for (int i = 0; i < V1.length; i++) {
            int subSon = V1[i].getSon() - V2[i].getSon();
            int subMom = V1[i].getMom() - V2[i].getMom();
            if (subSon != 0 || subMom != 0) return false;
        }
        return true;
    }

    /**
     * 获取PageRank矩阵
     * @param Vk
     * @return
     */
    public static Score[] getPageRank(Score[] Vk){
        List<Score> pageRankList = new ArrayList<>();
        for (Score[] dataItem : dataList) {
            Score itemSum = new Score(0,0); //itemSum中存放PageRank矩阵的每一项
            //通过遍历数据集的每一行和Vk的每一列实现矩阵乘法
            for (int i = 0; i < dataItem.length; i++) {
                Score multiply = Score.getMultiply(dataItem[i], Vk[i]);
                itemSum = Score.getAdd(multiply, itemSum); //将对应项相乘的结果累加到itemSum中
            }
            pageRankList.add(itemSum);
        }
        return pageRankList.toArray(new Score[pageRankList.size()]);
    }

    /**
     * 初始化数据集
     */
    public static void initData(){
        s00 = new Score(0, 0);
        s01 = new Score(1, 2);
        s02 = new Score(1, 1);
        s03 = new Score(0, 0);
        s10 = new Score(1, 3);
        s11 = new Score(0, 0);
        s12 = new Score(0, 0);
        s13 = new Score(1, 2);
        s20 = new Score(1, 3);
        s21 = new Score(0, 0);
        s22 = new Score(0, 0);
        s23 = new Score(1, 2);
        s30 = new Score(1, 3);
        s31 = new Score(1, 2);
        s32 = new Score(0, 0);
        s33 = new Score(0, 0);

        Score[] s0 = {s00, s01, s02, s03};
        Score[] s1 = {s10, s11, s12, s13};
        Score[] s2 = {s20, s21, s22, s23};
        Score[] s3 = {s30, s31, s32, s33};

        dataList.add(s0);
        dataList.add(s1);
        dataList.add(s2);
        dataList.add(s3);
    }
}

实验结果
在这里插入图片描述
面对这个迭代结果,笔者还是有些许疑问的,书上最后的迭代结果说是趋于稳定了最后结果是[3/9,2/9,2/9,2/9],可是本次实验最终并没有得到满意的结果,而是因为数据溢出直接终止了程序,但可以看到最后一次输出的结果已经很趋近于正确答案了,包括每次的迭代结果笔者也进行了笔算,也没发现什么问题。这图片不知道为啥字这么小,反正我是看不清,所以用表格盛一下:
在这里插入图片描述

五、实验总结

本实验结果笔者并不保证一定是正确的,笔者仅仅是提供一种使用Java语言实现PageRank算法的思路。因为实验并没有给答案,笔者已将书上有答案的实验数据输入程序后,程序输出的结果和答案一致,所以问题应该不大。若有写的不到位的地方,还请各位多多指点!
笔者主页还有其他数据挖掘算法的总结,欢迎各位光顾!

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

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

相关文章

嵌入式系统开发笔记109:多个LED的闪烁控制

文章目录前言一、一般思路1、LED0 100ms闪烁&#xff0c;LED1 200ms闪烁2、LED0 100ms闪烁&#xff0c;LED1 300ms闪烁3、LED0 200ms闪烁&#xff0c;LED1 600ms闪烁二、通过循环变量实现1、LED0 500ms闪烁&#xff0c;LED1 700ms闪烁2、LED0 15ms闪烁&#xff0c;LED1 7ms闪烁…

Java——LRUCache

概念 简单来说&#xff0c;由于我们的空间是有限的&#xff0c;所以发明了这个数据结构&#xff0c;当我们的空间不够添加新的元素时&#xff0c;就会删除最近最少使用的元素。 其底层逻辑通过哈希表和链表共同实现。哈希表中存储链表的每一个元素&#xff0c;方便进行元素的…

Mysql分布式锁(三)悲观锁实现并发

在前面的方法中&#xff0c;一条sql语句中仍然存在着很多问题&#xff0c;于是我们可以用悲观锁来代替解决。 假设我们不用一条sql&#xff0c;仍然用先查询&#xff0c;判断&#xff0c;最后更新来实现业务。 文章目录悲观锁 select...for update1. 不加悲观锁1) 两个机器连接…

因果推断2--深度模型介绍(个人笔记)

目录 一、方法介绍 1.1TarNet 1.1.1TarNet 1.1.2网络结构 1.1.3counterfactual loss 1.1.4代码实现 1.2Dragonet 1.3DRNet 1.4VCNet VCNET AND FUNCTIONAL TARGETED REGULARIZATION FOR LEARNING CAUSAL EFFECTS OF CONTINUOUS TREATMENTS 二、待补充 一、方法介绍 …

AcWing 第82场周赛

AcWing 第82场周赛 竞赛 - AcWing B 4783. 多米诺骨牌 - AcWing题库 模拟题&#xff0c;考察代码描述问题的能力。 由题意所给的数学形式化定义中看出&#xff0c;所给的骨牌初始序列 L 和 R 的顺序一定是相互交错的&#xff0c;即 ...LRLRLRLR... 所以&#xff0c;一旦遇到…

KNN算法 搜索最优超参数:n_neighbors/weights/p

目录 一&#xff1a;遍历参数 超参调优测试 二&#xff1a;网格模型 超参调优测试 三&#xff1a;模型保存 四&#xff1a;模型使用 一&#xff1a;遍历参数 超参调优测试 1.1 超参调试&#xff0c;找到模型最优解[仅做测试&#xff0c;得出最优&#xff1a;n_neighbors, …

PowerDesigner导入SQL脚本生成带中文注释(comment)的ER图并保存为图片格式(含通用可执行vb脚本文件)

目录 1、安装数据库建模工具PowerDesigner 16.5 2、打开 PowerDesigner&#xff0c;选择反向工程 3、选择数据库类型 4、导入SQL脚本文件并生成数据库表模型 5、去掉Diagram画板黑色网格线&#xff08;选做&#xff09; 6、ER图常规显示&#xff08;包含是否为Null及表名…

D. Same Count One(模拟 + 思维转换(行不行,从列入手))

Problem - D - Codeforces ChthollyNotaSeniorious收到了AquaMoon的一份特殊礼物&#xff1a;n个长度为m的二进制数组。AquaMoon告诉他&#xff0c;在一次操作中&#xff0c;他可以选择任何两个数组和1到m中的任何位置&#xff0c;并交换这些数组中位置的元素。 他对这个游戏很…

RabbitMQ知识总结一

更多知识在我的语雀平台&#xff1a; https://www.yuque.com/ambition-bcpii/muziteng RabbitMQ 1. RabbitMQ引言 1.1 什么是MQ MQ&#xff08;Message Queue&#xff09;消息队列&#xff0c;是基础数据结构中“先进先出”的一种数据结构。一般用来解决应用解耦&#xff0…

带token的登陆页面爆破方法(burp宏+爬虫脚本分享)

文章目录前言一、token参数分析二、burp设置宏操作三、爬虫脚本四、小结前言 在工作中&#xff0c;会遇到很多登陆页面有token保护&#xff0c;如果用Burpsuite直接抓取数据包并使用爆破模块&#xff0c;则会因token过期导致无法爆破。此时至少可以采用三种办法&#xff1a; 第…

Java诊断工具——arthas,实时监控,了解一下

文章目录1、arthas 简介官方文档2、arthas 的使用场景3、安装&启动3.1 安装3.2 启动4、常用命令5、使用示例5.1 stack5.2 jad5.3 sc5.4 watch5.5 trace5.6 jobs5.7 logger5.8 dashboard5.9 redefine6、其它1、arthas 简介 arthas是由阿里巴巴中间件团队开源的Java诊断工具。…

kubernetes对外服务之Ingress

目录 ​​​​​​​一、Ingress 是什么 1.1Service的作用 1.2Ingress简介 二、Ingress 安装 三、Ingress 代理访问 3.1Ingress HTTP 代理访问 3.2 Ingress: HTTPS 代理访问 3.3Ingress Contronler怎么工作的&#xff1f; ​​​​​​​​​​​​​​一、Ingress 是什…

Java核心实操:内存溢出 实战、内存泄漏实战

文章很长&#xff0c;而且持续更新&#xff0c;建议收藏起来&#xff0c;慢慢读&#xff01;疯狂创客圈总目录 博客园版 为您奉上珍贵的学习资源 &#xff1a; 免费赠送 :《尼恩Java面试宝典》 持续更新 史上最全 面试必备 2000页 面试必备 大厂必备 涨薪必备 免费赠送 经典…

ARM系列之MMU TLB和ASID基础概念介绍。

目录1、为什么要设计TLB&#xff1f;TLB中不包含我们需要的映射关系怎么办&#xff1f;2、TLB中都包含了啥&#xff1f;3、那什么是ASIDAddress Space ID&#xff08;ASID&#xff09;4、小结内存寻址简要过程如下&#xff1a;VA以页表大小取余&#xff0c;得到PA的低位&#x…

Go sync.Pool池化的学习

一句话总结&#xff1a;保存和复用临时对象&#xff0c;减少内存分配&#xff0c;降低 GC 压力。 一.前言 Go 语言标准库也大量使用了 sync.Pool&#xff0c;例如 fmt 和 encoding/json。 1.1 要解决的问题 一个新技术亦或是一个新名词&#xff0c;总是为了解决一些问题才出…

数据挖掘课程设计报告总结

一、实验题目 实验一 Apriori算法设计与应用 二、背景介绍 Apriori算法是一种挖掘关联规则的频繁项集算法&#xff0c;其核心思想是通过候选集生成和向下封闭检测两个阶段来挖掘频繁项集。 三、实验内容 1.3.1 运用的理论知识 关联规则挖掘是数据挖掘中最活跃的研究方法之…

数控恒流源电路简单讲解

&#xff08;1&#xff09;最近课设是做一个可步进的恒流源&#xff0c;所以查查找了很多资料之后。说一下自己对于恒流源电路的简单理解。 &#xff08;2&#xff09;我只是会将怎么使用和调整数据进行讲解&#xff0c;至于为什么这样只会讲我懂的部分。本人知道的也不是很多&…

【RPA前置知识】 整理并总结ForEach Activity类

&#x1f40b;作者简介&#xff1a;博主是一位.Net开发者&#xff0c;同时也是RPA和低代码平台的践行者。 &#x1f42c;个人主页&#xff1a;会敲键盘的肘子 &#x1f430;系列专栏&#xff1a;.Net实用方法总结 &#x1f980;专栏简介&#xff1a;本专栏介绍如何编写 Windows…

Biopython教程

Biopython教程 参考&#xff1a; https://biopython-cn.readthedocs.io/zh_CN/latest/index.html 蛋白质文件获取 Entrez方法 from Bio import Entrez Entrez.email邮箱名 #如123456789qq.com handleEntrez.esearch(dbprotein,term2rbg) recordEntrez.read(handle) idrecor…

C++PrimerPlus 第八章 函数探幽-8.2 引用变量

目录 8.2 引用变量 8.2.1 创建引用变量 8.2.2 将引用用作函数参数 8.2.3 引用的属性和特别之处 8.2.3.1 临时变量、引用参数和const 8.2.4 将引用用于结构 8.2.4.1 程序说明 8.2.4.2 为何要返回引用 8.2.4.3 返回引用时需要注意的问题 8.2.4.4 为何将const用于引用返…