UIMA和StanfordNLP在流水线操作之后生成输出,比如如果我们想做词性标记,那么在输入文本中首先进行标记化,然后进行词性标记。
我想使用UIMA的标记化,并在Stanford CoreNLP的POS标记器中使用该标记。但是Stanford CoreNLP的POS标记器需要在POS标记器之前运行标记器。
那么,是否可以在同一管道中使用不同的API?是否可以同时使用UIMA标记器和Stanford CoreNLP?
如果要使用CoreNLP作为管道,至少有两种方法可以处理此问题。
>
强制CoreNLP忽略这些要求。
Properties props = new Properties();
props.put("enforceRequirements", "false");
props.put("annotators", "pos");
这将消除“缺少需求”错误。但是,CoreNLP中的POSTaggerAnnotator期望令牌是CoreLabel对象,并期望句子是CoreMap对象(实例化为ArrayCoreMap),因此您必须转换它们。
向管道中添加自定义注释器。
CoreMaps/CoreLabels是以类作为键的映射,因此您需要为自定义注释提供类/键:
public class CustomAnnotations {
//this class will act as a key
public static class UIMATokensAnnotation
implements CoreAnnotation<List<CoreLabel>> {
//getType() defines/restricts the Type of the value associated with this key
public Class<List<CoreLabel>> getType() {
return ErasureUtils.<Class<List<CoreLabel>>> uncheckedCast(List.class);
}
}
}
您还需要一个注释器类:
public class UIMATokensAnnotator implements Annotator{
//this constructor signature is expected by StanfordCoreNLP.class
public UIMATokensAnnotator(String name, Properties props) {
//initialize whatever you need
}
@Override
public void annotate(Annotation annotation) {
List<CoreLabel> tokens = //run the UIMA tokenization and convert output to CoreLabels
annotation.set(CustomAnnotations.UIMATokensAnnotation.class, tokens);
}
@Override
public Set<Requirement> requirementsSatisfied() {
return Collections.singleton(TOKENIZE_REQUIREMENT);
}
@Override
public Set<Requirement> requires() {
return Collections.emptySet();
}
}
最后:
props.put("customAnnotatorClass.UIMAtokenize", "UIMATokensAnnotator")
props.put("annotators", "UIMAtokenize, ssplit, pos")
UIMA/OpenNLP/等句子注释可以以类似的方式作为自定义注释器添加。查看http://nlp.stanford.edu/software/corenlp-faq.shtml#custom以获取选项#2的浓缩版本。
在UIMA中组合来自不同工具链(例如OpenNLP、Stanford CoreNLP等)的分析步骤的典型方法是将每个步骤包装为UIMA分析引擎。分析引擎充当UIMA数据结构(CAS)和单个工具(例如OpenNLP POS标记器或CoreNLP解析器)使用的数据结构之间的适配器。在UIMA级别,这些组件可以组合成管道。
有各种各样的UIMA组件集合来包装这样的工具链,例如ClearTK、DKPro Core或U-Compare。
以下示例结合了OpenNLP分段器(标记器/句子拆分器)和Stanford CoreNLP解析器(它还在本示例中创建POS标签)。该示例被实现为使用uimaFIT API的Groovy脚本,以使用DKPro Core集合的组件创建和运行管道。
#!/usr/bin/env groovy
@Grab(group='de.tudarmstadt.ukp.dkpro.core',
module='de.tudarmstadt.ukp.dkpro.core.opennlp-asl',
version='1.5.0')
@Grab(group='de.tudarmstadt.ukp.dkpro.core',
module='de.tudarmstadt.ukp.dkpro.core.stanfordnlp-gpl',
version='1.5.0')
import static org.apache.uima.fit.pipeline.SimplePipeline.*;
import static org.apache.uima.fit.util.JCasUtil.*;
import static org.apache.uima.fit.factory.AnalysisEngineFactory.*;
import org.apache.uima.fit.factory.JCasFactory;
import de.tudarmstadt.ukp.dkpro.core.opennlp.*;
import de.tudarmstadt.ukp.dkpro.core.stanfordnlp.*;
import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.*;
import de.tudarmstadt.ukp.dkpro.core.api.syntax.type.*;
def jcas = JCasFactory.createJCas();
jcas.documentText = "This is a test";
jcas.documentLanguage = "en";
runPipeline(jcas,
createEngineDescription(OpenNlpSegmenter),
createEngineDescription(StanfordParser,
StanfordParser.PARAM_WRITE_PENN_TREE, true));
select(jcas, Token).each { println "${it.coveredText} ${it.pos.posValue}" }
select(jcas, PennTree).each { println it.pennTree }
它的输出(在大量记录输出之后)应该如下所示:
This DT
is VBZ
a DT
test NN
(ROOT
(S
(NP (DT This))
(VP (VBZ is)
(NP (DT a) (NN test)))))
我以Groovy脚本为例,因为它是开箱即用的。Java程序看起来非常相似,但通常会使用Maven或Ivy来获取所需的库。
如果您想尝试该脚本,并且需要有关安装Groovy和潜在故障排除的更多信息,您可以在这里找到更多信息。
披露:我正在从事DKPro核心和Apache UIMA uimaFIT项目。
我曾使用grep和awk从斯坦福CRF-NER的“内联XML”中提取英语文本中的命名实体,我希望在其他人类语言中使用相同的更大工作流。 我一直在尝试法语(西班牙语似乎给我带来了一个Java错误,这是另一个故事),并使用我得到标准文本输出,每个句子都有各种类型的注释,包括正确组合在一起的多单词实体,如下所示: 我知道解析它是可能的,但当我真的只是想要整个文件中的实体列表时,这似乎浪费了很多处理。 我
我是Java和Stanford NLP工具包的新手,并试图在一个项目中使用它们。具体地说,我尝试使用Stanford Corenlp toolkit来注释文本(使用Netbeans而不是命令行),并尝试使用http://nlp.Stanford.edu/software/Corenlp.shtml#Usage上提供的代码(使用Stanford Corenlp API)。问题是:有人能告诉我如何在文
有人能让我知道核心NLP的区别吗 http://stanfordnlp.github.io/CoreNLP/ 斯坦福大学NLP http://nlp.stanford.edu/
它工作得很好,但需要很多时间;假设我们在一个问答系统中使用它,那么对于每一个新的输入,都必须运行pipeAnnotation。正如你所知道的,每次都要提取一些规则,训练一些数据等,以生成一个带有NLP标记的句子,如POS,NER和...... 首先,我想用RMI和EJB解决这个问题,但是失败了,因为不管是什么JAVA架构,对于每一个新的句子,pipeAnnotation都应该从头开始学习。查看in
我正在注释和分析一系列文本文件。 pipeline.annotate方法每次读取文件时都会变得越来越慢。最终,我得到了一个OutOfMemoryError。 管道初始化一次: 然后,我使用相同的管道实例处理每个文件(如SO和斯坦福大学在其他地方推荐的)。 明确地说,我希望问题出在我的配置上。但是,我确信失速和内存问题发生在pipeline.annotate(file)方法上。 在处理每个文件后,我
我是斯坦福核心NLP的新手。我想用它来从英语,德语,法语的文本中拆分句子。这是哪一个班的工作?提前谢谢。