从某种程度上讲,Mukesh Kumar 和 GsusRecovery 提供的两个答案都有帮助,但并不完全正确。
document.replaceAll("[^\\u0009\\u000a\\u000d\\u0020-\\uD7FF\\uE000-\\uFFFD]", "")
看起来替换了所有无效字符。但是CoreNLP似乎不支持更多。我通过在整个语料库上运行解析器手动找出了它们,结果如下:
document.replaceAll("[\\uD83D\\uFFFD\\uFE0F\\u203C\\u3010\\u3011\\u300A\\u166D\\u200C\\u202A\\u202C\\u2049\\u20E3\\u300B\\u300C\\u3030\\u065F\\u0099\\u0F3A\\u0F3B\\uF610\\uFFFC]", "")
现在我运行了两个replaceAll()
命令,然后将文档交给解析器。完整的代码片段如下:
String tmpDoc1 = document.replaceAll("[^\\u0009\\u000a\\u000d\\u0020-\\uD7FF\\uE000-\\uFFFD]", "");
String tmpDoc2 = tmpDoc1.replaceAll("[\\uD83D\\uFFFD\\uFE0F\\u203C\\u3010\\u3011\\u300A\\u166D\\u200C\\u202A\\u202C\\u2049\\u20E3\\u300B\\u300C\\u3030\\u065F\\u0099\\u0F3A\\u0F3B\\uF610\\uFFFC]", "");
DocumentPreprocessor tokenizer = new DocumentPreprocessor(new StringReader(tmpDoc2));
for (List<HasWord> sentence : tokenizer) {
List<TaggedWord> tagged = tagger.tagSentence(sentence);
GrammaticalStructure gs = parser.predict(tagged);
System.err.println(gs);
}
这不一定是所有不支持字符的完整列表,这也是我在GitHub上开了一个问题的原因。
请注意,CoreNLP会自动删除那些不支持的字符。我想预处理我的语料库的唯一原因是为了避免所有这些错误消息。
更新11月27日
Christopher Manning刚刚回答了我打开的GitHub问题。有几种方法可以使用类edu.stanford.nlp.process.TokenizerFactory;
来处理这些字符。使用此代码示例对文档进行标记:
DocumentPreprocessor tokenizer = new DocumentPreprocessor(new StringReader(document));
TokenizerFactory<? extends HasWord> factory=null;
factory=PTBTokenizer.factory();
factory.setOptions("untokenizable=noneDelete");
tokenizer.setTokenizerFactory(factory);
for (List<HasWord> sentence : tokenizer) {
}
你可以将第4行中的
noneDelete
替换为其他选项。我引用了Manning的话:
"(...)完整的六个选项集合,包括是否记录警告信息以及删除还是将它们作为单个字符标记包含在输出中: noneDelete、firstDelete、allDelete、noneKeep、firstKeep、allKeep."
这意味着,为了保留字符而不获取所有这些错误消息,最好的方法是使用选项
noneKeep
。这种方式比任何尝试删除这些字符更加优雅。
replaceAll
方法会创建一个新的String
对象,它不会修改原有的document
对象。你是否使用了document = document.replaceAll(...)
或者其他方式来获取返回值? - Ted Hopp