2016-04-15 17 views
0

Ich möchte alle seltenen Wörter mit einem Bezeichner 'UNK' in einem Korpus ersetzen können. Der folgende Code funktioniert, ist aber ziemlich langsam. Gibt es einen besseren, klügeren Weg? EDIT: Der Flaschenhals ist die rareWordstoUNK Funktion - die vorherigen Teile sind sehr schnell. Es gibt ungefähr 80.000 Reihen in meiner Pandas-Reihe.Seltene Wort-Token ersetzen: Python

X_train ist eine Pandas-Serie, bei der jede "Zeile" eine Liste von Wort-Token wie ['this','is','my','first', 'sentence'] ist. Ich durchlaufe und erstelle ein Wörterbuch der Worthäufigkeiten und erstelle dann eine Liste der nicht seltenen Wörter (frequency >1 in diesem Beispiel). Dann mag ich dies auf zukünftige Daten anzuwenden, wo, wenn das Wort selten oder vielleicht vor nicht gesehen worden war, wird das Token mit

‚UNK‘ ersetzt
wordFreqDict={} 

#dictionary of word counts  
    for tokenlist in X_train: 
     for token in tokenlist: 
      if token in wordFreqDict: 
       wordFreqDict[token]=wordFreqDict[token]+1 
      else: 
       wordFreqDict[token]=1 

    #non rare tokens   
    FreqWordsGT1=[k for k,v in wordFreqDict.iteritems() if v >1] 

    #pass in list and replace those not in keeplist with 'UNK' 
    def rareWordstoUNK(tokenlist,keeplist, replaceToken='UNK'): 
     return [w if w in keeplist else replaceToken for w in tokenlist ] 

#apply pandas series 


     X_train=X_train.apply(rareWordstoUNK, args=(FreqWordsGT1,'UNK')) 
+0

Prüfung [diese] (http://stackoverflow.com/a/36310156/5741205) - es ist ziemlich ähnlich Ihrer Aufgabe – MaxU

+0

Sie könnten auch von der Verwendung von 'frozenset' für die' keeplist' profitieren. – ChrisP

+0

@MaxU Dieses Beispiel zählt Wörter, aber das ist nicht das Problem - der Schmerzpunkt ist der Ersatz. –

Antwort

0

Ich denke, eine leichte Veränderung in Ansatz zu einem großen führen Leistungssteigerung Ihr keeplist ist sehr wahrscheinlich, eine große Anzahl von Elementen darin zu haben, als Ergebnis w in keeplist Vergleich wird wahrscheinlich langsam sein. Gemäß python time complexity data ist dies eine O (n) -Operation. Sie haben also effektiv eine verschachtelte Schleife innerhalb von rareWordstoUNK.

Warum nicht eine Liste seltener Wörter erstellen und stattdessen vergleichen? Diese Liste wird wahrscheinlich kleiner sein. O (m) < O (n)

Auch wie von @ChrisP vorgeschlagen, können Sie eine set statt einer Liste verwenden. x in s Operation ist O (1) gemäß dem obigen Link.

+0

Danke für den Vorschlag. Das Problem ist, dass ich im Wesentlichen sagen muss "alle Wörter, die nicht in der großen Liste sind, müssen neu codiert werden". Dies schließt Wörter ein, die in den Trainingsdaten nicht zu sehen waren, aber möglicherweise in zukünftigen Daten enthalten sind. –

0

Wie @ e4c5 bereits erwähnt:

w in keeplist Vergleich wahrscheinlich langsam

Get Artikel von dict sein kostet Sie: O (1)

so würde ich umschreiben Ihre Funktion in der folgenden Weise:

from collections import defaultdict 

# change your `wordFreqDict` to defaultdict 
wordFreqDict = defaultdict(lambda: 0) 

Code zum Auffüllen des wordFreqDict

def rareWordstoUNK(tokenlist, wordfreq, replaceToken='UNK'): 
    """ 
    will replace all words with frequency <= 1, 
    including those which haven't been seen yet (i.e. if this word is not in `wordfreq`) 
    """ 
    return [w if w in wordfreq[w] > 1 else replaceToken for w in tokenlist] 

X_train=X_train.apply(rareWordstoUNK, args=(wordFreqDict,'UNK')) 

und es dann wie folgt aufrufen:

X_train=X_train.apply(rareWordstoUNK, args=(wordFreqDict,'UNK'))