Język (nie do końca) rozpoznawalny

praca magisterskaW poniedziałek, 15 września 2008 roku, zakończyłem oficjalnie pisanie pracy magisterskiej i złożyłem ją w dziekanacie. Jako, że nie wszyscy wiedzą o czym pisałem, postaram się przedstawić krótko całą historię.

Gdy półtora roku temu zacząłem się zastanawiać na poważnie nad tematem pracy, miałem kilka sprecyzowanych punktów, według których chciałem sobie dobrać temat. Moją specjalnością jest inżynieria oprogramowania, ale w tej dziedzinie dowolny temat pracy wydawał mi się mało interesujący. Postanowiłem pracę pisać w innym instytucie, a mianowicie w Instytucie Sztucznej Inteligencji i Metod Matematycznych. Miałem nawet konkretnie wybranego promotora, u którego chciałem pisać. Podszedłem do wyboru tematu dość ambitnie. Wybór czegoś łatwego i odtwórczego mnie zupełnie nie przekonywał. W końcu ma to być moja pierwsza publikacja naukowa z prawdziwego zdarzenia. Dlaczego więc nie połączyć kilku dziedzin, które mnie interesują? Z racji wybranej specjalności, głównym zadaniem w pracy miało być stworzenie programu. Chciałem napisać program, dzięki któremu przeprowadziłbym badania, których wyniki mogą się realnie przydać, a jednocześnie sam program mógł być rozwojowy. Wykorzystywałby sieci neuronowe do klasyfikacji czegoś związanego z dźwiękiem. Na początku myślałem o rozpoznawaniu stylu muzycznego badanego utworu. Jednak klasyfikacja gatunków muzycznych jest na tyle trudna dla człowieka, że komputer tym bardziej nie będzie w stanie sobie z tym poradzić. Poprosiłem więc promotora o pomoc w wymyśleniu tematu w sam raz dla mnie. I promotor wymyślił:

„Zastosowanie sztucznych sieci neuronowych do rozpoznawania języka mówiącej osoby”

Temat spodobał mi się od samego początku. Wow! Zajmę się rozpoznawaniem języków :-). Oprócz dziedzin związanych z dźwiękiem, sztuczną inteligencją i programowaniem, mogę się zająć też bardzo interesującą mnie dziedziną – językoznawstwem. Chociaż w ograniczonym stopniu. Do tematu nie miałem żadnych zastrzeżeń, więc taki właśnie został oficjalnie przyjęty.

Jako rasowy prokrastynator, na poważnie zająłem się pracą dopiero w ostatnim semestrze ;-). Wcześniej bardzo powoli gromadziłem literaturę, na której mógłbym się oprzeć. Jednak literatury takiej nie ma. Musiałem się oprzeć na kilku anglojęzycznych artykułach naukowych, traktujących konkretnie o temacie rozpoznawania języka. Reszta literatury to publikacje o analizie i syntezie dźwięku czy ogólne o samych sieciach neuronowych. W dodatku publikacji o identyfikacji języka, w języku polskim, nie znalazłem żadnych. Dobrze, że oprócz promotora znającego się na sieciach neuronowych, miałem też do kogo się zwrócić w temacie samej analizy dźwięku. Pani Ania dużo mi pomogła – dzięki niej opracowałem najważniejszą część pracy, czyli metodę ekstrakcji cech głosu, którymi potem miałem uczyć sieć neuronową.

Sama metoda powstała i została przetestowana w Matlabie jeszcze przed wakacjami. Zdążyłem jeszcze tylko napisać rozdziały teoretyczne i przesunąć termin oddania pracy na wrzesień. Wakacje upłynęły mi na pisaniu całego programu w C++ (jakieś 20% czasu) i jego testowaniu (80% czasu, bo przecież nic nie może dobrze działać za pierwszym razem ;-)). Gdy po bólach program już powstał, przeprowadziłem za jego pomocą badania. Wreszcie mogłem sprawdzić jak się sprawuje moje dziecko :-).

Badania były przeprowadzone na próbkach zdań w 6 językach: polskim, angielskim, niemieckim, włoskim, hiszpańskim i rosyjskim. Przygotowałem po 21 zdań w każdym z tych języków i zaprzęgłem syntezatory mowy, żeby wygenerowały mi zdania z poprawną wymową. Dodatkowo, przygotowałem próbki mowy żywego człowieka dla języka polskiego, angielskiego i rosyjskiego. Zapowiadało się ciekawie… ale wyniki badań mnie nieco rozczarowały. Przy uczeniu wszystkich 6 języków na raz, jakość rozpoznawania była bardzo niska. Od 20 do 50%. Z czego najgorzej sieć rozpoznawała… język angielski. Najlepiej za to włoski. Włoski praktycznie wygrywał w każdej konfiguracji. Najlepiej był rozpoznawalny (i to w prawie 85%) przy zestawie 3 języków – polskim, włoskim i hiszpańskim. Nie zdziwiło mnie to. Jeśli znacie melodię języka włoskiego (a mój program właśnie analizuje melodię wypowiadanych zdań), to wiecie, że każde zdanie kończy się skokiem intonacji od dźwięku wyższego do niższego. Co więcej -badania na próbkach żywej ludzkiej mowy wypadły nieco gorzej niż na próbkach syntetycznych.

Czy więc poniosłem klęskę? W żadnym wypadku! Wyciągnąłem wnioski, które pozwolą mi na udoskonalenie algorytmu i przeprowadzenie kolejnych badań. Na pewno nie porzucę tego co zacząłem. A świadomość tego, że moja publikacja jest chyba jedyną taką w języku polskim, motywuje mnie dodatkowo. W końcu interfejsy głosowe za kilka lat staną się bardzo popularne, a ja tworzę pewien ważny wycinek tego, co w tych interfejsach będzie implementowane. Napisałem przyzwoitą pracę, z której jestem zadowolony i która rokuje na przyszłość. Jeszcze czeka mnie obrona na początku października i wtedy będę mógł odetchnąć :-). I z pewnością po obronie opiszę bardziej szczegółowo wyniki badań, a także opublikuję swoją pracę w internecie.

Mam nadzieję, że Was nie zanudziłem, i że kogoś innego oprócz mnie też to zainteresowało. W razie czego – pytajcie w komentarzach. Chętnie odpowiem 🙂

Prawdziwi programiści

VIM najlepszy! O tak! Po co nam zorganizowane środowisko programistyczne „wszystko-w-jednym”, skoro możemy sobie go sami stworzyć z pojedynczych elementów? W końcu programista to nie byle jaki człowiek – potrafi wszystko!

gdbPo co Prawdziwemu Programiście jakieś środowisko IDE z wbudowanym debuggerem? Przecież najwygodniejszym sposobem jest skompilowanie programu z opcją -g i przejście do gdb. Tam ładnie krok po kroku widzimy jak program działa. Piszemy komendy, które bardzo łatwo zapamiętać i dostajemy to co chcemy na ekranie. Co? Że poprzednia wartość zniknęła z ekranu? Przecież możemy sobie go przesunąć! Mamy też bardzo wygodną historię ostatnio wklepywanych stu dwudziestu pięciu poleceń, dzięki której możemy szybko powtórzyć wcześniej wpisywaną komendę. Możemy też zobaczyć wartość naszej zmiennej – wystarczy tylko wpisać komendę. Oczywiście na bieżąco nie możemy śledzić jej zmian, ale od czego jest historia? Kilka strzałek w górę i już możemy wyświetlić nową zawartość zmiennej. Nie widzimy większego kontekstu kodu źródłowego? Możemy przecież przełączyć się między konsolami… albo wylistować kod w oknie debuggera. Znowu nie widzimy poprzednich wyników? Oj, żaden problem – to tylko 3 ekrany powyżej. A jak komuś się nie podoba, to może sobie w historii poszukać i jeszcze raz wyświetlić to co chce. Które to było polecenie w historii?

vim
W dodatku VIM w prosty sposób pozwala na pisanie skryptów, którymi można np. podczepić do niego kompilator. Wystarczy tylko wklepać polecenie. Potem ładnie przełączamy się na kolejną konsolę i odpalamy debuggera. To takie proste i wygodne. A nie jakieś lamerskie wciskanie ctrl+f9 czy innych takich.

Prawdziwy Programista, jeśli czegoś mu potrzeba, sam to sobie napisze. Od podstaw. No bo lamerzy tego nie potrafią i wolą skorzystać z gotowych rozwiązań. A fe! Prawdziwy Programista nie czuje się zmęczony, gdy po kilku dniach i nocach szukania błędów w swoim silniku do wyświetlania scen z lamerskiego 3D Studio, w końcu program je poprawnie wyświetla. W tym czasie Zenek odpoczywa na wakacjach ze swoją dziewczyną. A to lamer! Skorzystał z darmowego gotowca! Prawdziwy Programista nigdy nie będzie sfrustrowany, gdy następnego dnia silnik mu się wysypie. A tam! Najwyżej nie prześpi kolejnej nocy. W końcu tekstowy debugger jest de best!

Na studiach uczą Prawdziwie Programistycznego podejścia. Ansi C to podstawa. Czysta konsola to podstawa. Midnight Commander zabroniony (przecież jest dla lamerów). Ileż radości daje znalezienie jednej niedomkniętej klamry czy też niepostawionego średnika. Student musi znać podstawy. W końcu pracodawca będzie od niego tych podstaw wymagał. Tak jak tworzenia od podstaw pięć tysięcy trzysta sześćdziesiątego szóstego silnika do wyświetlania scen z 3D Studio czy też programu do mnożenia macierzy.

Przejaskrawiam? Tak.

Mam nadzieję na jakiekolwiek komentarze 😉