keskiviikko 25. marraskuuta 2009

Epälineaarinen suodatus ja tilastollinen signaalinkäsittely

Päivän aihe oli epälineaarinen signaalinkäsittely (kappale 7), jonka lisäksi tutkailtiin varovasti tilastollisen signaalinkäsittelyn aihepiiriä. Epälineaariset suotimet saattavat tarjota vaihtoehdon lineaarisille suotimille (FIR ja IIR) silloin kun häiriö ja signaali sijaitsevat samalla taajuusalueella. Klassisin epälineaarinen suodin on mediaanisuodin, jonka ulostulo on suuruusjärjestyksessä keskimmäinen ikkunan sisällä olevista arvoista. Tätä vertailtiin demossa lineaarisen suotimen kanssa sekä äänen että kuvan suodatuksessa. Lopuksi tarkasteltiin vielä suotimen robustisuusmittoja, ja erityisesti murtumapistettä.

Viimeisen 15 minuutin aikana luotiin katsaus tilastolliseen signaalinkäsittelyyn ja erityisesti parametrien estimointiin. Ideana on luoda malli signaalista, joka riippuu tietyistä parametreista. Ongelmana on tämän jälkeen kehittää menetelmä näiden parametrien valintaan mitatun datan perusteella. Esimerkkinä voisi olla signaali, jonka tiedetään olevan sinimuotoinen, mutta amplitudi, vaihe sekä taajuus eivät ole tiedossa. Tähän ongelmaan on olemassa estimaattori, joka arvioi optimaalisesti kohinaisesta datasta näitä kolmea parametria.

Seuraavaksi vilkaistiin esimerkkiä käytännön elämästä, jossa erään järjestelmän tilasta voidaan tehdä mittaus, jonka perusteella halutaan säätää järjestelmän erästä toista parametria. Käsin mittaamalla voidaan kehittää opetusaineisto "hyvistä" kombinaatioista (xk, yk), k = 1,2,...,N. Nämä ovat siis käsin mitattuja arvoja: kun mittaus on xk, kannattaa säätöruuvin olla asennossa yk. Näiden perusteella halutaan laskea funktio y = f(x), jolla voidaan ennustaa hyvä lukuarvo y:lle myös kun x ei ole mikään käsin mitatuista. Tätä varten muodostetaan ns. havaintomatriisi (observation matrix), jossa on mukana ne funktiot, joista f pystytään toivottavasti koostamaan. Esimerkiksi seuraavat rivit laskevat parhaan toisen asteen polynomin arvioimaan xk:n ja yk:n välistä riippuvuutta:

x = [1,2,3,4,5,6,7,8];
y = [18,15,12,11,11,11,13,16];
H = [ones(8,1), x, x.^2];

t = inv(H'*H)*H'*y;


Tuloksena saadaan vektoriksi t = [22.5893, -4.9821, 0.5179]T, eli paras toisen asteen relaatio vektoreiden x ja y välille on y = 22.5893 - 4.9821 * x + 0.5179 * x2. Menetelmä on ns. pienimmän neliösumman estimaatti, jonka Gauss keksi jo 18-vuotiaana pohdiskellessaan mallia Ceres-kääpiöplaneetan radalle.

Viimeisen 15 minuutin tavoitteena oli osin antaa rehellinen kuva signaalinkäsittelyn oppiaineesta: aihe vaatii matematiikan osaamista (tai ainakaan kaavoja ei saa pelätä). Toisaalta matematiikkaa pelkäämättömälle aihe tarjoaa hienon mahdollisuuden toteuttaa itseään mielenkiintoisten sovellusten parissa. Kriittisiä taitoja signaalinkäsittelijälle on mm. ohjelmointitaito, koska menetelmät miltei aina tullaan toteuttamaan ohjelmiston osana. Näin ollen ilman ohjelmointitaitoa ei kannata valmistua signaalinkäsittely pääaineenaan.

keskiviikko 18. marraskuuta 2009

Signaaliprosessorit

Tämän päivän luennolla käsiteltiin kappale signaaliprosessoreista. Tärkeimmät syyt niiden käyttöön ovat yksinkertaisuus, halvempi hinta sekä pienempi virrankulutus. Kuitenkin niistä saa riittävästi tehoa signaalinkäsittelyn tarpeisiin, koska alan tarvitsemat operaatiot ovat nopeita (kertolasku, yhteenlasku). Esimerkiksi FIR-suodatuksen tarvitsemat kertolaskut ja yhteenlaskut voidaan suurelta osin laskea rinnakkain ns. MAC-operaation avulla. Vastaavia operaatioita on nykyisin myös tavallisissa prosessoreissa, ja ensimmäinen tällainen laajennus oli Intelin MMX-käskykanta vuodelta 1997.

Ensi viikon viikkoharjoituksissa koodataan FIR-suodin luokan TC303 signaaliprosessoreille. Olennaisimmat vaiheet olivat:
  1. Suodin suunniteltiin Matlabin fir1-rutiinilla.
  2. Kertoimet kopioitiin C-koodiin.
  3. C-kieliseen pohjaan kirjoitettiin for-silmukka, jossa kertoimet käydään läpi.
  4. Ulostulonäyte kirjoitetaan D/A-muuntimelle.
Vaiheessa 3 on kiinnitettävä huomiota circular buffering-tekniikkaan, jotta viitataan oikeisiin aiemmin sisään tulleisiin alkioihin.

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.

keskiviikko 4. marraskuuta 2009

Audiokompressio

Tänään käsiteltiin kappale 6: audiokompressio. Audiokompression ideana on tallentaa äänisignaali häviöllisesti poistaen bittejä sieltä missä kuulo ei niitä havaitse. Tässä auttaa kuulon ominaisuuksien tuntemus, joista olennaisin osa on s. 81 kuulokäyrä. Kuulo havaitsee matalia ja korkeitä ääniä heikommin kuin keskiääniä. Tämän vuoksi epätarkemmin havaittavat taajuudet voidaan esittää pienemmällä bittimäärällä. Tässä yhteydessä on hyvä muistaa että jokainen poistettu bitti lisää kvantisointikohinaa kuudella desibelillä. Kysymys voidaan siis asettaa muotoon: "montako kuuden desibelin palikkaa kuulokäyrän alle mahtuu kullakin taajuudella". Lisätilaa kuuden desibelin palikoille saadaan havaitsemalla, että äänet peittävät heikompia ääniä alleen. Tässä tapauksessa siis itse kompressoitava signaali peittää näitä heikompia kuuden desibelin palikoita. Luennolla nähtiin myös esimerkki siitä miltä tulosmaski saattaisi näyttää yksittäisen piippauksen ympäristössä.

Jotta kuulomallia voitaisiin käyttää, täytyy signaali jakaa taajuuskaistoihin. Tämä tehdään kaistanpäästösuotimilla, ja kaistoja mp3-standardissa on 32. Kukin kaista voidaan alinäytteistää kertoimella 32, jolloin dataa on saman verran kuin alun perin. Nämä kaistat voidaan sitten kvantisoida kuulomallin mukaisesti. Palautettaessa alkuperäistä näytteenottotaajuutta riittää tehdä ylinäytteistys (nollien lisääminen) kertoimella 32, jolloin havaitaan, että aiemmin laskostunut signaali pomppaakin oikealle paikalleen ja vieläpä oikein päin --- siinäkin tapauksessa, että se olisi sattunut laskostumaan peilikuvakseen.