2015-11-20 6 views
5

मैं इस तरह से की तरह पाने के लिए वाक्य का पीओएस टैग एक के बाद एक सक्षम होना चाहते हैं:pos_tag() इतनी दर्दनाक धीमी क्यों है और क्या इससे बचा जा सकता है?

def __remove_stop_words(self, tokenized_text, stop_words): 

    sentences_pos = nltk.pos_tag(tokenized_text) 
    filtered_words = [word for (word, pos) in sentences_pos 
         if pos not in stop_words and word not in stop_words] 

    return filtered_words 

लेकिन समस्या यह है कि pos_tag() प्रत्येक वाक्य के लिए एक दूसरे के बारे में लेता है। इस बैच-वार और स्पीड चीजों को करने के लिए pos_tag_sents() का उपयोग करने का एक और विकल्प है। लेकिन अगर मैं वाक्य से यह वाक्य कर सकता हूं तो मेरा जीवन आसान होगा।

क्या यह तेजी से करने का कोई तरीका है?

+0

आप एनएलटीके का किस संस्करण का उपयोग कर रहे हैं? (यानी 'nltk .__ संस्करण__') – unutbu

+0

यह 3.1 (asdfasdf) – displayname

+0

पृष्ठभूमि: http://stackoverflow.com/questions/33676526/pos-tagger-is-incredibly-slow#comment55128218_33677051 – tripleee

उत्तर

14

nltk संस्करण 3.1 के लिए, nltk/tag/__init__.py अंदर, pos_tag इस तरह परिभाषित किया गया है:

from nltk.tag.perceptron import PerceptronTagger 
def pos_tag(tokens, tagset=None): 
    tagger = PerceptronTagger() 
    return _pos_tag(tokens, tagset, tagger)  

तो pos_tag पहले की गई प्रत्येक कॉल को दर्शाता है PerceptronTagger जो कुछ समय लगता है, क्योंकि यह loading a pickle file शामिल है। _pos_tagsimply calls tagger.tag जब tagsetNone है। तो तुम फ़ाइल एक बार लोड हो रहा है, और tagger.tag बुला खुद के बजाय pos_tag फोन करके कुछ समय बचा सकते हैं:

from nltk.tag.perceptron import PerceptronTagger 
tagger = PerceptronTagger() 
def __remove_stop_words(self, tokenized_text, stop_words, tagger=tagger): 
    sentences_pos = tagger.tag(tokenized_text) 
    filtered_words = [word for (word, pos) in sentences_pos 
         if pos not in stop_words and word not in stop_words] 

    return filtered_words 

pos_tag_sents ऊपर के रूप में ही चाल का उपयोग करता है - _pos_tag कई बार कॉल करने से पहले it instantiates PerceptronTagger once। तो आपको उपर्युक्त कोड का उपयोग करके प्रदर्शन में तुलनीय लाभ मिलेगा जैसा कि आप pos_tag_sents पर रीफैक्टरिंग और कॉल करके करेंगे।


इसके अलावा, अगर stop_words एक लंबी सूची है, तो आप समय का एक सा stop_words बनाकर एक सेट को बचाने कर सकते हैं:

stop_words = set(stop_words) 

एक सेट में सदस्यता जाँच (जैसे pos not in stop_words) के बाद से एक O(1) है (निरंतर समय) एक सूची में सदस्यता की जांच करते समय ऑपरेशन O(n) ऑपरेशन (यानी उस समय की आवश्यकता होती है जो सूची की लंबाई के अनुपात में बढ़ती है।)

+0

अब मैं यही बात कर रहा हूं! यह अजीब विचार है कि मुझे ऐसा करना है। मेरा मतलब है, यह कितनी बार होता है कि कोई सिर्फ * एक * एकल वाक्य टैग करना चाहता है? यह जानना दिलचस्प होगा कि डेवलपर्स ने क्यों फैसला किया कि यह एक अच्छा विचार है, लेकिन मुझे कामकाज करने में खुशी है। धन्यवाद! – displayname

+1

ठीक है, 'pos_tag() 'एक फ़ंक्शन है। यदि आप एक फ़ंक्शन को कॉल करते हैं तो आप उम्मीद कर रहे हैं कि फ़ंक्शन निष्पादित होने के बाद आपको परिणाम मिल जाएगा और स्मृति में चारों ओर कुछ भी नहीं है। – thorsten

+3

@StefanFalk, 'pos_tag' एक बतख प्रकार होने के लिए है। और इसे रखने के कारण का हिस्सा एनएलटीके <3.1 के साथ बैक-संगतता के लिए है। जब संभव हो तो हमेशा विशिष्ट टैगर का उपयोग करें। =) – alvas

संबंधित मुद्दे