UIMA 和 StanfordNLP 在操作管道之后生成输出,就像我们想要进行 POS 标记一样,因此在输入文本中首先完成标记化,然后进行 POS 标记。
我想使用 UIMA 的标记化并在 Stanford CoreNLP 的 POS 标记器中使用该标记。但是Stanford CoreNLP 的词性标注器需要在词性标注器之前运行分词器。
那么,是否可以在同一管道中使用不同的 API?是否可以同时使用 UIMA 标记器和斯坦福 CoreNLP?
UIMA 和 StanfordNLP 在操作管道之后生成输出,就像我们想要进行 POS 标记一样,因此在输入文本中首先完成标记化,然后进行 POS 标记。
我想使用 UIMA 的标记化并在 Stanford CoreNLP 的 POS 标记器中使用该标记。但是Stanford CoreNLP 的词性标注器需要在词性标注器之前运行分词器。
那么,是否可以在同一管道中使用不同的 API?是否可以同时使用 UIMA 标记器和斯坦福 CoreNLP?
在 UIMA中组合来自不同工具链(例如OpenNLP、Stanford CoreNLP等)的分析步骤的典型方法是将它们中的每一个包装为 UIMA 分析引擎。分析引擎充当 UIMA 数据结构(CAS)和用作单独工具(例如 OpenNLP POS 标记器或 CoreNLP 解析器)的数据结构之间的适配器。在 UIMA 级别,这些组件可以组合成管道。
有多种 UIMA 组件集合包装了此类工具链,例如ClearTK、DKPro Core或U-Compare。
以下示例结合了 OpenNLP 分段器(标记器/句子拆分器)和斯坦福 CoreNLP 解析器(在本示例中也创建了 POS 标签)。该示例被实现为一个Groovy脚本,它使用uimaFIT API来创建和运行使用 DKPro 核心集合的组件的管道。
#!/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 Core 和 Apache UIMA uimaFIT 项目。
如果你想使用 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 的精简版。