Kohti toimivaa puhekäyttöliittymää kotiautomaatioon.

Alkutilanne

Mikä on suomenkielisen puheen käytön tilanne puheentunnistuksessa ja voiko sitä käyttää luotettavasti esimerkiksi kotiautomaation ohjaukseen? Käyttötapa poikkeaa saneluiden ylöskirjoittamisesta siinä että virheitä ei oikeastaan voi olla paljoa, koska niitä ei voi näppäimistöllä korjailla. Toisaalta sanasto on yleensä yksinkertainen ja lyhyitä komentoja. Kun liitin kielimallin kotiautomaation, voin tosin antaa monimutkaisiakin ohjeita, sanella sähköposteja tai keskustella kielimallin kanssa päivän uutisista. Tämä kaikki edellyttää että puheentunnistus toimii riittävän hyvällä tasolla. 

Mikä sitten on riittävän hyvä taso? Yritän välttää "se on ihan huono" tason kommenteilta, siksi mieluummin mittaroin tarkasti, jotta ymmärrän mistä on kyse, mikä on ongelma, ja mikä on riittävä taso. Toki lopullinen päätös on minun. Minä päätän onko taso riittävä, jos mittari näyttää Wer=3%. Mutta mittarointi mahdollistaa myös järkevän kommunikoinnin ja tiedon levittämisen. Jos näen toisen tekemän testin, voin sen tuloksilla, niillä numeroilla, tehdä automaattisen päätöksen onko tulos minun mielestäni hyvä. Jos toisen kommentti on "se on ihan huono", en voi siitä päätellä oikeastaan mitään. 


Laitteisto

Kotiautomaation puheohjaukseen monet käyttävät satelliittikaiuttimia, kuten toimivat vaikkapa Googlen Echo tai Apple Siri. Minulla siis yksi ehdottomista vaatimuksista oli että kotiautomaatiossa kaikki toimii lokaalisti, ja puheentunnistus tehdään myös paikallisesti. Satelliittikaiutinratkaisussa on kuitenkin selkeitä huonoja puolia. Puhetta yleensä aloitetaan tunnistamaan herätesanoilla, jolloin laitteen pitää jatkuvasti kuunnella ympäristöään. Samoin laitteet vaaditaan jokaiseen huoneeseen, missä puheohjauksen halutaan toimivan. Mitä paremmin laitteet kuuntelevat, sitä enemmän ne myös kuuntelevat ympäristön hälyääniä, kun annat ohjeita. 

Näistä syistä johtuen päättelin jo aikoja sitten että "lälläri"-tyylinen ratkaisu olisi minulle toimivampi, eli että puheentunnistus alkaisi vasta kun fyysisesti painaisin jotain nappia. Kuulokemikrofonit puolestaan eivät oikein innostaneet, koska en halua pitää kuulokkeita päässä jatkuvasti, etenkin kun kuuntelen musiikkia kaiuttimista aika paljon. Joten "täydelliseksi" ratkaisuksi osoittautui Sony hartioilla pidettävät bluetooth-kuulokemikrofonit SRS-NB10. 




Pääsen myös ohjelmallisesti lukemaan kuulokkeiden play/pause-napin tuplaklikkausta, joten voin sillä aloittaa puheentunnistuksen. 
Niinkuin arvelinkin, ympäristön hälyäänet kuuluvat tähänkin, eli jos samaan aikaan soi musiikki, niin puheentunnistus voi sieltä poimia lauseita ja puheettomien pätkien tunnistaminen ei toimi. Tällöin Whisper-puheentunnistuksen hallusinoinnit myös tulevat esiin. Kiitos kun katsoit videon! 

Mittarointi

Puheentunnistuksessa mittarointiin käytetään sanavirheitä ( WER, Word Error Rate ) ja kirjainvirheitä ( CER, Character Error Rate ). Niiden laskeminen on sinänsä melko suoraviivaista eli WER kertoo kuinka monessa prosentissa sanoja oli virheitä. Tämä on vielä matematiikkaa eli selkeää. Siksi tämä on lyhyt kappale. 

Testiaineisto

Puheentunnistuksen testaukseen käytetään melko standardeja testijoukkoja kuten Googlen Fleurs tai Mozillan Common Voice. Päätin ensin alkaa testailla Fleursilla, koska niiden testi antoivat huonompia tuloksia suomenkielelle, joten ajattelin että se on rankempi testi. Mutta sitten kun ajoin testejä, huomasin että suuri osa virhetulkinnoista on virheellisestä normalisoinnista, vaikeista nimistä tai jopa virheistä aineistossa. 

Jos aineistossa on mainittu nimi Schwarzenegger, niin kuinka moni ihminen osaa kirjoittaa sen oikein vain nimen kuulessaan? Siinä ei ollut enää kyse puheentunnistuksesta, vaan siitä että se tunnistettiin nimeksi, eli puheentunnistuksen kielimalliosuuteen on tallennettu tuo nimi. Koska aineisto on alunperin englantilainen, niin tietenkään nimi Zyskowicz ei onnistunut ollenkaan. Joten kun tuollaisia nimiä on testiaineistossa, onko se todella olennaista puheentunnistuksen näkökulmasta. Aineistossa on todella paljon erimaalaisia nimiä, joiden kirjoitusasua minäkään en ennalta tiennyt. Testaus ei siis minusta anna hyvää kuvaa kuinka hyvin tavallisten sanojen tunnistus toimii. 

Aineistossa oli myös selkeitä virheitä. Yksi kielioppivirhe oli niin että kun kolme lukijaa sen luki, niin kaksi luki niinkuin se oli kirjoitettu ja kolmas luki ilmeisesti automaattisesti virheen korjaten. Miten puheentunnistuksen siis pitäisi tuossa tilanteessa toimia? Sehän nyt luki tietenkin sen kolmannen lukijan tekstin oikein, mutta se näkyi WER/CER-mittareissa virheenä.  

Sitten on ongelma tekstin normalisoinnissa eli teksti pitäisi saada samanlaiseksi, jotta WER/CER-mittarit toimivat. Perustasollaan tuo tarkoittaa että pisteet, pilkut ja ylimääräiset välilyönnit poistetaan sekä isot kirjaimet muutetaan pieniksi. Mutta se ei oikeasti riitä. Jos/kun aineistossa on numeroita, jotkut puheentunnistukset näyttävät ne numeroina, jotkut kirjaimina. Jos aineistossa on lyhenteitä kuten mm., pitäisikö se näyttää lyhenteenä vai aukikirjoitettuna? Mistä puheentunnistus voi tietää kumpaa käytettiin tekstissä? Näitä ongelmia oli paljon Fleur-aineistossa, josta ensin vain kylmästi poistin niitä rivejä, joita en pitänyt kovin hyvinä mittareina puheentunnistuksen toimivuudesta. Toinen tapa olisi kehittää normalisointi, joka toimii suomenkielellä, jolloin voitaisiin oikeasti luotettavasti vertailla puheentunnistussovelluksia. 

Kun huomasin että Fleursista poistettavia rivejä olisi ollut jo aika suuri määrä, päätin kokeilla testinä Common Voicea. Mozilla on vasta syksyllä siirtänyt pois aineistonsa Hugginfacesta, joten netin skriptit sen lataukseen eivät enää toimineet, ja kävin lataamassa viimeisimmä CV23:n manuaalisesti. Siinäkin oli ongelmia, eli aineisto sisälsi "-merkkejä eri variaatioineen niin että yhdellä rivillä saattoi olla vain toinen niistä, jolloin Datasets-pythonkirjasto jatkoi "rivin"-lukemista kunnes vastaan tuli seuraava rivi missä hipsut suljettiin. Ensimmäisiä töitä oli siis hipsujen poisto aineistosta kokonaan. Voi olla että tuo on korjattu Datasets-paketissa, mutta en viitsinyt lähteä sitä päivittämään. Joka tapauksessa Common Voice oli testiaineistona huomattavasti parempaa, eikä rivejä tarvinnut lähteä karsimaan. 

Nyt kun näen netissä puheentunnistusohjelmien WER/CER-tuloksia, etenkin suomenkielellä, mielessä käy kieltämättä onko vain ajettu kerran läpi tarkistamatta millaisia virheitä tuloksissa on ollut. Huono tulos ei siis välttämättä kerro vielä että puheentunnistus olisi huono. Testi on voinut olla huono. 

Whisper ja sen versiot

Whisper on tunnetuin avoimen koodin puheentunnistimista ja OpenAIn kehittämä. Whisperille löytyy myös FinnishNLPn julkaisemia suomenkielellä hienotuunattuja versioita. Koska Whisper on niin tunnettu, on siitä paljon myös eri erikoisversioita ja netti täynnä myös niiden WER/CER-tuloksia. Mutta suomenkielen tuloksia siten vähemmän. Tärkeää on kuitenkin oikeasti testata miten ne toimivat myös suomenkielisinä. 

Minulla on tällä hetkellä kotiautomaatiossani Whisperin erikoisversio, Whisper_online, joka mahdollistaa puheentunnistuksen aloittamisen heti kun puhe on alkanut. Puhetta viedään sekunnin paloissa eteenpäin tunnistukseen heti kun puhetta on syntynyt, mikä mahdollistaa oikeastaan reaaliaikaisen puheentunnistuksen. Koneena on Strix Halo eli AMDn Ryzen AI Max+ 395 128Gtn muistilla, ja siitä Whisper vie 25% konetehoista, joten puhe on tunnistettu käytännössä heti kun se loppuu.  

Kun etsin "täydellistä" puheentunnistusta, törmästi paperiin Espanjan pienempien kielien puheentunnistuksen parantamisesta käyttämällä erillistä KenLM-kielimallia oikeiden sanavalintojen tekemiseen. Whisper-LM: Improving ASR Models with Language Models for Low-Resource Languages
Tulokset KenLM-mallin käytöstä vaihtelivat, mutta parhaat tulokset olivat baskin kielellä ja sen puhujia oli alle miljoona. Mietin että eihän tämä meidän suomikaan kovin yleinen kieli ole. Mitenkähän vastaava toimisi suomenkielelle? 
Paperin kirjoittajilla oli onneksi Githubissa Whisperin erikoisversion koodit( whisper-lm-transformers), ja sai myös pythonilla asennettua pakettina. Lisäksi heidän käyttämänsä KenLM-mallit löytyivät Huggingfacesta( Whisper-Lm-Ngrams ) 

Tarvittavan KenLM-mallin löysin FinnishNLPn (taas ne! )Huggingfacesta, eli noita on käytetty yleisesti Wav2vec-puheentunnistusmalleissa. Otin testaukseen 1Gtn mallin ( Finnish-NLP KenLM )

Otin testaukseen myös mukaan WhisperX:n, koska moni sitä kehui paremmaksi ( ... ilman niitä mittaustuloksia ) 

WhisperOnline käyttää OpenAIn Whisperiä, kun taas whisper_lm_transformers käyttää transforms-paketin versiota. 

Tein vertailuun myös "oman" version OpenAin Whisperistä, koska siihen voi antaa parametrinä äänimallin .pt-tiedostona, mutta tällöin mallille annetaan attention_heads tieto tyhjänä. Kokeilin yhtenä versiona sitä että lisäsin suomituunatun version mukaan Whisperin sorsakoodiin ja kopioin sille alkuperänsä large-v3n attention_heads-tiedot. Luin kyllä että tuon tiedon pitäisi vaikuttaa vain timestamppien tarkkuuteen, mutta tulipa tuokin kokeiltua. 

Tulokset Common Voice 23 aineistolla 

CommonVoice 23 

Ohjelma Äänimalli WER CER
Transformers Whisper FI 6.97 1.24
WhisperX FI 7.43 1.67
Tr.Whisper + KenLM FI 3.37 0.68
Tr.Whisper + tyhjä KenLM FI 7.08 1.27
WhisperOnline(openai.whisper) EN 10.62 2.04
WhisperOnline(openai.whisper) FI 7.44 1.33
WhisperOnline + KenLM EN 4.13 0.82
WhisperOnline + KenLM FI 4.13 0.82
WhisperOnline + KenLM fi pt + attentionheads 4.13 0.82
WhisperOnline fi pt + attentionheads 7.44 1.33

 

Ensimmäinen huomio tuloksista on varmaankin se että FinnishNLP:n KenLM-malli paransi tuloksia selkeästi! Virheellisten sanojen määrä puolittui! Alkuperäinen virhetaso 7-10% sanoissa olisi ollut käytössä aika huono tulos, mutta 3% virhe alkaa olla jo hyväksyttävää tasoa. WhisperX(7.43%) oli yllättäen hieman huonompi kuin transformers-versio(6.97%) mutta samoin myös OpenAIn versio oli huonompi (7.44%). Whisperin suomituunaus toi selvän edun OpenAin versiossa ( 10.62% vs 7.44%), mutta kun mukaan liitettiin KenLM, etua ei enää ollut. 

Oman kotiautomaation liittyvän testiaineiston luominen

Seuraava askel oli luoda oma testiaineisto, jotta voin testata myös miten tunnistus mitattavasti toimisi käytännössä. Lisäsin kotiautomaatioon ominaisuuden, jossa jokainen sanottu komento tallennetaan myös äänitiedostona ja samalla myös kotiautomaation käyttämän puheentunnistuksen (Whisper-online fi) veikkaus sisällöstä. Tarkoituksella lausuin sanat niin että puheentunnistus ne osaisi mahdollisimman hyvin tunnistaa. Sen jälkeen kävin tekstit läpi ja korjasin ne referensseiksi, mitä vastaan verrataan.  

Sitten muutin puheentunnistustestaussoftaani niin että se osasi käyttää aineiston hakemistoa parametrinä ja haki sieltä kaikki tiedostot ( ääni &teksti) ja suoritti testit niillä. 

Whisper ajoittain hallusinoi hiljaisuudessa ja siksi kotiautomaatiossani on oma funktio joka poistaa tunnistetusta tekstistä kaikki eri variaatiot lauseesta "Kiitos kun katsoit videon!". Jos Whisperin kieleksi on valittu englanti, on vastaava "Thanks for watching the video". Kotiautomaatiolleni on siis turha sanoa kiitos. Se ei sitä koskaan tule kuulemaan. 

Testaus kannattaa aina eli minähän en aiemmin ollut kuullut sitä mitä ääntä Whisperille menee, joten yllätys oli suuri kun WER-arvot olivat 23-40% tasoa!  

Oma 30 lauseen aineisto Home Assistant kotiautomaation komentoja 

Ohjelma Äänimalli WER CER
Transformers Whisper FI 32.37 13.98
WhisperX FI

Tr.Whisper + KenLM FI 41.62 19.52
Tr.Whisper + tyhjä KenLM FI

WhisperOnline(openai.whisper) EN 23.12 6.2
WhisperOnline(openai.whisper) FI 36.42 16.29
WhisperOnline + KenLM EN 40.46 17.12
WhisperOnline + KenLM FI 40.46 17.12
WhisperOnline + KenLM fi pt + attentionheads 36.42 16.29
WhisperOnline fi pt + attentionheads 40.46 17.12

Kävi ilmi että GPT5.1:n koodaama puheenstriimaus ei toiminutkaan luotettavasti, vaan sisälsi jatkuvasti pieniä mikropätkäyksiä. En varsinaisesti löytänyt sen juurisyytä, mutta ongelma poistui. Aiemmin ääni striimattiin ensin 100ms:n pätkissä,  sitten 30ms:n pätkissä ( koska VAD sitä vaatii) kunnes syötettiin Whisperille. Muutin koodia niin että striimaus menee jatkuvasti 100ms:n pätkissä ja VADille se syötettiin erillisellä funktiolla, joka pätki äänen sen vaatimiin 30ms pätkiin. Lisäksi lisäsin toimintalogiikkan sen että jos puhe alkaa, niin Whisperille syötetään myös edellinen 100ms ennenkuin VAD oli puhetta tunnistanut. Näin nauhoitukseen tuli varmemmin myös koko puheen alku. 

Näiden muutosten jälkeen tulokset paranivat rutkasti:   

Oma 30 lauseen aineisto Home Assistant kotiautomaation komentoja

Ohjelma Äänimalli WER CER
Transformers Whisper FI 4.65 1.45
WhisperX FI

Tr.Whisper + KenLM FI 11.63 2.34
Tr.Whisper + tyhjä KenLM FI

WhisperOnline(openai.whisper) EN 4.65 0.67
WhisperOnline(openai.whisper) FI 4.48 1.29
WhisperOnline + KenLM EN 8.96 1.83
WhisperOnline + KenLM FI 8.96 1.83
WhisperOnline + KenLM fi pt + attentionheads

WhisperOnline fi pt + attentionheads

Näissä tuloksissa esiin nousee se että kotiautomaatiolauseissa KenLM-kielimallista ei ollutkaan hyötyä vaan haittaa. Kun katsoin virheellisiä lauseita, niin virheitä oli selkeästi eniten lauseen alkamisissa, eli onko niin että algoritmi toimi silloin vielä ilman mitään pohjatietoa mihin suuntaan lause on menossa.  Esim. käsky "pistä" usein olikin "mistä" tai "pistää". 

Huvittavin väärinkuultu oli "soita Iron Maidenin levyltä Live After Death kappale, ei siis High".  

Kokeilin luoda aiemmin finwiki-aineistosta KenLM-malli, mutta se toimi huonommin. Samoin loin "extreme"-mallin, missä oli ainoastaan nuo kotiautomaatio-testiaineiston 30 lausetta, mutta sekään ei parantanut tulosta. Selvästi kuitenkin KenLM-malli olisi se millä puheentunnistuksen tarkkuutta voi helpoiten parantaa, joten selvitystyö vielä jatkuu. 
Tällä hetkellä kuitenkaan kotiautomaatiokäytössä minun ei kannata Whisper+KenLM:ää käyttää. Konetehoja tuo minulla vei 68% eli vielä tulisi reaaliaikaista ääntä, mutta en saanut vielä Whisper-onlinen ja Whisper-lm-transformersin koodia yhdistettyä niin että se olisi toiminut oikein striimattuna. Whisper-lm-transforms-koodi vaikutti aloittavan tunnistuksen aina alusta uudestaan, jolloin kun se tuotiin sekunnin pätkinä niin lopullinen tunnistus oli 1+2+3+4+5 eli kesti huomattavasti pitempään. Tuo kuitenkin luultavasti on korjattavissa, mutta kannattavaa vasta kun löytyy myös kotiautomaatioon sopiva KenLM. 

Tällä hetkellä Whisper-onlinen tulos 4.48 % - 4.65% on kuitenkin riittävä kotiautomaatiokäyttöön. 

Jatkoa varmaankin seuraa. Seuraava testi minulla varmaan että luen parikymmentä lausetta Common Voice aineistosta ja tarkistan johtuuko huono tulos kotiautomaatiotestissä minun lukuäänestäni vai KenLM-mallin puutteista. 

Comments