学習

同梱モデルは、そのままですぐに使えます。自分のメールで学習したモデルのほうがよく働きます。購読しているニュースレター、同僚の文章、受け取るメールの言語など、自分のハムがどのようなものかを学習するためです。

モデルを学習させる#

trainにスパムとハムのフォルダーを指定します。

Shell
spamscanner train --spam ~/Maildir/.Junk --ham ~/Maildir/cur --ham ~/Maildir/.Archive --out my-model.json

使えるソース:

  • mboxファイル(gzip圧縮したもの.mbox.gzも含む)
  • Maildir(curとnewフォルダーを読み、tmpは読み飛ばします)
  • .emlファイルのフォルダー(再帰的に読みます)
  • データセット:テキストの列とラベルの列を持つCSVまたはJSON Linesのファイル(--dataset)。text、message、body、email、contentという名前の列と、label、category、class、spam、is_spamという名前の列は自動的に見つけます。それ以外の場合は--text-columnと--label-columnを使ってください。spam、1、phishingや、ham、0、not_spam、legitimateといったラベルを理解します。

重複したメッセージは1回だけ数えます。空の状態からではなく同梱モデルをもとに学習させるには、--mergeを追加します。

モデルを使う:

Shell
spamscanner scan message.eml --model my-model.json
SPAMSCANNER_MODEL=/var/lib/spamscanner/model.json spamscanner milter
JavaScript
const scanner = new SpamScanner({classifier: '/var/lib/spamscanner/model.json'});

必要なメールの量の目安:それぞれ数百通あれば役に立つモデルに、数千通あれば良いモデルになります。両者の数はおおよそ釣り合わせ、フィルタリングしたくないメール(パスワードのリセット、自社の取引先からの請求書など)はハムに入れてください。

計測する#

一部のメールを学習から外しておき、それで計測します。

Shell
spamscanner eval --model my-model.json --spam held-out/spam --ham held-out/ham

同梱モデルを、一度も見たことのない21言語のSMSメッセージで計測した結果です。その多くは、モデルがほとんど知らない言語です。

Text
Messages: 13028 spam, 92406 ham
Precision: 89.72%   Recall: 11.18%   F1: 19.89%
False positives: 167 (0.18% of ham)   False negatives: 132
Unsure: 91247 (86.54%)

適合率(Precision)は、スパムと判定したもののうち実際にスパムだった割合です。再現率(Recall)は、スパムのうち検出できた割合です。ここでは判定不能のメッセージをスパムの見逃しとして数えていますが、実際のスキャンではほかの検査や言語モデルがそれらを検出できます。注目すべき数値は誤検知、つまりスパムと判定されたハムです。上の実行結果では、モデルはこれらのメッセージの大半について誤った判定をするのではなく判定不能としています。これは、学習したメールが少ない言語で意図した動作です。

--jsonを使うと、同じ数値をスクリプト向けに出力します。

報告から学習する#

ユーザーがメールを迷惑メールフォルダーに移動したり、そこから戻したりしたときは、メッセージを1通ずつモデルに学習させます。

Shell
spamscanner learn spam message.eml --model /var/lib/spamscanner/model.json
spamscanner learn ham message.eml --model /var/lib/spamscanner/model.json

最初のlearnで、同梱モデルからファイルが作られます。HTTPでは、HTTP APIのPOST /learn/spamと/learn/hamが同じことを行い、--allow-tellを指定したspamdサーバーに対してはspamc -L spamが使えます。DovecotのIMAPSieveから、メッセージの移動時にどちらかを呼び出せます。

Node.jsからは次のようにします。

JavaScript
await scanner.learn(raw, 'spam');
await scanner.unlearn(raw, 'spam'); // undo, before learning it as ham
scanner.saveModel('/var/lib/spamscanner/model.json');

誤分類として報告されたメッセージを以前に学習させていた場合は、正しいクラスで学習させる前に、誤ったクラスから学習を取り消してください。

同梱モデル#

model/classifier.jsonは、npm run model:trainがHugging Faceにある次の公開データセットから作ります。いずれもオープンなライセンスです。

データセットライセンス内容
FredZhang7/all-scam-spamApache-2.043言語のメッセージとメール
SetFit/enron_spam公開研究用コーパスEnron-Spamコーパス
alt-gnome/telegram-spamCC0-1.0ロシア語のTelegramメッセージ
tanaos/synthetic-spam-detection-dataset-german、-italian、-spanishMIT合成メッセージ

このモデルは62,480通のスパムと76,489通のハムから学習しました。スクリプトは10通に1通を取り分け、残りで学習し、ほかの検査を使わずに分類器単体を計測します。

取り分けたテストメッセージ適合率再現率誤検知判定不能
英語6,564100.0%97.0%0.0%2.4%
ロシア語1,682100.0%97.4%0.0%2.2%
イタリア語1,38998.1%85.3%1.8%10.9%
ドイツ語1,30997.7%76.1%2.2%20.7%
スペイン語1,28197.5%82.5%2.6%16.8%
Enron-Spam2,888100.0%93.1%0.0%4.5%
all-scam-spam4,236100.0%88.8%0.0%11.2%
すべて13,84099.2%85.1%0.5%12.4%

ここでのスパムは、分類器の確率が99%以上のものを指します。これは分類器単体でスパムのしきい値に達する点です。実際のスキャンでは、確信度がそれより低いスパムにも点数が付き、ほかの検査もそれぞれの点数を加えます。

ドイツ語、スペイン語、イタリア語の結果は合成データセットによるもので、ほぼ同じ内容のメッセージがスパムとハムの両方のラベルで含まれています。そのため誤りの一部はモデルではなくラベルにあります。最善の対策は、自分の言語のメールです。すべての言語とデータセットの数値は、モデルのmetadata.metricsにあります。

言語を増やす#

npm run model:train -- --with multilingual-smsは、SMS Spam Multilingual Collectionを追加します。これはSMS Spam Collectionを21言語に機械翻訳したものです。データセットのカードにGPLライセンスと記載されているため、同梱モデルには含めていません。モデルを共有する方法に合うかどうか確認してください。これを加えて学習させると、同梱モデルがほとんど知らない言語での、取り分けたテストの結果は次のとおりでした。

言語メッセージ適合率再現率誤検知
中国語430100.0%82.3%0.0%
アラビア語430100.0%84.6%0.0%
韓国語412100.0%80.4%0.0%
日本語48696.0%85.7%0.5%
ヒンディー語412100.0%63.9%0.0%
フランス語48098.6%94.2%0.6%
トルコ語220100.0%73.1%0.0%

再学習させる#

Shell
npm run model:train                       # downloads the datasets into data/ the first time
npm run model:train -- --no-download      # reuse data/
npm run model:train -- --out /tmp/model.json --max-features 200000

モデルファイル#

モデルはJSONファイルです。学習したスパムとハムのメッセージ数と、ハッシュ化した各特徴を含んでいたスパムとハムのメッセージ数を、並べ替えてbase64でエンコードしたものが入っています。単語もメッセージのテキストも含みません。--max-featuresは最も頻度の高い特徴だけを残し、--min-countはまれな特徴を捨てます。どちらも精度と引き換えにサイズを小さくします。同梱モデルは40万の特徴を約6 MBで保持しています。

Spam Scanner 6以前のモデルは読み込めません。ハッシュ化する特徴が異なるためです。同じメールから新しいモデルを学習させてください。

このページをGitHubで編集 · Markdown ·