CoreNLP tokenizer/sentence 拆分器在 HTML 输入上表现不佳

CoreNLP tokenizer/sentence splitter misbehaves on HTML input

我正在使用命令行中的 Stanford CoreNLP 管道对大型文档进行依赖解析,文档中的每一行都接收自己的依赖树非常重要(否则其他内容将无法对齐)。这对台词目前让我感到悲伤:

<!-- copy from here --> <a href="http://strategis.gc.ca/epic/internet/inabc-eac.nsf/en/home"><img src="id-images/ad-220x80_01e.jpg" alt="Aboriginal Business Canada:
Opening New Doors for Your Business" width="220" height="80" border="0"></a> <!-- copy to here --> Small ABC Graphic Instructions 1.

这是我正在使用的命令:

java -cp "*" -Xmx1g -Xss515m edu.stanford.nlp.pipeline.StanfordCoreNLP \ 
     -annotators tokenize,ssplit,pos,depparse \
     -ssplit.eolonly true \
     -ssplit.newlineIsSentenceBreak always \
     -outputFormat conllu \
     -file "input.txt"

这是结果输出:

1   <!-- copy from here --> _   _   JJ  _   9   amod    _   _
2   <a href="http://strategis.gc.ca/epic/internet/inabc-eac.nsf/en/home">   _   _   JJ  _   9   amod    _   _
3   <img src="id-images/ad-220x80_01e.jpg" alt="Aboriginal Business Canada:
Opening New Doors for Your Business" width="220" height="80" border="0">    _   _   NN  _   9   compound    _   _
4   </a>    _   _   NN  _   9   compound    _   _
5   <!-- copy to here -->   _   _   NN  _   9   compound    _   _
6   Small   _   _   JJ  _   9   amod    _   _
7   ABC _   _   NNP _   9   compound    _   _
8   Graphic _   _   NNP _   9   compound    _   _
9   Instructions    _   _   NNS _   0   root    _   _
10  1   _   _   CD  _   9   nummod  _   _
11  .   _   _   .   _   9   punct   _   _

HTML 标签中引号内的换行符似乎被解释为标记的一部分,而不是句子中断。这很奇怪,因为我使用的是 -ssplit.newlineIsSentenceBreak always 标志,我希望它会强制解析器拆分 HTML 代码。然而,即使我不需要每一行都得到自己的解析,这种行为也很麻烦,因为生成的文件不再是有效的 conllu 格式,因为第 3 行只有两个制表符分隔的列(而不是所需的 10 列)而第 4 行只有 9.

我尝试过的一个解决方法是将原始文件中的每一行转换为自己的文件,然后使用 -filelist 参数将它们输入,但这会产生太多 stdout 输出,从而减慢速度下来并堵塞了终端。我尝试将输出重定向到 /dev/null 或打开 "quiet mode" 失败,但这可能是另一个 post.

的问题

我试过将文件加倍行距,但没有用。使用 sed 's/"/\"/g' 预处理文本确实通过破坏管道将其识别为 HTML 代码的能力解决了这个问题,但引入了新的代码,因为解析器可能没有接受过转义引号的训练。

显然这是一个奇怪的句子,我不希望输出被合理地解析,但我确实需要它被合理地格式化。有什么建议吗?

更新 有人建议我尝试使用 cleanxml 注释器来完全摆脱 HTML 标记。这减少了文件中的行数,这可能会导致以后出现错位,但是由于 HTML 标签无论如何都没有得到合理的解析,因此摆脱它们似乎是独立有利的。我稍后会再次更新这是否适合我的目的,但同时我愿意接受其他建议。

这里有两个问题:

  1. 标记器将解析为单个标记 HTML/XML/SGML 标记,其中属性的引用值被拆分成多行。通常这是一件好事——如果这是普通文本,它为这个例子所做的事情实际上是明智的,将整个 img 标签保持在一起——但如果你想将文本严格地作为一个句子来处理,那将是灾难性的每行,就像在大多数机器翻译语料库中一样。在这种情况下,您希望将每一行都视为一个句子,即使原来的断句是错误的,如此处所示。

  2. 如果在属性值中捕获换行符,则保留原样,然后在输出时,这至少破坏了面向行的 CoNLL 和 CoNLL-U 输出的完整性格式。

我有 added/changed 代码来解决这些问题:

  1. 有一个新的分词器选项:-tokenize.options tokenizePerLine,它将禁止分词器在形成分词或做出分词决策时跨行边界查看。 (此选项可以与所有其他 tokenize.options 选项组合在逗号分隔的列表中。)

  2. 如果在属性值中捕获换行符,则将其映射到 U+00A0(不间断 space)。这已经发生在 U+0020 (space) 上,现在也适用于换行符。这修复了 CoNLL/CoNLL-U 输出并维护了 Stanford CoreNLP 的正确不变性:令牌可能偶尔包含不间断的 spaces,但从不包含 space 或换行符。

此问题已在 the CoreNLP github 的提交 0a17fe4c0fc4ccfb095f474bf113d1df0c6d17cb 中修复。如果您获取该版本——或最低限度地更新 PTBLexer.classPTBTokenizer.class,那么您将拥有这个新选项并且应该不错。下面的命令应该给你你想要的:

java -cp "*" -Xmx1g edu.stanford.nlp.pipeline.StanfordCoreNLP \ -annotators tokenize,ssplit,pos,depparse -ssplit.eolonly true \ -tokenize.options tokenizePerLine -outputFormat conllu -file "input.txt"

p.s。我猜你是想修复问题,但如果你使用的是 -ssplit.eolonly true,那么你不需要也不会看到与 -ssplit.newlineIsSentenceBreak always 的区别。此外,我们也许应该让打开 -ssplit.eolonly true 自动打开 -tokenize.options tokenizePerLine,但目前情况并非如此....