一个快速高效,不那么复杂的单词内容过滤器



在不进入贝叶斯级内容分类项目的情况下,我正在尝试为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的坏词列表(我们生活在一个多么的世界!),理想情况下,我想创建一个分数,不仅基于单词出现次数,而且基于每个单词出现的次数。因此,如果单词出现两次,分数将增加两次。

上面的分数生成器非常简单,但重新评估字符串数千次,而且它不会按照我想要的方式递增。

如何调整性能和准确性?

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

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

真的效率低下。

首先要做的是:让badwords成为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())

这将比完整循环更快,因为 Python 需要构建和破坏较少的临时上下文(这在技术上有点误导,但您可以节省大量 cpython pyObject 创建)。

尝试使用 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

如果每个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()))

最新更新