运行 Hadoop 作业时出现 java.lang.OutOfMemoryError

标签 java hadoop stanford-nlp

我有一个输入文件(大小约为 31GB),其中包含消费者对某些产品的评论,我正在尝试对这些产品进行词形还原并找到相应的词条计数。该方法有点类似于 Hadoop 提供的 WordCount 示例。我总共有 4 个类来执行处理:StanfordLemmatizer [包含用于从斯坦福的 coreNLP 包 v3.3.0 进行词形还原的好东西]、WordCount [驱动程序]、WordCountMapper [映射器] 和 WordCountReducer [缩减器]。

我已经在原始数据集的一个子集(以 MB 为单位)上测试了该程序,它运行良好。不幸的是,当我在大小为 ~31GB 的完整数据集上运行作业时,作业失败了。我检查了作业的系统日志,它包含以下内容:

java.lang.OutOfMemoryError: Java heap space at edu.stanford.nlp.sequences.ExactBestSequenceFinder.bestSequence(ExactBestSequenceFinder.java:109) [...]

关于如何处理这个问题有什么建议吗?

注意:我使用的是预配置了 hadoop-0.18.0 的 Yahoo 虚拟机。我还尝试了此线程中提到的分配更多堆的解决方案:out of Memory Error in Hadoop

WordCountMapper 代码:

import java.io.IOException;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.MapReduceBase;
import org.apache.hadoop.mapred.Mapper;
import org.apache.hadoop.mapred.OutputCollector;
import org.apache.hadoop.mapred.Reporter;

public class WordCountMapper extends MapReduceBase
    implements Mapper<LongWritable, Text, Text, IntWritable> {

  private final IntWritable one = new IntWritable(1);
  private final Text word = new Text();
  private final StanfordLemmatizer slem = new StanfordLemmatizer();

  public void map(LongWritable key, Text value,
      OutputCollector output, Reporter reporter) throws IOException {

    String line = value.toString();

    if(line.matches("^review/(summary|text).*"))    //if the current line represents a summary/text of a review, process it! 
    {
        for(String lemma: slem.lemmatize(line.replaceAll("^review/(summary|text):.", "").toLowerCase()))
        {
            word.set(lemma);
            output.collect(word, one);
        }
    }
  }
}

最佳答案

您需要使正在处理的各个单元(即 map-reduce 中的每个 Map 作业)的大小合理。第一个单位是您提供给 StanfordCoreNLP 的 annotate() 调用的文档的大小。您在此处提供的整段文本将在内存中进行标记和处理。在标记化和处理的形式中,它比它在磁盘上的大小大一个数量级。因此,文档大小需要合理。例如,您可能一次传递一个消费者评论(而不是 31GB 的文本文件!)

其次,向下一级,词性标注器(在词形还原之前)一次标注一个句子,它使用大型临时动态编程数据结构来标注一个句子,其大小可能大 3 个数量级比句子。所以,单个句子的长度也需要合理。如果有很长的文本或垃圾没有分成句子,那么你也可能在这个级别有问题。一种简单的解决方法是使用 pos.maxlen 属性来避免 POS 标记超长句子。

附注当然,如果您只需要词形还原器,则不应运行您未使用的注释器,例如 parse、dcoref。

关于运行 Hadoop 作业时出现 java.lang.OutOfMemoryError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20247185/

相关文章:

java - Eclipse 的 .ini 设置似乎无法帮助我更改最大堆大小

java - jarsigner 无法在 java 中工作,因此构建失败

java - 我怎样才能获得语言环境?

windows - Windows上的Hadoop构建错误

java - 斯坦福 NLP 在运行代码时给出异常

java - 如何使用正则表达式将文本拆分为标题和内容?

hadoop - 在配置单元中转换日期格式

java - Spark下载页面上预构建的hadoop和用户提供的hadoop有什么区别?

java - 如何修改StanfordNLP中的TokenRegex规则?

parallel-processing - 特征选择、特征提取、特征权重的区别