【问题标题】:PageRank implementation for Research用于研究的 PageRank 实施
【发布时间】:2012-11-04 05:38:07
【问题描述】:

在阅读this site的PageRank算法理论之后,我想玩它。 我正在尝试在 Java 中实现这一点。我的意思是我想详细使用 PageRank(比如给出不同的权重等等)。为此,我需要构建超链接矩阵。如果我有 100 万个节点,那么我的超链接矩阵将是 100 万 x 100 万大小,这会导致此异常:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at WebGraph.main(WebGraph.java:6)

如何在 Java 中实现 PageRank,有没有办法存储超链接矩阵?

【问题讨论】:

  • 你已经看过哪里了?你有没有发现任何非开源的实现?您是否考虑过自己实施?你对语言有什么偏好吗?
  • @acattle 我看过 Jung 和 WebLA。我想专注于理论而不是实施。语言偏好:任何。
  • 您是否尝试过增加堆大小以消除该异常?
  • @DanW 我该怎么做?
  • 你需要一个擅长存储稀疏矩阵的库 Matlab 有这样一个库(我相信在 c++ 中),我相信你可以借用它,并将它链接到你的 java 代码中。除非您处理小图形/矩阵,否则增加堆大小只是一种绷带解决方案。也许在java中使用这个introcs.cs.princeton.edu/java/44st/SparseMatrix.java.html

标签: java algorithm graph-algorithm pagerank


【解决方案1】:

这是一篇了解 pagerank 的好文章。我从 here 实现了一个 Perl 版本,以便与 Textrank 一起使用。但是,如果您只想了解 pagerank 以及文章中讨论的各个方面如何影响结果(阻尼因子、有向图或无向图等),我建议您在 ROctave 中运行实验。如果您想学习如何有效地实现它,那么最好从头开始编程,就像您正在做的那样。

大多数网络图(或网络)都非常sparse,这意味着图的矩阵表示中的大多数条目为零。用于表示稀疏矩阵的常见数据结构是hash-map,其中不存储零值。例如,如果矩阵是

1, 0, 0
0, 0, 2,
0, 3, 0

二维哈希映射将仅存储 hm(0,0)=1、hm(1,2)=2 和 hm(2,1)=3 的值。因此,在web graph 的 1,000,000 x 1,000,000 矩阵中,我预计只有几百万个值是非零的。如果每行平均只有 5 个非零值,则哈希映射将使用大约 5*(8+8+8)*10^6 字节 ~ 115mb 来存储它(8 用于左侧 int 索引,8 用于右侧 int索引,8 表示双精度值)。方阵将使用 8*10^6*10^6 ~ 7 TB。

在 Java 中实现高效的稀疏矩阵向量乘法并非易事,如果您不想花时间在算法的这方面,已经有一些 implemented。稀疏矩阵乘法是 pagerank 算法最难实现的方面,因此之后它变得更容易(也更有趣)。

【讨论】:

    【解决方案2】:

    Python networkx 模块有一个很好的 pagerank 实现。它使用 scipy/numpy 来实现矩阵。以下关于 stackoverflow 的两个问题应该足以让您入门。

    【讨论】:

      【解决方案3】:

      一些建议:

      • 使用 python,而不是 Java:python 是一种出色的原型设计语言,并且具有可用的稀疏矩阵(在 scipy 中)以及许多其他好东西。正如其他人所指出的,它还有一个 pagerank 实现。

      • 不要将数据全部存储在内存中:任何类型的轻量级数据库都可以,例如 sqlite、hibernate、...

      • 处理数据块:如果有一个大矩阵 NxN,将其分解为小块 MxM,其中 M 是 N 的一部分,适合内存。结合稀疏矩阵,您可以处理非常大的 N(数亿到数十亿,具体取决于数据的稀疏程度)。

      【讨论】:

        【解决方案4】:

        按照 Dan W 的建议,尝试增加堆大小。如果您从命令行运行 Java 应用程序,只需添加具有所需堆大小的开关 -Xmx。假设您将 Java 代码编译成一个名为 pagerank.jar 的可运行 JAR 文件,并且您希望将堆大小设置为 512 MB,您将发出以下命令:

        java -jar -Xmx512m pagerank.jar
        

        编辑: 但这仅在您没有那么多“页面”时才有效…… 100 万 x 100 万的数组太大而无法放入您的 RAM(1 万亿倍 * 64 位双精度值 = 7.27595761 TB)。您应该更改算法以从磁盘加载数据块,对其进行操作,然后将其存储回磁盘。

        您可以为此目的使用像 Neo4j 这样的图形数据库。

        【讨论】:

        • 我有WebGraph.class,所以我跑了:java -Xmx2048m WebGraph,但它仍然给出OutOfMemoryError
        • @torayeff:查看我编辑的答案。 100 万 * 100 万个节点 = 1 万亿个单元。如果您使用超过 7 TB 的双精度数组(双精度可能是 64 位),这可能超出您的 RAM 可以处理的范围。
        【解决方案5】:

        您不必存储整个 1000000x1000000 矩阵,因为大多数矩阵条目将为零。相反,您可以(例如)为每行存储一个非零条目列表,并编写矩阵函数以直接使用它,而无需将其扩展为完整矩阵。

        这种压缩表示称为sparse matrix 格式,大多数矩阵库都有构建和使用稀疏矩阵的选项。

        稀疏矩阵的一个缺点是,将其中两个相乘会得到一个稀疏得多的矩阵。但是,PageRank 算法被设计成不需要这样做:超链接矩阵是恒定的,并且只更新分数向量。

        【讨论】:

          【解决方案6】:

          PageRank 由 Google 使用“Pregel”BSP(实际上只是关键字)框架执行。

          我记得Apache Giraph(另一个 Pregel),它的基准包中包含一个 PageRank 版本。

          Here's a video about Giraph:介绍,专门讲PageRank的处理。

          如果这不起作用:

          在 Java 中有一个 Pregel 的实现,称为 GoldenOrb

          PageRank 算法的伪代码是 here(在 Pregel 的不同实现上)。

          您必须阅读 BSP 和 PageRank 来处理您拥有的数据大小。

          【讨论】:

            【解决方案7】:

            因为矩阵是稀疏的,您可以实现像 svd、pca、mds 或包含 svd 的 Lsi 这样的降维。有一个库可以实现这种称为 Jama 的过程。你可以找到它here

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-02-14
              • 1970-01-01
              • 1970-01-01
              • 2015-06-09
              • 2013-09-19
              • 1970-01-01
              • 1970-01-01
              • 2014-04-27
              相关资源
              最近更新 更多