keskiviikko 11. marraskuuta 2009

Oppivat järjestelmät

Tänään käytiin läpi kappale 8, joka prujussa on nimellä Hermoverkot, mutta uudessa versiossa on nimeltään Oppivat järjestelmät.

Oppivien järjestelmien ideana on esittää järjestelmälle näytteitä ja opettaa se tuottamaan oikea ulostulo kun sille esitetään opetusjoukkoon kuulumaton uusi näyte. Yksi oppivien järjestelmien osajoukko ovat luokittelijat, jossa ulostulo kertoo luokan johon esitetty näyte kuuluu.

Suosittuja luokittelualgoritmeja ovat ainakin seuraavat (kasvavan monimutkaisuuden järjestyksessä):
Kaikki näistä käsiteltiin luennolla, ja luentomonisteen uudessa versiossa esitellään kolme viimeisintä. KNN on ideana yksinkertaisin: kaikki opetusdata pidetään muistissa ja uuden näytteen tullessa etsitään k samanlaisinta näytettä, ja valitaan näistä yleisin luokka. Tyypillisesti k on vajaan kymmenen luokkaa, mutta voi olla suurempikin; esim. 30. Mitä suurempi k on, sitä sileämpi luokkarajasta tulee. Vaikka KNN:n luokittelutulos onkin melko hyvä, on sen ongelmana suuri muistin tarve sekä laskennallinen kompleksisuus. Koko opetusjoukko täytyy nimittäin säilyttää muistissa, josta etsitään k lähintä naapuria jokaisen luokittelun yhteydessä. Sekä tilantarve että etsinnän vaatima aika voivat olla ongelmallisia jos opetusjoukossa on esim. 100000 alkiota.

Luentomonisteen ensimmäinen menetelmä on LDA. Ennen sitä pruju esittelee yksinkertaisemman version samasta ideasta, jossa raja piirretään luokkien keskipisteiden puoliväliin. Tämä ei kuitenkaan toimi, jos luokat ovat "limittäin". Näin päädytäänkin LDA:han, joka ottaa limittäisyyden huomioon.

LDA:ta parempi tulos saadaan (yleensä) käyttämällä SVM:ää. SVM:n ominaisuutena on luokkien välisen marginaalin maksimointi. Tästä on iloa eritoten, jos data on korkeaulotteista. Lisäksi se tarjoaa paremman vaihtoehdon haluttaessa käyttää ns. kernelitemppua, joka kuvaa datan keinotekoisesti korkeampiulotteiseen avaruuteen. Korkeampiulotteisessa avaruudessa on enemmän tilaa, ja siellä on tyypillisesti helpompi löytää lineaarinen päätöspinta joukkojen väliin. Dataa ei konkreettisesti tarvitse kuitenkaan kuvata toiseen avaruuteen, koska kernelitemppu tekee saman yksinkertaisesti korvaamalla kaikki sisätulot sopivalla kernel-funktiolla.

SVM on ollut suosituin luokittelualgoritmi tällä vuosikymmenellä, koska se ei ole herkkä ylioppimisilmiölle. Lisäksi suosion syynä on sen yksinkertainen ja laskennallisesti tehokas toteutus, mutta mukana lienee myös hypeä liittyen optimointialgoritmin syvälliseen matematiikkaan jonka vain harva ymmärtää kunnolla.

Tämän jälkeen paneuduttiin hermoverkkojen opetukseen, ja mainittiin lyhyesti opetusalgoritmin perustuvan derivaattaan ja ketjusääntöön. Näiden avulla voidaan päätellä suunta, jossa luokitteluvirhe pienenee jyrkimmin, ja kyseiset kaavat löytyvät esim. täältä. Perus- backpropagationin lisäksi on olemassa kehittyneempiä ja nopeampia opetusalgoritmeja, ja esim. Matlabissa niitä on lähes parikymmentä. Olennaisin ero algoritmien välillä on niiden nopeudessa ja muistin tarpeessa.

Luennon lopussa laitettiin verkon opetus pyörimään, ja opetettiin sitä luokittelemaan suomalaisissa rekisterikilvissä olevia kirjaimia ja numeroita (vrt. prujun esimerkki). Opetusaineistona oli n. 7000 kirjainta ja ajo kesti vain 5 minuuttia. Tulosta demottiin skriptillä, jossa hiirellä voitiin näyttää merkin summittainen sijainti isossa kuvassa, ja verkko luokitteli sen johonkin luokkaan. Todettiin, että luokittelun suhteen oli kriittistä mikä kohta tarkalleen verkolle syötettiin. Yleisemminkin käytetty GIGO-periaate pitää siis paikkansa tässäkin yhteydessä. Luennolla ei otettu kantaa siihen miten järjestelmä löytää verkolle syötettävät merkit, mutta joitain yleisimpiä ratkaisuja kuvaillaan wikipedian feature detection -artikkelissa.

Lisäksi aivan alussa vilkaistiin OpenCV-pakettia, jonka kasvontunnistusesimerkkiä demottiin luennolla sekä alkuviikon opintosuunnistuksessa. OpenCV on vapaan lähdekoodin C++-kielinen paketti, joka on hyvä lähtökohta tutustua konenäköön lähemmin (CV = computer vision). Kasvontunnistusdemo toimii useiden webbikameroiden kanssa "heittämällä". OpenCV:n kasvontunnistus perustuu yksinkertaisten luokittelijoiden yhdistämiseen, niin että jokainen pyrki löytämään mahdollisimman suuren osan ei-kasvoista. Koska näitä on paljon enemmän kuin kasvoja, tulee toteutuksesta tehokas. Menetelmä esiteltiin v. 2004 ja sitä on kutsuttu läpimurroksi.

Perinteisempi tapa etsii kasvokandidaatteja ihonvärin perusteella ja syöttää ne hermoverkolle. Koska kasvojen ala kuvassa voi olla melko suuri, pudotetaan kasvokandidaatin dimensiota esim. 100 x 100 = 10000 komponentista esim. neljäänkymmeneen käyttäen ns. pääkomponenttianalyysiä.

OpenCV on myös muuten lupaava alusta konenäköprojektien toteutukseen Matlabin sijaan. Toinen yleinen vaihtoehto on Java-kielinen ImageJ.

Ei kommentteja:

Lähetä kommentti