我正在尝试将OpenNLP集成到Hadoop上的map-reduce工作中,从一些基本的句子拆分开始。在映射函数中,运行以下代码:
public AnalysisFile analyze(String content) {
InputStream modelIn = null;
String[] sentences = null;
// references an absolute path to en-sent.bin
logger.info("sentenceModelPath: " + sentenceModelPath);
try {
modelIn = getClass().getResourceAsStream(sentenceModelPath);
SentenceModel model = new SentenceModel(modelIn);
SentenceDetectorME sentenceBreaker = new SentenceDetectorME(model);
sentences = sentenceBreaker.sentDetect(content);
} catch (FileNotFoundException e) {
logger.error("Unable to locate sentence model.");
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (modelIn != null) {
try {
modelIn.close();
} catch (IOException e) {
}
}
}
logger.info("number of sentences: " + sentences.length);
<snip>
}
当我运行作业时,我在日志中收到一个错误,指出"in 不得为空!(类抛出错误的来源),这意味着我不知何故无法打开模型的输入流。其他花絮:
- 我已经验证模型文件是否存在于
sentenceModelPath
引用的位置。 - 我已经为 opennlp-maxent:3.0.2-incubating、opennlp-tools:1.5.2-incubating 和 opennlp-uima:1.5.2-incubating 添加了 Maven 依赖项。
- Hadoop只是在我的本地机器上运行。
其中大部分是来自OpenNLP文档的样板文件。我是否缺少一些东西,无论是在Hadoop端还是OpenNLP端,导致我无法从模型中读取?
你的问题是getClass().getResourceAsStream(sentenceModelPath)
行。这将尝试从类路径加载文件 - HDFS 中的文件和客户端本地文件系统中的文件都不是映射器/化简器运行时的类路径的一部分,所以这就是为什么你会看到 Null 错误(如果找不到资源,getResourceAsStream() 返回 null)。
要解决此问题,您有多种选择:
-
修改代码以从 HDFS 加载文件:
modelIn = FileSystem.get(context.getConfiguration()).open( new Path("/sandbox/corpus-analysis/nlp/en-sent.bin"));
-
修改代码以从本地目录加载文件,并使用
-files
GenericOptionsParser选项(从本地文件系统复制到HDFS到文件,然后返回到正在运行的映射器/化简器的本地目录):modelIn = new FileInputStream("en-sent.bin");
- 将文件硬烘焙到作业 jar 中(在 jar 的根目录中),并修改代码以包含前导斜杠:
modelIn = getClass().getResourceAsStream("/en-sent.bin");</li>