Iti0210lab91: erinevus redaktsioonide vahel
Resümee puudub |
|||
| 25. rida: | 25. rida: | ||
Laadi siit [http://nlp.cs.aueb.gr/software_and_datasets/Enron-Spam/preprocessed/enron6.tar.gz treeningandmed] ja paki lahti. Võid kasutada ka muid andmeid, aga ära kasuta ''enron1'' osa samast korpusest, kuna sealt pärinevad testandmed. | Laadi siit [http://nlp.cs.aueb.gr/software_and_datasets/Enron-Spam/preprocessed/enron6.tar.gz treeningandmed] ja paki lahti. Võid kasutada ka muid andmeid, aga ära kasuta ''enron1'' osa samast korpusest, kuna sealt pärinevad testandmed. | ||
Teisendame | Teisendame tekstifailid sõnade listideks, edaspidi viitame nendele listidele kui dokumentidele. Selle juures on kasulik ka sõnu filtreerida, jättes välja näiteks sidesõnad. Esialgu teeme lihtsamalt ja filtreerime lihtsalt sõnad, mis on lühemad kui 4 tähemärki. | ||
<pre> | <pre> | ||
| 38. rida: | 38. rida: | ||
<pre> | <pre> | ||
import os | |||
def read_dir(dirn): | def read_dir(dirn): | ||
cont_l = [] | cont_l = [] | ||
| 59. rida: | 61. rida: | ||
print(len(spam_l), "spam messages") | print(len(spam_l), "spam messages") | ||
</pre> | </pre> | ||
== Treenimine == | |||
Rämpsposti mudeli tegemiseks võtame uuesti teooria kokku ja kohandame selle meie ülesande jaoks. | |||
Meil on kiri, mis sisaldab sõnu ''w<sub>1</sub>, w<sub>2</sub>, ...,''. Nende sõnade põhjal tuleb hinnata, kumb tõenäosus on suurem: rämpspost ''P(spam|w<sub>1</sub>, ..., w<sub>n</sub>)'' või tavaline kiri ''P(ham|w<sub>1</sub>, ..., w<sub>n</sub>)''. Selleks arvutame hinnangud: | |||
''H<sub>spam</sub> = P(spam) * P(w<sub>1</sub>|spam) * P(w<sub>2</sub>|spam) *... * P(w<sub>n</sub>|spam)'' | |||
''H<sub>ham</sub> = P(ham) * P(w<sub>1</sub>|ham) * ... * P(w<sub>n</sub>|ham)''. | |||
Kõik väärtused valemites saab leida dokumentide pealt statistikat tehes. ''P(spam)'' ja ''P(ham)'' on eeltõenäosused. Kui meil on treenimiseks 1000 kirja, millest 900 on rämpspost, võime öelda, et ''P(spam) = 0.9''. See tähendab, et meil on mingi eelneval kogemusel põhinev eelarvamus selle kohta, kas klassifitseeritav kiri on rämps või mitte. | |||
''w<sub>i</sub>'' tähistab sõna dokumendis positsioonil ''i''. Nüüd teeme kaks eeldust, mis ei ole loomuliku keele puhul kumbki korrektne, aga lihtsustab meie elu tunduvalt: | |||
* sõna esinemise tõenäosus dokumendis ei sõltu täpselt kohast (''i'') | |||
* sõna esinemise tõenäosus ei sõltu teistest sõnadest - see on NB mudeli põhieeldus. | |||
Oletame, et sõna "Tere" esineb suvalisel kohal tavalises kirjas tõenäosusega 0.001. Kui meil on tavalistes kirjades (''ham'') kokku 200000 sõna, siis nendest umbes 200 on järelikult "Tere". Sõna esinemise tõenäosust ''P(w<sub>j</sub>|c)'', kus ''c'' on tähistab klassi - kas ''spam'' või ''ham'' - hindame järgmise valemiga: | |||
[[Image:Iti0210lab91_laplace.gif|korrigeeritud tõenäosus]] | |||
<!-- | <!-- | ||
Et klassifikaatorit treenida, tuleb leida: | Et klassifikaatorit treenida, tuleb leida: | ||
* iga klassi ''c<sub>i</sub>'' esinemise sagedus treeningnäidetes (annab eeltõenäosuse) | * iga klassi ''c<sub>i</sub>'' esinemise sagedus treeningnäidetes (annab eeltõenäosuse) | ||
Redaktsioon: 3. aprill 2019, kell 21:12
"Naiivne" Bayesi klassifikaator
Sissejuhatus
Klassifitseerimise ülesandes on vaja objekti tunnuste järgi otsustada, millisesse klassi mingi objekt kuulub. Näiteks tuntud iiriste klassifitseerimise ülesandes saab taime teatud osade mõõtude järgi otsustada, millisesse iirise alamliiki ta kuulub. Klassifitseerimiseks saab kasutada ka Naiivse Bayesi (lühidalt NB) tõenäosusmudelit, mis põhineb eeldusel, et kui meil on peidetud põhjus, siis selle nähtavad tagajärjed on kõik üksteisest sõltumatud. See eeldus võimaldab tagajärgede alusel põhjuse tõenäosust leida üsna lihtsa valemi järgi.
Kui meil on teada klassifitseeritava objekti mingid tunnused x1, ..., xn ning mingid võimalikud klassid c1, c2, ..., siis tõenäosus, et objekti klass on ci on proportsionaalne järgmise valemiga:
Täpset tõenäosust see valem ei anna, küll aga annab ta seda suurema numbri, mida suurem on tõenäosus. Seega tuleb see valem arvutada välja iga võimaliku klassi ci kohta ja siis saadud tulemusi võrrelda, et leida kõige tõenäolisem klass. Vaja on iga klassifitseeringu esinemise tõenäosust P(ci) ning iga tunnuse tinglikku tõenäosusjaotust iga klassi kohta P(Xj|ci).
NB mudeli üks esimesi ja tuntumaid rakendusi on rämpsposti klassifitseerimine. Idee on lihtne - rämpspostis esinevad rohkem ühesugused sõnad (buy Go1d watches CHE4P!!), päris kirjades teistsugused. Sõnad on tunnusteks, nende esinemise peidetud põhjus on aga see, kas kiri on rämpspost või tavaline.
Kirjuta programm, mis:
- etteantud treeningnäidetest, kus on antud nii tunnused kui ka klass, ehitab vajalikud tõenäosustabelid;
- leiab ainult tunnuste alusel objekti klassi
Treeni oma mudel kasutades väikest rämpsmeilide korpust [1]. Allpool leiad juhised selle alla laadimiseks ja kasutamiseks. Seejärel proovi, kas õnnestub kahte toodud kirja klassifitseerida.
Taustainfo: lühidalt, detailsemalt saad lugeda loengukava alt viidatud materjalidest.
Ettevalmistus
Laadi siit treeningandmed ja paki lahti. Võid kasutada ka muid andmeid, aga ära kasuta enron1 osa samast korpusest, kuna sealt pärinevad testandmed.
Teisendame tekstifailid sõnade listideks, edaspidi viitame nendele listidele kui dokumentidele. Selle juures on kasulik ka sõnu filtreerida, jättes välja näiteks sidesõnad. Esialgu teeme lihtsamalt ja filtreerime lihtsalt sõnad, mis on lühemad kui 4 tähemärki.
def stopword(wstr):
w = wstr.strip()
if len(w) < 4:
return True
return False
Ja siin on laadimise funktsioon ise:
import os
def read_dir(dirn):
cont_l = []
for fn in os.listdir(dirn):
with open(os.path.join(dirn, fn), encoding="latin-1") as f:
words = [w.strip()
for w in f.read().replace("\n", " ").split(" ")
if not stopword(w)
]
cont_l.append(words)
return cont_l
Kasutada saad seda nii:
ham_l = read_dir("enron6\\ham")
spam_l = read_dir("enron6\\spam")
print(len(ham_l), "ham messages") # meaning, these are not spam
print(len(spam_l), "spam messages")
Treenimine
Rämpsposti mudeli tegemiseks võtame uuesti teooria kokku ja kohandame selle meie ülesande jaoks.
Meil on kiri, mis sisaldab sõnu w1, w2, ...,. Nende sõnade põhjal tuleb hinnata, kumb tõenäosus on suurem: rämpspost P(spam|w1, ..., wn) või tavaline kiri P(ham|w1, ..., wn). Selleks arvutame hinnangud:
Hspam = P(spam) * P(w1|spam) * P(w2|spam) *... * P(wn|spam)
Hham = P(ham) * P(w1|ham) * ... * P(wn|ham).
Kõik väärtused valemites saab leida dokumentide pealt statistikat tehes. P(spam) ja P(ham) on eeltõenäosused. Kui meil on treenimiseks 1000 kirja, millest 900 on rämpspost, võime öelda, et P(spam) = 0.9. See tähendab, et meil on mingi eelneval kogemusel põhinev eelarvamus selle kohta, kas klassifitseeritav kiri on rämps või mitte.
wi tähistab sõna dokumendis positsioonil i. Nüüd teeme kaks eeldust, mis ei ole loomuliku keele puhul kumbki korrektne, aga lihtsustab meie elu tunduvalt:
- sõna esinemise tõenäosus dokumendis ei sõltu täpselt kohast (i)
- sõna esinemise tõenäosus ei sõltu teistest sõnadest - see on NB mudeli põhieeldus.
Oletame, et sõna "Tere" esineb suvalisel kohal tavalises kirjas tõenäosusega 0.001. Kui meil on tavalistes kirjades (ham) kokku 200000 sõna, siis nendest umbes 200 on järelikult "Tere". Sõna esinemise tõenäosust P(wj|c), kus c on tähistab klassi - kas spam või ham - hindame järgmise valemiga: