2015-06-14 54 views
0

沒有進入貝葉斯級別的內容分類項目,我試圖爲twitter帳戶製作一個非常簡單的褻瀆過濾器。一個快速而高效的,不太複雜的詞語內容過濾器

從根本上,我只是加入一個用戶的所有微博爲一體的大型文本BLOB運行對我的過濾器中的內容,這在本質上是這樣的:

badwords = ['bad', 'worse', 'momwouldbeangry', 'thousandsofperversesayings', 'xxx', 'etc'] 

s = 'Get free xxx etc' 

score = 0 

for b in badwords: 
    if b in s: 
     score = score+1 

我有一個3K不好的單詞列表(我們生活的變態世界!),理想情況下我想創建一個不僅基於單詞出現的分數,而且每個單詞出現多少次。所以如果這個詞出現兩次,分數會增加兩次。

上面的分數發生器非常簡單,但重新評估字符串數千次,再加上它不增加我想要的方式。

如何調整性能和準確度?

+0

這種做法是極其脆弱的*「斯肯索普問題」 * ... – jonrsharpe

+0

使用KMP或文本常規experssions – Tempux

+0

使用'collections.Counter',然後檢查其在櫃檯詞出現在你的壞名單。 –

回答

2

所以len(badwords) == 3000,因此用tweet_words = len(s.split()))它是len(tweet_words) < len(badwords);因此

for b in badwords: 
    if b in s: 
     score = score+1 

確實效率低下。

首先要做的事:make badwords a frozenset。那樣的話,尋找其中的某些東西要快得多。

然後,搜索詞在badwords,而不是周圍的其他方式:

for t_word in tweet_words 
    if t_word in badwords: 
     score = score+1 

然後,有點更多的功能!

score_function = lambda word: 0 if len(word) < 3 or (word not in badwords) else 1 
score = lambda tweet: sum(score(lower(word)) for word in tweet.split()) 

,這將是比全循環更快,因爲蟒蛇需要構建和破壞較少臨時上下文(這在技術上是有點誤導,但你節省大量的CPython的PyObject創作)。

+0

不需要使用帶和的列表。 '總和(在tweet.split())中的單詞總分(低(單詞))' –

+1

@PadraicCunningham謝謝,我總是忘記從我的心理計劃中「刪除」我的代碼應該如何工作的列表構造我的思想構建了這樣的代碼片段)。我會編輯:) –

0

如果每個badword不能是一個子,你想爲每個你可以使用字典字計數,你還需要在你的用戶鳴叫,以降低和剝去的話任何標點符號:

from string import punctuation 
badwords = dict.fromkeys(('bad', 'worse', 'momwouldbeangry', 'thousandsofperversesayings', 'xxx', 'etc'),0) 

s = 'Get free xxx! etc!!' 

for word in s.split(): 
    word = word.lower().strip(punctuation) 
    if word in badwords: 
     badwords[word] += 1 


print(badwords) 
print(sum(badwords.values())) 
{'momwouldbeangry': 0, 'xxx': 1, 'etc': 1, 'bad': 0, 'thousandsofperversesayings': 0, 'worse': 0} 
2 

如果你不在乎什麼話剛剛出現的次數:

from string import punctuation 
badwords = {'bad', 'worse', 'momwouldbeangry', 'thousandsofperversesayings', 'xxx', 'etc'} 

s = 'Get free xxx! etc!!' 

print(sum(word.lower().strip(punctuation)in badwords for word in s.split())) 
0

嘗試使用collections.Counter;

In [1]: text = """Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum""" 

In [2]: badwords = ['in', 'ex'] 

In [3]: from collections import Counter 

In [9]: words = text.lower().split() 

In [10]: c = Counter(words) 

In [11]: c 
Out[11]: Counter({'ut': 3, 'in': 3, 'dolore': 2, 'dolor': 2, 'adipiscing': 1, 'est': 1, 'exercitation': 1, 'aute': 1, 'proident,': 1, 'elit,': 1, 'irure': 1, 'consequat.': 1, 'minim': 1, 'pariatur.': 1, 'nostrud': 1, 'laboris': 1, 'occaecat': 1, 'lorem': 1, 'esse': 1, 'quis': 1, 'anim': 1, 'amet,': 1, 'ipsum': 1, 'laborum': 1, 'sunt': 1, 'qui': 1, 'incididunt': 1, 'culpa': 1, 'consectetur': 1, 'aliquip': 1, 'duis': 1, 'cillum': 1, 'excepteur': 1, 'cupidatat': 1, 'labore': 1, 'magna': 1, 'do': 1, 'fugiat': 1, 'reprehenderit': 1, 'ullamco': 1, 'ad': 1, 'commodo': 1, 'tempor': 1, 'non': 1, 'et': 1, 'ex': 1, 'deserunt': 1, 'sit': 1, 'eu': 1, 'voluptate': 1, 'mollit': 1, 'eiusmod': 1, 'aliqua.': 1, 'nulla': 1, 'sed': 1, 'sint': 1, 'nisi': 1, 'enim': 1, 'veniam,': 1, 'velit': 1, 'id': 1, 'officia': 1, 'ea': 1}) 

In [12]: scores = [v for k, v in c.items() if k in badwords] 

In [13]: scores 
Out[13]: [1, 3] 

In [14]: sum(scores) 
Out[14]: 4 
+0

雖然我不確定性能,但這對於提供評分系統非常有用。 – 1Up

+0

正如你所看到的,我只使用列表理解循環分數。爲我的機器創建一個9 kB,1374字的語料庫計數器需要239μs。 –