首先,我将文件内容标记为句子,然后在每个句子上调用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)
答案 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')]

的更多细节
答案 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')]
它产生了一些我非常喜欢的功能:
doc.sentences
访问每个句子。