您好所有人!
所以我是Python的初学者,我目前在我的代码中遇到了一个问题......(我想这很常见)。
我正在使用Python 3中的自然语言处理(NLP),更具体地说是哈利波特系列书籍中的命名实体识别(NER)。我正在使用StanfordNER,它工作得非常好,但需要花费大量的时间......
我已经在网上做了一些研究,为什么会这么慢但是我似乎找不到任何真正适合我的代码的东西,老实说我认为这个问题在我编写代码的(坏)方式上更多
所以这就是我现在写的:
import string
from nltk.tokenize import sent_tokenize, word_tokenize
import nltk.tag.stanford as st
tagger = st.StanfordNERTagger('_path_/stanford-ner-2017-06-09/classifiers/english.all.3class.distsim.crf.ser.gz', '_path_/stanford-ner-2017-06-09/stanford-ner.jar')
#this is just to read the file
hp = open("books/hp1.txt", 'r', encoding='utf8')
lhp = hp.readlines()
#a small function I wrote to divide the book in sentences
def get_sentences(lbook):
sentences = []
for k in lbook:
j = sent_tokenize(k)
for i in j:
if bool(i):
sentences.append(i)
return sentences
#a function to divide a sentence into words
def get_words(sentence):
words = word_tokenize(sentence)
return words
sentences = get_sentences(lhp)
#and now the code I wrote to get all the words labeled as PERSON by the StanfordNER tagger
characters = []
for i in sentence:
characters = [tag[0] for tag in tagger.tag(get_words(sentences[i])) if tag[1]=="PERSON"]
print(characters)
现在问题正如我所解释的那样,代码需要花费大量时间......所以我想知道,这是正常还是我可以通过更好地重写代码来节省时间吗? / strong>如果是的话,你能帮助我吗?
我还面临另一个问题,我在网上找不到一条信息......
当我启动代码时,我得到的输出是:
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/nltk/tag/stanford.py:183:
DeprecationWarning:
The StanfordTokenizer will be deprecated in version 3.2.5.
Please use [91mnltk.tag.corenlp.CoreNLPPOSTagger[0m or [91mnltk.tag.corenlp.CoreNLPNERTagger[0m instead.
super(StanfordNERTagger, self).__init__(*args, **kwargs)
你知道我怎么解决这个问题吗?
无论如何,如果您碰巧有任何建议我会很高兴能够掌握它...非常感谢您提前!
最后,如果这有助于回答这个问题,我将在2017年的计算机上运行代码(1,8 GHz Intel Core i5和8GB 1600 MHz DDR3)。
先生。 Tibbles
答案 0 :(得分:3)
瓶颈是tagger.tag
方法,它有很大的开销。因此,为每个句子调用它会导致程序非常慢。除非还需要将书分成句子,否则我会立即处理整个文本:
with open('books/hp1.txt', 'r') as content_file:
all_text = content_file.read()
tags = tagger.tag(word_tokenize(all_text))
characters = [tag[0] for tag in tags if tag[1] == "PERSON"]
print(characters)
现在,如果你想知道的是,每个角色被提及的句子是什么,那么你可以先得到角色' characters
中的名称,如上面的代码中所示,然后循环检查句子是否存在来自characters
的元素。
如果文件大小是一个问题(尽管大多数书籍的.txt文件不应该成为加载到内存中的问题),那么您可以阅读一个数字n
而不是阅读整本书。一次性的句子。从您的代码中,修改您的for循环,如下所示:
n = 1000
for i in range(0, len(sentences), n):
scs = '. '.join(sentences[i:i + n])
characters = [tag[0] for tag in tagger.tag(get_words(scs)) if tag[1]=="PERSON"]
一般的想法是尽量减少对tagger.tag
的调用,因为它的开销很大。