如何使用python nltk

时间:2015-11-17 03:17:45

标签: python nlp nltk stanford-nlp named-entity-recognition

首先,我将文件内容标记为句子,然后在每个句子上调用Stanford NER。但这个过程非常缓慢。我知道如果我在整个文件内容上调用它会更快,但我会在每个句子上调用它,因为我想在NE识别之前和之后索引每个句子。

st = NERTagger('stanford-ner/classifiers/english.all.3class.distsim.crf.ser.gz', 'stanford-ner/stanford-ner.jar')
for filename in filelist:
    sentences = sent_tokenize(filecontent) #break file content into sentences
    for j,sent in enumerate(sentences): 
        words = word_tokenize(sent) #tokenize sentences into words
        ne_tags = st.tag(words) #get tagged NEs from Stanford NER

这可能是因为为每个句子调用st.tag(),但有没有办法让它运行得更快?

修改

我想将句子分开标记的原因是我想将句子写入文件(如句子索引),以便在后期给出带有标签的句子,我可以得到未处理的句子(我也是在这里做引理)

文件格式:

  

(sent_number,orig_sentence,NE_and_lemmatized_sentence)

4 个答案:

答案 0 :(得分:8)

StanfordNERTagger开始,有tag_sents()个功能,请参阅https://github.com/nltk/nltk/blob/develop/nltk/tag/stanford.py#L68

>>> st = NERTagger('stanford-ner/classifiers/english.all.3class.distsim.crf.ser.gz', 'stanford-ner/stanford-ner.jar')
>>> tokenized_sents = [[word_tokenize(sent) for sent in sent_tokenize(filecontent)] for filename in filelist]
>>> st.tag_sents(tokenized_sents)

答案 1 :(得分:5)

你可以使用stanford ner服务器。 速度会快得多。

安装sner

pip install sner

运行服务器



cd your_stanford_ner_dir
java -Djava.ext.dirs=./lib -cp stanford-ner.jar edu.stanford.nlp.ie.NERServer -port 9199 -loadClassifier ./classifiers/english.all.3class.distsim.crf.ser.gz






from sner import Ner

test_string = "Alice went to the Museum of Natural History."
tagger = Ner(host='localhost',port=9199)
print(tagger.get_entities(test_string))




此代码结果为



[('Alice', 'PERSON'),
 ('went', 'O'),
 ('to', 'O'),
 ('the', 'O'),
 ('Museum', 'ORGANIZATION'),
 ('of', 'ORGANIZATION'),
 ('Natural', 'ORGANIZATION'),
 ('History', 'ORGANIZATION'),
 ('.', 'O')]




查看https://github.com/caihaoyu/sner

的更多细节

答案 2 :(得分:1)

首先从这里下载Stanford CoreNLP 3.5.2:http://nlp.stanford.edu/software/corenlp.shtml

让我们说你把下载放在/ User / username / stanford-corenlp-full-2015-04-20

此Python代码将运行管道:

stanford_distribution_dir = "/User/username/stanford-corenlp-full-2015-04-20"
list_of_sentences_path = "/Users/username/list_of_sentences.txt"
stanford_command = "cd %s ; java -Xmx2g -cp \"*\" edu.stanford.nlp.pipeline.StanfordCoreNLP -annotators tokenize,ssplit,pos,lemma,ner -ssplit.eolonly -filelist %s -outputFormat json" % (stanford_distribution_dir, list_of_sentences_path)
os.system(stanford_command)

以下是一些示例Python代码,用于加载.json文件以供参考:

import json
sample_json = json.loads(file("sample_file.txt.json").read()

此时,sample_json将是一个很好的字典,其中包含文件中的所有句子。

for sentence in sample_json["sentences"]:
  tokens = []
  ner_tags = []
  for token in sentence["tokens"]:
    tokens.append(token["word"])
    ner_tags.append(token["ner"])
  print (tokens, ner_tags)

list_of_sentences.txt应该是包含句子的文件列表,例如:

input_file_1.txt
input_file_2.txt
...
input_file_100.txt

因此,一旦运行Java命令并且.json文件将具有NER标记,input_file.txt(每行应该有一个句子)将生成input_file.txt.json。您可以为每个输入文件加载.json,并轻松获取(句子,ner标签序列)对。你可以试试" text"作为替代输出格式,如果你更喜欢这样。但是" json"将创建一个很好的.json文件,您可以使用json.loads(...)加载它,然后您将有一个很好的字典,您可以使用它来访问句子和注释。

这样,您只需为所有文件加载一次管道。

答案 3 :(得分:0)

尝试了几个选项后,我喜欢Stanza。它是由斯坦福开发的,实现起来非常简单,我不需要自己弄清楚如何正确启动服务器,它极大地提高了我的程序速度。它实现了 18 种不同的对象分类。

我在搜索 the documentation 时找到了 Stanza。

下载: pip install stanza

然后在 Python 中:

import stanza
stanza.download('en') # download English model
nlp = stanza.Pipeline('en') # initialize English neural pipeline
doc = nlp("My name is John Doe.") # run annotation over a sentence or multiple sentences

如果你只想要一个特定的工具 (NER),你可以用 processors 指定为: nlp = stanza.Pipeline('en',processors='tokenize,ner')

对于类似于 OP 产生的输出:

classified_text = [(token.text,token.ner) for i, sentence in enumerate(doc.sentences) for token in sentence.tokens]
print(classified_text)
[('My', 'O'), ('name', 'O'), ('is', 'O'), ('John', 'B-PERSON'), ('Doe', 'E-PERSON')]

但是要生成仅包含可识别实体的单词的列表:

classified_text = [(ent.text,ent.type) for ent in doc.ents]
[('John Doe', 'PERSON')]

它产生了一些我非常喜欢的功能:

  1. 您可以使用 doc.sentences 访问每个句子。
  2. 不是将每个词都归类为一个单独的人实体,而是将 John Doe 组合成一个“PERSON”对象。
  3. 如果您确实想要每个单独的词,您可以提取它们并识别它是对象的哪个部分('B' 表示对象中的第一个单词,'I' 表示中间词,'E' 表示对象中的最后一个词)