テキストの文字列からストップワードを削除しようとしています:
_from nltk.corpus import stopwords
text = 'hello bye the the hi'
text = ' '.join([Word for Word in text.split() if Word not in (stopwords.words('english'))])
_
このようなストリングを6ミル処理しているので、速度が重要です。私のコードをプロファイリングすると、最も遅い部分は上の行ですが、これを行うより良い方法はありますか?正規表現の_re.sub
_などを使用することを考えていますが、一連の単語のパターンを記述する方法がわかりません。誰かが私に手を差し伸べることができますか、そして私は他のおそらくより速い方法を聞いてうれしいです。
注:stopwords.words('english')
をset()
でラップするという誰かの提案を試しましたが、違いはありませんでした。
ありがとうございました。
次に示すように、ストップワードオブジェクトをキャッシュしてみてください。関数を呼び出すたびにこれを作成することがボトルネックのようです。
from nltk.corpus import stopwords
cachedStopWords = stopwords.words("english")
def testFuncOld():
text = 'hello bye the the hi'
text = ' '.join([Word for Word in text.split() if Word not in stopwords.words("english")])
def testFuncNew():
text = 'hello bye the the hi'
text = ' '.join([Word for Word in text.split() if Word not in cachedStopWords])
if __name__ == "__main__":
for i in xrange(10000):
testFuncOld()
testFuncNew()
これをプロファイラーで実行しました:python -m cProfile -s incremental test.py。関連する行を以下に掲載します。
nCalls累積時間
10000 7.723 words.py:7(testFuncOld)
10000 0.140 words.py:11(testFuncNew)
したがって、ストップワードインスタンスをキャッシュすると、最大70倍のスピードアップが得られます。
正規表現を使用して、一致しないすべての単語を削除します。
import re
pattern = re.compile(r'\b(' + r'|'.join(stopwords.words('english')) + r')\b\s*')
text = pattern.sub('', text)
これはおそらく、特に大きな入力文字列の場合、ループするよりもway速くなります。
これによってテキストの最後のWordが削除された場合、末尾に空白がある可能性があります。これは別に処理することを提案します。
まず、文字列ごとにストップワードを作成します。一度作成してください。セットは本当にここで素晴らしいでしょう。
_forbidden_words = set(stopwords.words('english'))
_
その後、join
内の_[]
_を削除します。代わりにジェネレータを使用してください。
_' '.join([x for x in ['a', 'b', 'c']])
_
に置き換える
_' '.join(x for x in ['a', 'b', 'c'])
_
次に対処することは、配列を返す代わりに.split()
の値を生成することです。 私は regex
が良い代替品になると思います。s.split()
が実際に高速である理由については thist hread を参照してください。
最後に、このような作業を並行して実行します(6m文字列のストップワードを削除します)。それはまったく別のトピックです。
返事が遅れて申し訳ありません。新規ユーザーに役立つでしょう。
その辞書を非常に高速な検索に使用します(時間= O(1))リストで実行するのではなく(時間= O(ストップワード))
from collections import Counter
stop_words = stopwords.words('english')
stopwords_dict = Counter(stop_words)
text = ' '.join([Word for Word in text.split() if Word not in stopwords_dict])