2017-05-02 10 views
2

私は、テキスト文/段落のリストからPythonで名前付きエンティティ(NLTKを使用)を削除するためのユーザー定義関数をいくつか書いています。私が抱えている問題は、私の方法が非常に遅い、特に大量のデータの場合です。誰もがこれを最適化してより速く走らせる方法を提案していますか?NLTKによる高速名前付きエンティティの削除

import nltk 
import string 

# Function to reverse tokenization 
def untokenize(tokens): 
    return("".join([" "+i if not i.startswith("'") and i not in string.punctuation else i for i in tokens]).strip()) 

# Remove named entities 
def ne_removal(text): 
    tokens = nltk.word_tokenize(text) 
    chunked = nltk.ne_chunk(nltk.pos_tag(tokens)) 
    tokens = [leaf[0] for leaf in chunked if type(leaf) != nltk.Tree] 
    return(untokenize(tokens)) 

コードを使用するには、私は通常、テキストリストを持っており、リスト内包を通じてne_removal関数を呼び出します。例:

text_list = ["Bob Smith went to the store.", "Jane Doe is my friend."] 
named_entities_removed = [ne_removal(text) for text in text_list] 
print(named_entities_removed) 
## OUT: ['went to the store.', 'is my friend.'] 

更新:このコードでバッチバージョンに切り替えることを試みましたが、わずかに高速です。探検を続けます。これまでの入力をありがとう。

def extract_nonentities(tree): 
    tokens = [leaf[0] for leaf in tree if type(leaf) != nltk.Tree] 
    return(untokenize(tokens)) 

def fast_ne_removal(text_list): 
    token_list = [nltk.word_tokenize(text) for text in text_list] 
    tagged = nltk.pos_tag_sents(token_list) 
    chunked = nltk.ne_chunk_sents(tagged) 
    non_entities = [] 
    for tree in chunked: 
     non_entities.append(extract_nonentities(tree)) 
    return(non_entities) 
+1

codereviewへの移行が適切であるとは確信していません。余りにも遅いコード_問題ですが、これは「私のコードをより良く構造化できますか」ということではありません。 – alexis

答えて

2

あなたがne_chunk()を呼び出すたびに、それはチャンカオブジェクトを初期化し、ディスクからのチャンクのための統計モデルをロードする必要があります。同上はpos_tag()です。だからではなく、一度に一つの文章でそれらを呼び出すのでは、テキストの完全なリストに自分のバッチバージョンを呼び出します。

all_data = [ nltk.word_tokenize(sent) for sent in list_of_all_sents ] 
tagged = nltk.pos_tag_sents(all_data) 
chunked = nltk.ne_chunk_sents(tagged) 

これはあなたにかなりのスピードアップを与える必要があります。それでもあなたのニーズにあまりにも遅い場合は、コードをプロファイリングして、@ Lenzのようなより高性能なツールに切り替える必要があるかどうかを検討してください。

+0

また、 'i not string.punctuation'テストでは、文字列を検索して' i'を検索します。 'string.punctuation'を(グローバルに定義された)セットに置き換えると、この行が飛躍的に高速化されます。これは、タグ付けとチャンク化がずっと時間がかかるため、ランタイム全体の重要な部分かどうか予測できませんでした。 – alexis

+0

ありがとう!私はバッチバージョン(元の投稿に追加されたコード)で遊んでいます。私は1,000文でそれを計時していますが、それはやや速いです(古い方法82.9対78.9秒)が、それほど顕著ではありません。私は、物事をスピードアップする簡単な方法として、spaCyの名前付きエンティティ・タグを使って探索するかもしれません。私は最初に 'string.punctuation'の変更を試みます。 – user1895076

+0

私はそれを聞いて少し驚いています。あなたのコードに何か問題がない限り、大きな違いがあったはずです。しかし、あなたが現在のコードを徹底的にプロファイリングし、どこに行くのか理解するまで、他のタグをインストールする時間を無駄にしないでください。たとえば、プライマリデータの非効率な管理など、愚かでないことを確認します。 – alexis

関連する問題