我正在使用CoreNLP 3.6.0创建一个自定义的NER模型
我的属性设置如下:
# 训练文件的位置 trainFile = /home/damiano/stanford-ner.tsv # 你希望保存(序列化)你的分类器的位置;在文件末尾添加.gz会自动压缩文件, # 使其更小,并加载更快 serializeTo = ner-model.ser.gz# 你的训练文件的结构;这告诉分类器 # 单词在第0列,正确答案在第1列 map = word=0,answer=1# 这指定了CRF的顺序:顺序1意味着特征 # 最多应用于前一个类和当前类或当前类和下一个类的类对。 maxLeft=1# 这些是我们希望训练的特征 # 有些在下面讨论,其余的可以通过 # 查看NERFeatureFactory来理解 useClassFeature=true useWord=true # 单词字符ngram将被包含,最大长度为6,作为前缀 # 和后缀 useNGrams=true noMidNGrams=true maxNGramLeng=6 usePrev=true useNext=true useDisjunctive=true useSequences=true usePrevSequences=true # 最后4个属性处理单词形状特征 useTypeSeqs=true useTypeSeqs2=true useTypeySequences=true wordShape=chris2useLC
我使用以下命令构建:
java -classpath "stanford-ner.jar:lib/*" edu.stanford.nlp.ie.crf.CRFClassifier -prop /home/damiano/stanford-ner.prop
问题是当我使用这个模型从文本文件中提取实体时。命令是:
java -classpath "stanford-ner.jar:lib/*" edu.stanford.nlp.ie.crf.CRFClassifier -loadClassifier ner-model.ser.gz -textFile file.txt
其中file.txt的内容是:
Hello!mynameisJohn.
输出是:
Hello/O !/O my/O name/O is/O John/PERSON ./O
如你所见,它将”Hello!”分成了两个标记。”John.”也是如此。
我必须使用空白分词器。
我如何设置它?
为什么CoreNLP会将这些词分成两个标记?
回答:
你可以通过指定类名到tokenizerFactory
标志/属性来设置你自己的分词器:
tokenizerFactory = edu.stanford.nlp.process.WhitespaceTokenizer$WhitespaceTokenizerFactory
你可以指定任何实现Tokenizer<T>
接口的类,但包含的WhitespaceTokenizer
听起来像是你想要的。如果分词器有选项,你可以用tokenizerOptions
指定它们。例如,如果你还指定:
tokenizerOptions = tokenizeNLs=true
那么输入中的换行符将在输入中保留(对于不总是将事物转换为每行一个标记格式的输出选项)。
注意:像tokenize.whitespace=true
这样的选项适用于CoreNLP级别。如果提供给像CRFClassifier这样的单个组件,它们不会被解释(你会得到一个警告说该选项被忽略)。
正如Nikita Astrakhantsev指出的,这不一定是件好事。在测试时这样做只有在你的训练数据也是空白分隔的情况下才是正确的,否则会对性能产生不利影响。而且像你从空白分隔得到的标记对于后续的NLP处理(如解析)是不利的。