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:
spamscanner train --spam ~/Maildir/.Junk --ham ~/Maildir/cur --ham ~/Maildir/.Archive --out my-model.jsonBronnen kunnen zijn:
- mbox-bestanden, ook gzip-gecomprimeerd (
.mbox.gz), - een Maildir (de mappen
curennewworden gelezen,tmpwordt 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 naamtext,message,body,emailofcontent, enlabel,category,class,spamofis_spam, worden vanzelf gevonden; gebruik anders--text-columnen--label-column. Labels zoalsspam,1,phishingenham,0,not_spam,legitimateworden 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:
spamscanner scan message.eml --model my-model.json
SPAMSCANNER_MODEL=/var/lib/spamscanner/model.json spamscanner milterconst 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:
spamscanner eval --model my-model.json --spam held-out/spam --ham held-out/hamHet meegeleverde model op sms-berichten in 21 talen die het nooit had gezien, de meeste in talen die het nauwelijks kent:
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:
spamscanner learn spam message.eml --model /var/lib/spamscanner/model.json
spamscanner learn ham message.eml --model /var/lib/spamscanner/model.jsonDe 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:
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:
| Dataset | Licentie | Inhoud |
|---|---|---|
| FredZhang7/all-scam-spam | Apache-2.0 | Berichten en e-mails in 43 talen |
| SetFit/enron_spam | Openbaar onderzoekscorpus | Het Enron-Spam-corpus |
| alt-gnome/telegram-spam | CC0-1.0 | Russische Telegram-berichten |
| tanaos/synthetic-spam-detection-dataset-german, -italian, -spanish | MIT | Synthetische 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 test | Berichten | Precisie | Recall | Fout-positieven | Onzeker |
|---|---|---|---|---|---|
| Engels | 6.564 | 100,0% | 97,0% | 0,0% | 2,4% |
| Russisch | 1.682 | 100,0% | 97,4% | 0,0% | 2,2% |
| Italiaans | 1.389 | 98,1% | 85,3% | 1,8% | 10,9% |
| Duits | 1.309 | 97,7% | 76,1% | 2,2% | 20,7% |
| Spaans | 1.281 | 97,5% | 82,5% | 2,6% | 16,8% |
| Enron-Spam | 2.888 | 100,0% | 93,1% | 0,0% | 4,5% |
| all-scam-spam | 4.236 | 100,0% | 88,8% | 0,0% | 11,2% |
| Alle | 13.840 | 99,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:
| Taal | Berichten | Precisie | Recall | Fout-positieven |
|---|---|---|---|---|
| Chinees | 430 | 100,0% | 82,3% | 0,0% |
| Arabisch | 430 | 100,0% | 84,6% | 0,0% |
| Koreaans | 412 | 100,0% | 80,4% | 0,0% |
| Japans | 486 | 96,0% | 85,7% | 0,5% |
| Hindi | 412 | 100,0% | 63,9% | 0,0% |
| Frans | 480 | 98,6% | 94,2% | 0,6% |
| Turks | 220 | 100,0% | 73,1% | 0,0% |
Opnieuw trainen#
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 200000Het 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.