NLP - 哈利波特的命名实体识别速度(StanfordNER)

时间:2018-02-15 22:00:53

标签: python python-3.x nlp stanford-nlp ner

您好所有人!

所以我是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

1 个答案:

答案 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的调用,因为它的开销很大。