0

我应该使用维基百科的文章链接数据转储从组织的网站中提取具有代表性的术语。为了实现这一点,我 -

  1. 抓取和下载组织的网页。(~110,000)
  2. 创建了维基百科 ID 和术语/标题的字典。(约 4000 万条记录)

现在,我应该使用字典来处理每个网页以识别术语并跟踪它们的术语 ID 和频率。

为了使字典适合内存,我将字典拆分为较小的文件。根据我对小数据集的实验,上述处理时间约为 75 天。

这仅适用于 1 个组织。我必须为其中的 40 多个人做同样的事情。

执行 -

  • HashMap 用于在内存中存储字典。
  • 使用 Boyer-Moore 搜索实现循环遍历每个地图条目以搜索网页中的术语。
  • 对每个网页重复上述操作,并将结果存储在 HashMap 中。

我已经尝试优化代码并调整 JVM 以获得更好的性能。

有人可以建议一种更有效的方法来实施上述方法,将处理时间减少到几天。

Hadoop是一个可以考虑的选择吗?

4

2 回答 2

0

根据您的问题:

Number of Documents = 110000

Dictionary => List of [TermID, Title Terms] = 40million entries

Size of documents = 11000 * 1KB per document on an average =  26.9GB
(1KB per document on an average)

Size of dictionary = 40million * 256bytes = 9.5GB of raw data
(256bytes per entry on an average)

您是如何得出 75 天估算的?

有许多性能目标:

  • 您如何存储文档?
  • 您如何存储/检索字典?(假设不是全部都在内存中,除非你负担得起)
  • 你在多少台机器上运行它?
  • 您是否并行执行字典查找?(当然,一旦你已经处理了整个维基百科,假设字典是不可变的)

以下是我认为您正在做的事情的大纲:

dictionary = read wikipedia dictionary
document = a sequence of documents
documents.map { doc =>
  var docTermFreq = Map[String, Int]()
  for(term <- doc.terms.map if(dictionary.contains(term)) ) {
     docTermFreq = docTermFreq + (term -> docTermFreq.getOrElse(term, 0) + 1)
  }
  // store docTermFreq map
}

这实际上是将每个文档分解为标记,然后在维基百科词典中查找其标记的存在。

这正是Lucene Analyzer所做的。

Lucene Tokenizer会将文档转换为令牌。这发生在术语被索引到 lucene 之前。所以你所要做的就是实现一个分析器,它可以查找维基百科词典,以确定一个标记是否在词典中。

我会这样做:

  • 获取每个文档并准备一个令牌流(使用上述分析器)
  • 索引文档术语。
  • 此时,您将在 Lucene 索引中只有 wikipedia 术语。

执行此操作时,您将从 Lucene Index 获得现成的统计信息,例如:

您可以做很多事情来提高性能。例如:

我希望这会有所帮助。

于 2014-01-23T18:29:57.033 回答
0

仅使用 MR 的方法之一是:

假设您已经有 N 个适合内存的较小尺寸的字典,您可以: 启动 N 个“仅映射”作业,这些作业将扫描您的所有数据(每个作业只有一个字典)并输出诸如 {pageId、termId、occurrence 等} 到文件夹 /your_tmp_folder/N/ 因此,您将拥有 N*M 个文件,其中 M 是每个阶段的映射器数量(应该相同)。

然后第二个工作将简单地分析您的 {pageId、termId、occurrence 等} 对象并为每个页面 id 构建统计信息。

在您的情况下,仅地图作业应该非常快。如果没有 - 请粘贴您的代码。

于 2014-01-23T17:12:51.713 回答