我想运行nltk punkt来分割句子。没有训练模型,所以我单独训练模型,但我不确定我使用的训练数据格式是否正确。
我的训练数据是每行一个句子。我无法找到任何关于此的文档,只有这个帖子(https://groups.google.com/forum/#!topic/nltk-users/bxIEnmgeCSM)提供了有关训练数据格式的一些信息。
nltk punkt句子标记化器的正确训练数据格式是什么?
答案 0 :(得分:18)
啊是的,Punkt tokenizer是神奇的无监督句子边界检测。作者的姓氏也很酷,Kiss and Strunk (2006)。我们的想法是使用 NO注释来训练句子边界检测器,因此输入将是任何类型的明文(只要编码是一致的)。
要训练新模型,只需使用:
import nltk.tokenize.punkt
import pickle
import codecs
tokenizer = nltk.tokenize.punkt.PunktSentenceTokenizer()
text = codecs.open("someplain.txt","r","utf8").read()
tokenizer.train(text)
out = open("someplain.pk","wb")
pickle.dump(tokenizer, out)
out.close()
为了获得更高的精确度并允许您随时停止训练并仍然为您的标记器保存适当的pickle,请查看此代码段以训练德语句子标记器,https://github.com/alvations/DLTK/blob/master/dltk/tokenize/tokenizer.py:
def train_punktsent(trainfile, modelfile):
""" Trains an unsupervised NLTK punkt sentence tokenizer. """
punkt = PunktTrainer()
try:
with codecs.open(trainfile, 'r','utf8') as fin:
punkt.train(fin.read(), finalize=False, verbose=False)
except KeyboardInterrupt:
print 'KeyboardInterrupt: Stopping the reading of the dump early!'
##HACK: Adds abbreviations from rb_tokenizer.
abbrv_sent = " ".join([i.strip() for i in \
codecs.open('abbrev.lex','r','utf8').readlines()])
abbrv_sent = "Start"+abbrv_sent+"End."
punkt.train(abbrv_sent,finalize=False, verbose=False)
# Finalize and outputs trained model.
punkt.finalize_training(verbose=True)
model = PunktSentenceTokenizer(punkt.get_params())
with open(modelfile, mode='wb') as fout:
pickle.dump(model, fout, protocol=pickle.HIGHEST_PROTOCOL)
return model
但请注意,周期检测对拉丁语fullstop,问号和感叹号非常敏感。如果你要为不使用拉丁拼写法的其他语言训练punkt tokenizer,你需要以某种方式破解代码以使用适当的句子边界标点符号。如果您正在使用NLTK的punkt实现,请编辑sent_end_chars
变量。
除了使用nltk.tokenize.sent_tokenize()
的“默认”英语标记器之外,还有预训练模型可用。它们是:https://github.com/evandrix/nltk_data/tree/master/tokenizers/punkt
请注意,预先训练的模型目前无法使用,因为上面列出的nltk_data
github仓库已被删除。