Tänään tarkasteltiin Fourier-muunnoksen ominaisuuksia, sovelluksia sekä nopeaa toteutusta.
Luennon aluksi käytiin läpi v. 2016 elokuun tentin tehtävä 2b, jossa laskettiin käsin neljän mittainen Fourier muunnos (ks. myös videon esimerkki).
Seuraavaksi tutustuttiin Fourier-muunnoksen käyttöön alkeellisessa puheentunnistimessa. Kirjan Elements of statistical learning kappaleen 5.2.3 inspiroimana toteutin Matlab-skriptin, joka löytää S-kirjaimet mikrofonin taltioimasta puheesta. Menetelmä on nimeltään logistinen regressio, joka monimutkaisista kaavoista huolimatta on varsin yksinkertainen toteuttaa: menetelmä etsii kertoimet kullekin Fourier-muunnoksen taajuudelle, ja laskee tulokset yhteen. Tuloksen perusteella saadaan todennäköisyys kummallekin luokalle: "S" ja "ei-S".
Menetelmää demottiin Matlab-toteutuksella, jossa luokittelija opetettiin erottamaan S-äänne muista äänteistä näyttämällä luokittimelle esimerkkejä kahteen luokkaan kuuluvista Fourier-muunnoksista. Menetelmä toimi kohtalaisen hyvin ottaen huomioon opetusaineiston erot testiaineistoon. Matlab-koodi löytyy alta.
Esimerkki kuvaa hyvin tämän päivän signaalinkäsittelyalgoritmia: perusmenetelmiä (Fourier-muunnos, konvoluutio, jne.) käytetään piirregeneraattoreina, jotka tuottavat hieman parempaa raakadataa kuin suora mittaussignaali (esim. taajuustietoa eikä raakaa mittausdataa). Laskettujen piirteiden perusteella sitten nostetaan tiedon abstraktiotasoa edelleen. Esimerkiksi äänteen tunnistuksessa hierarkia on esimerkiksi seuraava:
16000 aikatason näytettä -> 128 taajuustason kerrointa -> 1 bitti, joka kertoo kumpi äänne on kyseessä
Tämän jälkeen siirryttiin tarkastelemaan Fourier-muunnoksen ominaisuuksia. Ominaisuuksista tutustuttiin lähemmin siirtoon ajassa (esim. laske signaalin x(n+20) muunnos, kun tiedetään x(n):n muunnos) sekä konvoluution muunnokseen (DFT muuntaa konvoluution kertolaskuksi, eli x(n)*y(n) -> X(n)Y(n)). Aivan luennon lopussa mainittiin yhteys ns. dekonvoluutioon joka on konvoluutiolle käänteinen operaatio. Menetelmää käytetään muun muassa matkaviestinnän siirtotien häiriöiden korjaukseen sekä Hubble-teleskoopin alkuaikoina, jolloin yhdessä peilissä olleen hiontavirheen vuoksikuvat olivat sumuisia. Kuvantamisprosessia voidaan nimittäin mallintaa (kaksilulotteisella) konvoluutiolla
y(n,m) = h(n,m) * x(n,m),
missä x on todellinen näkymä, y on havaittu sumuinen kuva, ja h on linssin impulssivaste (nk. point spread function; PSF). Yhtälössä y ja h ovat tunnettuja, ja tehtävänä on ratkaista x. Ratkaisu löytyy taajuustasossa, koska
Y(n,m) = H(n,m) X(n,m),
joten (Matlabin syntaksilla ilmaistuna):
x(n,m) = ifft (Y(n,m) ./ H(n,m)).
Dekonvoluutiosta on hyötyä yleisemminkin lineaarisen kanavan aiheuttaman häiriön poistossa. Jos tiedetään signaalin x kulkeneen kanavan h läpi, voidaan vastaanotetusta mittaustuloksesta y päätellä x, jos meillä on joku käsitys kanavasta h. Esimerkkinä tästä on esim.mainittu langattoman tiedonsiirtokanavan estimointi ja sen aiheuttaman vääristymän kompensointi.
Toinen menetelmän tuottama etu on että Fourier-muunnoksen (käytännössä FFT:n) avulla voidaan laskea konvoluutio kaavasta (Matlabin syntaksilla ilmaistuna):
conv(x,y) = ifft(fft(x) .* fft(y))
Lisäksi käsiteltiin nopeaa Fourier-muunnosta eli FFT:tä, joka on vain nopeampi tapa toteuttaa diskreetti Fourier-muunnos (DFT). FFT perustuu signaalin jakamiseen lyhyempiin pätkiin, jotka muunnetaan jakamalla ne edelleen rekursiivisesti kahtia. Rekursio päättyy, kun muunnoksen pituus on 1, jolloin muunnosta ei tarvitse enää tehdä. 1-ulotteisen vektorin tapauksessa muunnosmatriisi on yksinkertaisesti F = [1], joka tarkoittaa pelkkää ykkösellä kertomista eikä sitä tarvitse tehdä. Lyhyemmistä vektoreista saadaan koostettua pidemmät vektorit kaavoilla (3.3) ja (3.4).
Alla on vielä luennon esimerkkikoodi S-kirjaimen tunnistuksesta. Funktio käyttää Stanfordin yliopistossa kehitettyä glmnet-pakettia. Jos näiden asennus on haastavaa, Matlabissa on nykyään myös valmis glmfit-funktio.
function vokaalin_tunnistus() % % Esimerkki vokaalin ja S-kirjaimen erottelusta äänisignaalista. % heikki.huttunen@tut.fi -- 4.2.2015 % close all addpath /home/hehu/Documents/Libraries/glmnet_matlab/ % Ladataan opetusaineisto: [x, Fs] = audioread('seiska.wav'); [X, H, numFrames] = extractFeatures(x, Fs); title ('Merkitse S-kirjaimet hiirella'); isConsonant = zeros(numFrames, 1); while true [x1, y1] = ginput(1); [x2, y2] = ginput(1); if x1 > x2 xt = x1; x1 = x2; x2 = xt; end isConsonant(round(x1 * numFrames) : round(x2 * numFrames)) = 1; response = questdlg('Jatketaanko annotointia?', ... 'Kysymys', ... 'Kyllä', 'Ei', 'Kyllä'); if strcmp(response, 'Ei') break end end cvob2 = cvglmnet(X, isConsonant, 'binomial', [], 'class'); yHat = glmnetPredict(cvob2.glmnet_fit, X, cvob2.lambda_min, 'response'); coefficients = H * cvob2.glmnet_fit.beta(:, cvob2.lambda == cvob2.lambda_min); figure() subplot(211) plot(yHat); ylabel('S-kirjaimen TN') subplot(212) stem(coefficients) response = questdlg('Valmiina tunnistamaan?', ... 'Tunnistus', ... 'OK', 'OK'); while true close all myRecObj = audiorecorder(Fs, 16, 1); recordblocking(myRecObj, 2); y = getaudiodata(myRecObj); X = extractFeatures(y, Fs); yHat = glmnetPredict(cvob2.glmnet_fit, X, cvob2.lambda_min, 'response'); figure() plot(yHat); response = questdlg('Jatketaanko tunnistusta?', ... 'Kysymys', ... 'Kyllä', 'Ei', 'Kyllä'); if strcmp(response, 'Ei') break end end end function [F, H, numFrames] = extractFeatures(x, Fs) [~,f,t,S] = spectrogram(x, 256, 128, 256, Fs, 'yaxis'); surf(t, f, 10*log10(abs(S)), 'EdgeColor', 'none'); axis xy; axis tight; colormap(jet); view(0,90); S = log10(S)'; H = []; n = (1:size(S, 2))'; for k = 0:3 H = [H, n.^k]; end F = S * H; numFrames = size(S, 1); end
Ei kommentteja:
Lähetä kommentti