2015-06-14 55 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。 –