Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at WebGraph.main(WebGraph.java:6)
如何在Java中实现PageRank算法,有没有存储超链接矩阵的方法?
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at WebGraph.main(WebGraph.java:6)
大多数网络图(或网络)非常稀疏,这意味着图的矩阵表示中的大多数条目都是零。用于表示稀疏矩阵的常见数据结构是哈希映射表,其中不存储零值。例如,如果矩阵为
1, 0, 0
0, 0, 2,
0, 3, 0
在Java中实现高效的稀疏矩阵-向量乘法并不容易,如果您不想花时间处理算法的这个方面,已经有一些实现了。稀疏矩阵乘法是PageRank算法中最难实现的部分,所以在此之后会变得更容易(也更有趣)。
Python的networkx
模块有一个很好的PageRank实现。它使用scipy/numpy进行矩阵实现。以下两个stackoverflow上的问题应该足以让您开始。
使用Python而不是Java:Python是一个非常好的原型语言,有可用的稀疏矩阵(在SciPy中),以及许多其他好处。正如其他人所指出的那样,它还有一个PageRank实现。
不要将所有数据都存储在内存中:任何类型的轻量级数据库都可以,例如sqlite、hibernate等。
按数据块工作:如果有一个大的矩阵NxN,请将其分解为小的矩阵MxM,其中M是N的一小部分,并适合内存。与稀疏矩阵相结合,这使您能够处理真正大的N(根据数据的稀疏程度,达到数十亿到数百亿)。
-Xmx
和所需的堆大小即可。假设您将Java代码编译为可运行的JAR文件,名为pagerank.jar
,并且您想将堆大小设置为512 MB,则应发出以下命令:java -jar -Xmx512m pagerank.jar
编辑: 但是这仅适用于您没有太多的“页面”...一个100万 x 100万的数组太大了,无法放入您的RAM中(1万亿次*64位双精度值=7.27595761 TB)。您应该更改算法以从磁盘加载数据块,对其进行操作并将其存储回磁盘。
您可以使用类似Neo4j的图形数据库来实现此目的。
Google使用“Pregel”BSP(实际上只是关键字)框架执行PageRank。
我记得Apache Giraph(另一个Pregel),其中包括其基准套件中的PageRank版本。
这里有一个关于Giraph的视频:它是一个介绍,特别讲述了如何处理PageRank。
如果那不起作用:
在Java中有一个名为GoldenOrb的Pregel实现。
PageRank算法的伪代码在这里(使用不同的Pregel实现)。
您需要阅读有关BSP和PageRank的信息以处理您所拥有的数据量。
你不需要存储整个1000000x1000000的矩阵,因为大多数矩阵条目都是零。相反,你可以(例如)为每一行存储一个非零条目列表,并编写矩阵函数直接使用它,而不将其扩展为完整矩阵。
这种压缩表示称为稀疏矩阵格式,大多数矩阵库都有构建和处理稀疏矩阵的选项。
稀疏矩阵的一个缺点是将两个稀疏矩阵相乘会得到一个远比原来稀疏的矩阵。然而,PageRank算法设计成不需要这样做:超链接矩阵是恒定的,只有分数向量被更新。