3

私は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)

スクリプトを実行すると、次の出力が得られます。

  • ユーザーAは100000件の提出を行いました。それらの60194は「ハム」です。
  • ユーザーBは29864件の送信を正しくモデレートしました。
  • ユーザーCは79990の送信を正しくモデレートしました。
  • 「spam」は、ユーザーBによって「spam」として識別され、ユーザーCによって「ham」として2346回識別されました。
  • 「ham」は、ユーザーBによって「spam」として識別され、ユーザーCによって「ham」として33634回識別されました。
  • ユーザーBがスパムだと言い、ユーザーCがハムだと言った場合、6.52%の確率でスパムになり、93.48%の確率でハムになります。

ここでの確率は妥当ですか?これはシナリオをシミュレートする正しい方法でしょうか?

4

3 に答える 3

5

ベイズの定理から次のことがわかります。

<code>P(A|B)=P(B|A)P(A)/P(B)</code>

イベント A と B の文字をそれぞれ X と Y に変更しましょう。人を表すために A、B、C を使用しているため、混乱を招く可能性があります。

P(X|Y) = P(Y|X) P(X) / P(Y)

編集: 以下は、「この投稿はスパムです」だけでなく、「B は A の投稿を受け入れ、C はそれを拒否する」であるX必要があるため、少し間違っています。this post _by A_ is spamとにかく数字が変更されるため、ここで数学をやり直すことはありません。正しい数字正しい算術については、以下の他の編集を参照してください。

X「この投稿はスパムです」という意味Yで、状況の組み合わせを表しますA has posted it, B approved it, C rejected it(問題の状況は条件付きで独立していると仮定しましょう)。

必要なP(X)のは、投稿 (誰が投稿したか承認したかに関係なく) がスパムであるというアプリオリな確率です。P(Y)、投稿が A によって作成され、B によって承認され、C によって拒否される (スパムかどうかに関係なく) 確率。とP(Y | X)、後者と同じですが、投稿がスパムです。

お気づきかもしれませんが、計算に必要なすべての要素が実際には提供されていません。あなたの 3 つのポイントは次のことを示しています。B の受け入れ確率は 0.3 ですが、スパムと非スパムでどのように異なるかはわかりませんが、違いは「ほとんど」ない (精度が低い) はずです。C は 0.8 であり、これがスパムと非スパムによってどのように影響されるかはわかりませんが、「大きな」違い (高い精度) があるはずです。

だから、もっと数が必要です!C が投稿の 80% を受け入れる一方で精度が高いという事実は、スパム全体が驚くほど少ないに違いないことを示しています。常に非スパムを受け入れることで完璧でした) 全体の受け入れ率 80% を取得しましたが、それは「高精度」とは言い難いでしょう。つまり、スパム全体がわずか 20% で、C はその 1/4 しか受け入れず (非スパムの 1/16 を拒否)、実際にかなり良い精度であり、全体的にあなたが与えている数値と一致しているとします。

全体の 30% で受け入れる B を推測し、全体のスパムが 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(A のスパム送信確率 B のスパム受信確率 C のスパム拒否確率)。

だからP(X|Y)=0.075*0.2/0.06=0.25-- 私が何らかの算術エラーを犯していない限り (そのような場合にどのように推論できるかを示すことが主な目的です;-)、この特定の投稿がスパムである確率は 0.25 です。ランダムな投稿がスパムである確率は、 A によるランダムな投稿がスパムである確率よりも低くなります。

しかし、もちろん (あらゆる場所での条件付き独立性の単純化仮説の下でも;=) この計算は、B と C の偽陽性と偽陰性の比率、および全体的なスパム比率に関する私の推測/仮説に非常に敏感です。関連するこの種の数値は 5 つあり (全体的なスパムの確率、スパムと非スパムの B と C のそれぞれの条件付き確率)、2 つの関連する (線形) 制約 (B と C の受け入れの無条件の確率) のみを指定します。 2 つのあいまいな「手を振っている」ステートメント (精度の低さと高さについて) があるため、そこには十分な自由度があります。

5 つの主要な数値をより正確に見積もることができれば、計算をより正確に行うことができます。

そして、ところで、Python (および fortiori Django) はこのケースとはまったく関係がありません。より広い範囲の応答を得るために、これらの無関係なタグを削除することをお勧めします!

編集: ユーザーが明確にします (コメントで -- shd 本当に彼の Q を編集してください!):

「B のモデレーションの承認率はわずか 30% です」と私が言ったのは、B がスパムをモデレートする 10 回ごとに、7 回間違った決定を下すことを意味します。したがって、彼が何かスパムにタグを付ける/そうでない場合に、スパムではないタグを付ける可能性は 70% です。ユーザー C にとって、「モデレーションの承認率が 80% である」とは、C がスパムである、またはスパムではないと言った場合、80% の確率で正しいことを意味します。登録ユーザーがスパムを送信する可能性は全体で 20% です。

...そして、計算をやり直すように求められます (B と C のそれぞれについて、偽陽性と偽陰性の可能性が同じであると想定しています)。B は 70% の確率で間違っているので、優れた「逆張り指標」であることに注意してください!-)。

とにかく、A の投稿に対する B の全体的な受け入れ率は、0.6*0.3 (A の非スパムを受け入れた場合) + 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(A に対する 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% です。

于 2010-06-07T15:37:18.247 に答える
2

ベイジアン分類を使用してスパムを検出し、変更の結果に基づいてスパムとハムのトレーニング セットを選択することができます。結果は、ユーザーが投稿を受け入れた割合によって重み付けされる可能性もあります。

スパムである可能性が高い結果は、モデレーション ワークフローにプッシュされる可能性があります (専任のモデレーターがいる場合)。同様に、以前のモデレーションの結果のサンプルをメタモデレーション ワークフローに送信して、分類の品質を確認することもできます (つまり、許容できないほど高い誤検出率と誤検出率があるか)。

最後に、ユーザーが投稿が不当に分類されていることに不満を言うことができる「アピール」は、投稿をメタモデレーションワークフローにプッシュすることもできます. ユーザーが異議申し立てを拒否したり、異議申し立てを送信する頻度が高すぎる場合 (DOS 攻撃の試みなど)、ユーザーの投稿には、異議申し立てワークフローで次第に低い優先度が割り当てられる可能性があります。

于 2010-06-07T15:15:37.753 に答える
-1

私たちはより経験的にそれに取り組みます。

スパムの最良の指標の1つは、投稿/コメント内の外部リンクの数です。スパムの全体的なポイントは、どこかに行って何かを購入したり、友好的なgooglebotにリンクされていると思わせることだからです。 -ページへの方が面白いです。

未登録ユーザーに対する一般的なルールは次のとおりです。1つのリンクは問題ない可能性があり、2つは80%以上のスパムである可能性があり、3つ以上は乾杯です。拒否された投稿に表示されるメインドメイン名のリストを保持し、1つまたは2つのリンカーであってもそれらがトリガーになります。RBLを使用することもできますが、RBLは非常に厳しいものになる可能性があるため、注意が必要です。

この単純なことではうまくいかないかもしれませんが、モデレーターの負担が大幅に軽減され、実際の人間からの苦情はありませんでした。

于 2010-06-07T16:17:45.930 に答える