计算垃圾邮件概率

Hob*_*use 3 probability bayesian

我正在python/django建立一个网站,想要预测用户提交是否有效或者是垃圾邮件.

用户对其提交的内容具有接受率,如本网站所示.

用户可以审核其他用户的提交内容; 这些调节后来由管理员进行元模式化.

鉴于这种:

  • 提交接受率为60%的注册用户A提交了一些内容.
  • 用户B将A的帖子作为有效提交进行审核.但是,用户B在70%的时间内都是错误的.
  • 用户C将A的帖子视为垃圾邮件.用户C通常是对的.如果用户C说某些内容是垃圾邮件/没有垃圾邮件,则80%的时间都是正确的.

如何预测A的帖子被垃圾邮件的可能性?

编辑:我制作了一个模拟这种情况的python脚本:

#!/usr/bin/env python

import random

def submit(p):
    """Return 'ham' with (p*100)% probability"""
    return 'ham' if random.random() < p else 'spam'

def moderate(p, ham_or_spam):
    """Moderate ham as ham and spam as spam with (p*100)% probability"""
    if ham_or_spam == 'spam':
        return 'spam' if random.random() < p else 'ham'
    if ham_or_spam == 'ham':
        return 'ham' if random.random() < p else 'spam'

NUMBER_OF_SUBMISSIONS = 100000 
USER_A_HAM_RATIO = 0.6 # Will submit 60% ham
USER_B_PRECISION = 0.3 # Will moderate a submission correctly 30% of the time
USER_C_PRECISION = 0.8 # Will moderate a submission correctly 80% of the time

user_a_submissions = [submit(USER_A_HAM_RATIO) \
                        for i in xrange(NUMBER_OF_SUBMISSIONS)]

print "User A has made %d submissions. %d of them are 'ham'." \
        % ( len(user_a_submissions), user_a_submissions.count('ham'))

user_b_moderations = [ moderate( USER_B_PRECISION, ham_or_spam) \
                        for ham_or_spam in user_a_submissions]

user_b_moderations_which_are_correct = \
    [i for i, j in zip(user_a_submissions, user_b_moderations) if i == j]

print "User B has correctly moderated %d submissions." % \
    len(user_b_moderations_which_are_correct)

user_c_moderations = [ moderate( USER_C_PRECISION, ham_or_spam) \
                        for ham_or_spam in user_a_submissions]

user_c_moderations_which_are_correct = \
    [i for i, j in zip(user_a_submissions, user_c_moderations) if i == j]

print "User C has correctly moderated %d submissions." % \
    len(user_c_moderations_which_are_correct)

i = 0
j = 0    
k = 0 
for a, b, c in zip(user_a_submissions, user_b_moderations, user_c_moderations):
    if b == 'spam' and c == 'ham':
        i += 1
        if a == 'spam':
            j += 1
        elif a == "ham":
            k += 1

print "'spam' was identified as 'spam' by user B and 'ham' by user C %d times." % j
print "'ham' was identified as 'spam' by user B and 'ham' by user C %d times." % k
print "If user B says it's spam and user C says it's ham, it will be spam \
        %.2f percent of the time, and ham %.2f percent of the time." % \
         ( float(j)/i*100, float(k)/i*100)
Run Code Online (Sandbox Code Playgroud)

运行脚本给我这个输出:

  • 用户A提交了100000个提交.其中60194是'火腿'.
  • 用户B已正确审核了29864个提交.
  • 用户C已正确审核了79990个提交.
  • "垃圾邮件"被用户B识别为"垃圾邮件",用户C识别为"火腿"2346次.
  • 'ham'被用户B识别为'垃圾','ham'被用户C 33634次识别为'垃圾'.
  • 如果用户B说它是垃圾邮件而用户C说这是垃圾邮件,则垃圾邮件的垃圾邮件占6.52%,垃圾邮件占93.48%.

这里概率合理吗?这是模拟场景的正确方法吗?

Ale*_*lli 5

贝叶斯定理告诉我们:

<代码> P(A | B)= P(B | A)P(A)/ P(B)</代码>

让我们将事件A和B的字母更改为X和Y resp.因为你使用A,B和C代表人,这会让事情变得混乱:

P(X|Y) = P(Y|X) P(X) / P(Y)
Run Code Online (Sandbox Code Playgroud)

编辑:以下是略有错误,因为X应该是this post _by A_ is spam,而不仅仅是"这篇文章是垃圾邮件"(因此Y应该只是"B接受A的帖子,C拒绝它").我不是在这里重做数学,因为无论如何数字都会改变 - 请参阅下面的其他编辑以获得正确的数字正确的算术.

你想要X的意思是"这个帖子是垃圾邮件",Y代表情况的组合A has posted it, B approved it, C rejected it(让我们假设有条件的情况有条件独立).

我们需要P(X)一个先验概率,即任何帖子(无论是谁制作或批准它)都是垃圾邮件; P(Y),由B批准,由C拒绝的帖子的先验概率(无论是否为垃圾邮件); 并且P(Y | X),与后者相同,但帖子是垃圾邮件.

正如您可能注意到的那样,您还没有真正给我们提供计算所需的所有零碎.你有三点告诉我们:A给出的帖子是垃圾邮件,概率为0.4(这似乎是第一点的读数); B的接受概率为0.3,但我们不知道垃圾邮件和非垃圾邮件有何不同,除了应该存在"小"差异(低精度); C是0.8,我们不知道这是如何受垃圾邮件和非垃圾邮件的影响,除了应该有"大"差异(高准确性).

所以我们需要更多数字!事实上C在接受80%的帖子时具有高准确度,这告诉我们整体垃圾邮件必须低得惊人 - 如果垃圾邮件总体上与A相同,则为40%,那么C必须接受其中的一半(即使他是总是接受非垃圾邮件是完美的,以获得80%的总体接受率,这几乎不是"高准确度".所以说垃圾邮件整体只有20%而且C只接受1/4(并拒绝1/16的非垃圾邮件),确实非常好的准确性,并且整体匹配你给出的数字.

猜测B,总体上接受30%,现在"知道"垃圾邮件总体上是20%,我们可以猜测B接受1/4的垃圾邮件和只有5/16的非垃圾邮件.

所以:P(X)=0.2; P(Y)=0.3*0.2=0.06(B的总接受时间C的拒绝概率); P(Y|X)=0.4*0.25*0.75=0.075(垃圾邮件发送时间B的概率B接受垃圾邮件时间的概率C拒绝垃圾邮件的可能性).

所以P(X|Y)=0.075*0.2/0.06=0.25- 除非我做了一些算术错误(很可能,重点是向你展示在这种情况下如何推理;-),这个特定帖子被垃圾邮件的概率是0.25 - 略高于任何随机帖子是垃圾邮件的概率,低于A是垃圾邮件的随机帖子的概率.

但是当然(即使在条件独立的简化假设下,所有地方; =)这个计算对我的猜测/假设高度敏感,关于B和C的假阳性与假阴性的比率,以及整体垃圾邮件比率.有五种此类数字涉及(总体垃圾邮件问题,垃圾邮件和非垃圾邮件中B和C各自的条件概率),您只给出了两个相关(线性)约束(B和C的无条件接受概率)和两个模糊的"handwaving"陈述(关于低精度和高精度),所以那里有很多自由度.

如果您可以更好地估计五个关键数字,则可以使计算更精确.

而且,顺便说一下,Python(以及更为重要的Django)与这个案例完全无关 - 我建议你删除那些不相关的标签以获得更广泛的响应!

编辑:用户澄清(在评论中 - shd真的编辑他的Q!):

当我说"B的节制'接受率仅为30%"时,我的意思是,每10次B调节一些垃圾邮件/没有垃圾邮件,他做出错误的决定7次.因此,有70%的可能性他会标记垃圾邮件/没有垃圾邮件.对于用户C,"他的审核接受率为80%"意味着如果C表示某些内容是垃圾邮件或没有垃圾邮件,那么他在80%的时间都是正确的.注册用户发送垃圾邮件的总体机率为20%.

...并要求我重做数学(我假设假阳性和阴性对B和C各有可能).请注意,B是一个出色的"反向指标",因为他70%的时间都是错误的! - ).

无论如何:B的A的帖子的总体接受率必须是0.6*0.3(当他接受A的nonspam时)+ 0.4*0.7(当他接受A的垃圾邮件时)= 0.18 + 0.28 = 0.46; C必须为0.8*0.4 + 0.2*0.6 = 0.32 + 0.12 = 0.44.所以我们......:

P(X)=0.4(我之前错过了0.2,因为我忽略了A的垃圾邮件概率为0.4 的事实- 垃圾邮件的整体概率不相关,因为我们知道邮件是A的!); P(Y)=0.46*0.56=0.2576(B对A次C的拒绝概率的总体接受率;); P(Y|X)=0.7*0.8=0.56(B接受垃圾邮件时间的概率C拒绝垃圾邮件的可能性).

所以P(X|Y)=0.56*0.4/0.2576=0.87(四舍五入).IOW:虽然先验A是垃圾邮件的概率是0.4,B的接受和C的拒绝都会提高它,所以A的这个特定帖子有大约87%的机会成为垃圾邮件.