Training

Het meegeleverde model werkt direct. Een model dat op je eigen mail is getraind, werkt beter, omdat het leert hoe je hamGewenste mail: het tegenovergestelde van spam. eruitziet: je nieuwsbrieven, de schrijfstijl van je collega's, de talen die je ontvangt.

Een model trainen#

Wijs train naar mappen met spam en ham:

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

Bronnen kunnen zijn:

  • mbox-bestanden, ook gzip-gecomprimeerd (.mbox.gz),
  • een Maildir (de mappen cur en new worden gelezen, tmp wordt overgeslagen),
  • een map met .eml-bestanden, recursief gelezen,
  • een dataset: een CSV- of JSON Lines-bestand met een tekstkolom en een labelkolom (--dataset). Kolommen met de naam text, message, body, email of content, en label, category, class, spam of is_spam, worden vanzelf gevonden; gebruik anders --text-column en --label-column. Labels zoals spam, 1, phishing en ham, 0, not_spam, legitimate worden begrepen.

Dubbele berichten worden één keer geteld. Voeg --merge toe om op het meegeleverde model voort te bouwen in plaats van leeg te beginnen.

Gebruik het model:

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'});

Hoeveel mail genoeg is: een paar honderd berichten van elk soort geven een bruikbaar model, een paar duizend een goed model. Houd de twee ongeveer in balans, en houd mail die je niet wilt filteren (wachtwoordherstel, facturen van je eigen leveranciers) in de ham.

Het meten#

Houd wat mail buiten de training en meet daarop:

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

Het meegeleverde model op sms-berichten in 21 talen die het nooit had gezien, de meeste in talen die het nauwelijks kent:

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%)

Precisie is hoeveel van wat het spam noemt ook spam is; recall is hoeveel van de spam het vangt. Onzekere berichten tellen hier als gemiste spam, al kunnen de andere controles en het taalmodel ze in een scan nog vangen. Het getal om in de gaten te houden is het aantal fout-positieven: ham die als spam is gemarkeerd. In de run hierboven is het model over de meeste van deze berichten onzeker in plaats van ernaast te zitten. Dat is het bedoelde gedrag voor talen waarin het weinig mail heeft gezien.

--json geeft dezelfde getallen voor scripts.

Leren van meldingen#

Als gebruikers mail naar of uit een Junk-map verplaatsen, leer het model dan bericht voor bericht bij:

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

De eerste learn maakt het bestand aan vanuit het meegeleverde model. Via HTTP doen POST /learn/spam en /learn/ham op de HTTP API hetzelfde, en spamc -L spam werkt tegen de spamd-server met --allow-tell. IMAPSieve van Dovecot kan een van beide aanroepen als een bericht wordt verplaatst.

Vanuit 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');

Een bericht dat als verkeerd geclassificeerd is gemeld, moet uit de verkeerde klasse worden afgeleerd voordat het in de juiste wordt aangeleerd, als het eerder al was aangeleerd.

Het meegeleverde model#

model/classifier.json wordt door npm run model:train gebouwd uit deze openbare datasets op Hugging Face, allemaal met een open licentie:

DatasetLicentieInhoud
FredZhang7/all-scam-spamApache-2.0Berichten en e-mails in 43 talen
SetFit/enron_spamOpenbaar onderzoekscorpusHet Enron-Spam-corpus
alt-gnome/telegram-spamCC0-1.0Russische Telegram-berichten
tanaos/synthetic-spam-detection-dataset-german, -italian, -spanishMITSynthetische berichten

Het leerde van 62.480 spam- en 76.489 hamberichten. Het script houdt elk tiende bericht achter, traint op de rest en meet alleen de classifier, zonder de andere controles:

Achtergehouden testBerichtenPrecisieRecallFout-positievenOnzeker
Engels6.564100,0%97,0%0,0%2,4%
Russisch1.682100,0%97,4%0,0%2,2%
Italiaans1.38998,1%85,3%1,8%10,9%
Duits1.30997,7%76,1%2,2%20,7%
Spaans1.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%
Alle13.84099,2%85,1%0,5%12,4%

Spam betekent hier een classifierkans van 99% of meer, het punt waarop de classifier op zichzelf de spamdrempel haalt. In een scan krijgt spam waarover hij minder zeker is nog steeds punten, en de andere controles tellen de hunne erbij op.

De Duitse, Spaanse en Italiaanse resultaten komen uit synthetische datasets, die bijna identieke berichten bevatten met zowel het label spam als ham: een deel van die fout zit in de labels, niet in het model. Mail in je eigen talen is de beste oplossing. De getallen, met elke taal en dataset, staan in metadata.metrics van het model.

Meer talen#

npm run model:train -- --with multilingual-sms voegt de SMS Spam Multilingual Collection toe: de SMS Spam Collection, machinaal vertaald in 21 talen. Die is weggelaten uit het meegeleverde model omdat de datasetkaart een GPL-licentie noemt; controleer of dat past bij hoe je het model deelt. Daarmee getraind waren de resultaten op achtergehouden berichten voor talen die het meegeleverde model nauwelijks kent:

TaalBerichtenPrecisieRecallFout-positieven
Chinees430100,0%82,3%0,0%
Arabisch430100,0%84,6%0,0%
Koreaans412100,0%80,4%0,0%
Japans48696,0%85,7%0,5%
Hindi412100,0%63,9%0,0%
Frans48098,6%94,2%0,6%
Turks220100,0%73,1%0,0%

Opnieuw trainen#

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

Het modelbestand#

Een model is een JSON-bestand: het aantal geleerde spam- en hamberichten, en voor elk gehasht kenmerk hoeveel spam- en hamberichten het bevatten, gesorteerd en base64-gecodeerd. Het bevat geen woorden en geen berichttekst. --max-features houdt alleen de vaakst voorkomende kenmerken en --min-count laat zeldzame weg, wat nauwkeurigheid inruilt voor grootte; het meegeleverde model houdt 400.000 kenmerken in ongeveer 6 MB.

Modellen van Spam Scanner 6 en eerder kunnen niet worden geladen: die hashten andere kenmerken. Train een nieuw model op dezelfde mail.

Bewerk deze pagina op GitHub · Markdown ·