OpenFst ile Sonlu Durum Dönüştürücüleri Oluşturmak

OpenFst sonlu durum dönüştürücüleri (Finite State Transducer) oluşturmak için kullanılan bir kütüphanedir. Sonlu durum dönüştürücüleri, sonlu durum makinalarının bir çeşididir diyebiliriz. Wikipedia’daki tanımına bakarsak, sonlu durum makinaları (FSA):

Sonlu durum makinası, (veya sonlu durum otomatı veya basitçe durum makinası) sınırlı sayıda durumdan, durumlar arası geçişlerden ve eylemlerin birleşmesiyle oluşan davranışların bir modelidir.

Sonlu Durum Makinası ve sonlu durum dönüştürücüleri konusu, çok geniş ve ayrıntılı incelenmesi gereken bir konu. İşin teorisi, uygulama alanları yabancı kaynaklarda detaylı bir şekilde ele alınmıştır. Biz burda daha çok OpenFst’in kullanımı ile ilgili basit birkaç şey göstereceğiz. OpenFst’nin 1.2.10 versiyonunu kullanarak, basit bir uygulama yazacağız. 1.2.10 ve üzeri herhangi bir versiyonu kullanılabilir. Windows 7 64 bit bilgisayarda ve cygwin kullanarak yapacağım.

OpenFst windows ortamında visual studio 2010 ile kurulabilir. Bu durumda cmd.exe kullanılabilir. Fakat benim tercihim, linux benzeri (posix) bir ortam sağlayan cygwin aracı oldu. OpenFst’yi mingw64 paketini kullanarak cygwin’de derledim. Genelde böyle bir ortamı tercih ediyorum. Cygwinle gelen bash 4 ortamı işimi kolaylaştırıyor. OpenFst ve kaldi speech recognition gibi araçlar, ilk olarak linux esas alınarak yazıldığı için, linuxtan windowsa geçiş daha az problemli oluyor. Mingw64 derleyicileri, native windows kodu üretiyor. Böylece, program yazıp, başka bir bilgisayara taşıdığınızda Cygwin dll’ini beraberinde taşımak zorunda değilsiniz. Açık kaynak kodlu olmayan uygulamalar için, cygwin dll’ini serbestçe dağıtamayız.

Yazacağımız uygulama, bir basamaklı ve iki basamaklı rakamlarının yazısını, sayıya dönüştürecek. Örneğin:

bir -> 1

iki -> 2

oniki -> 12

doksansekiz -> 98

Bu uygulamayı daha da geliştirerek, 6, 9, 12 basamaklı rakamları çevirecek şekle getirebilirsiniz. Amacımız burda OpenFst’nin kullanımına bir giriş yapmak olduğu için, kompleks bir örnek üzerinden gitmemeyi tercih ediyoruz.

Öncelikle OpenFst’nin kurulumunu tamamlıyoruz. Sitesinde bununla ilgili açıklamalar var. Bende C:\openfst-1.2.10 dizininde kurulu. OpenFst executable’ları da C:\openfst-1.2.10\bin dizininde, bu dizini bilgisayarın Path ortam değişkenine ekliyorum. Dönüştürücümü yazmak için, bir dizin oluşturuyorum (C:\testopenfst).

Cygwin’i başlatıyorum. Cygwin windowstaki path değişkenini okuduğu için, shell’de örneğin fstunion.exe dediğimde, ilgili exe’i bulup çalıştıracaktır.

Öncelikle sayilar.txt dosyamızı oluşturuyoruz:

0 1 sifir 0 
0 1 bir 1 
0 1 iki 2 
0 1 uc 3 
0 1 dort 4 
0 1 bes 5 
0 1 alti 6 
0 1 yedi 7 
0 1 sekiz 8 
0 1 dokuz 9 
0 2 on 1 
0 2 yirmi 2 
0 2 otuz 3 
0 2 kirk 4 
0 2 elli 5 
0 2 altmis 6 
0 2 yetmis 7 
0 2 seksen 8 
0 2 doksan 9 
1 3 <eps> <eps>
2 3 <eps> 0
2 0 <eps> <eps>
3

dosyanın yapısı;
sourcestate destinationstate input output -> 0 1 sifir 0

Bu dosyayı ilerde daha detaylı açıklayacağız. Şimdilik şunu diyebiliriz, bu dosya bizim, sonlu durum dönüştürücümüzü (finite state transducer), tarif ediyor. 0 durumunda iken, sifir inputu geldiğinde, 1 durumuna geçiyor, output olarak 0 değerini veriyor. 0 bizim başlangıç durumumuz. Son satırda belirttiğimiz 3 rakamıda, id’si 3 olan state’in son durum (final state) olduğunu ifade ediyor.

Kullanacağımız dosyaları burdan indirebilirsiniz

OpenFst’yi derlediğimiz zaman çeşitli işler için kullanacağımız, exe’ler oluşuyor; fstunion, fstcompile, fstcompose vs …
OpenFst’yi kullanabilmemiz için öncelikle, sayilar.txt dosyasını OpenFst’nin anlayacağı şekilde bir binary formata çevrilmesi gerekiyor.

fstcompile –isymbols=isyms.txt –osymbols=osyms.txt –keep_isymbols –keep_osymbols sayilar.txt sayilar.fst

Böylece sayilar.fst dosyasını oluşturmuş olduk.

Oluşturduğumuz dönüştürücünün nasıl bir şeye benzediğini görmek için fstprint komutunu kullanabiliriz:

fstprint sayilar.fst

Dönüştürücünün gözümüzde canlanması için, daha da güzel bir yöntem var. Graphviz kütüphanesinin dot komutunu kullanarak, dönüştürücünün grafiğini oluşturabiliriz.

Cygwin’e graphviz’i kurmak için şu sitede anlatıldığı şekilde, cygwinports sitesine bağlanıyorum. Daha sonra gelen paket seçme ekranına graphviz yazarak, kurulum yapıyorum. Böylece graphviz kütüphanesini cygwin’e kurmuş oluyorum.

Aşağıdaki komutları sırasıyla çalıştırınca, bir dönüştürücünün jpg formatında grafiğini oluşturmuş oluyoruz.

fstdraw –portrait sayilar.fst > sayilar.dot
dot -Tjpg sayilar.dot > sayilar.jpg

sayilar.jpg’yi açtığınızda, sonlu durum dönüştürücümüzü grafik olarak görebilirsiniz.

sayilar

Yaptığımız bu dönüştürücüyü nasıl kullanabiliriz. Biz bir input gönderip, outputunu almak istiyoruz. Yani otuz üç gönderdiğimiz zaman, bize output olarak 33dönmesini istiyoruz

Bunun için bir input.fst oluşturup, bunu sayilar.fst ile fstcompose komutuyla birleştirmemiz gerekiyor. Stackoverflow sitesinde konuyla ilgili bir soruya verilen cevabı inceleyebilirsiniz.

input.txt dosyası şu şekilde oluşuyor

0 1 otuz
1 2 uc
2

Ardından aşağıdaki komutu çalıştırarak, input.fst oluşturuyoruz.

fstcompile –acceptor –isymbols=isyms.txt –osymbols=isyms.txt –keep_isymbols –keep_osymbols input.txt input.fst
fstcompose komutunu çalıştırıyoruz.
fstcompose input.fst sayilar.fst output.fst

output.fst‘nin grafiğini görmek için:

fstdraw –portrait output.fst | dot -Tjpg > output.jpg
output

Grafiğine baktığımız zaman, bazı gereksiz durumların (state) olduğunu görüyoruz. Bu durumda fstrmepsilon.exe, fstminimize.exe gibi komutları kullanarak, daha sade ve verimli sonlu durum dönüştürücüleri oluşturabiliriz.

Son olarak, fstinvert komutunu kullanarak, yaptığımız dönüştürücünün tersini oluşturabiliriz. Yani:
1 -> bir
33 -> otuz uc

OpenFst’nin güzel tarafı bunun için yeni bir sonlu durum dönüştürücüsü yazmak gerekmiyor. fstinvert’i çalıştırıyoruz:

fstinvert sayilar.fst sayilartersi.fst

sayilartersi.fst dosyasini oluşturduk. input.fst‘ye benzer şekilde inputtersi.fst‘yi oluşturuyoruz.
inputtersi.txt:

0 1 3
1 2 3
2

fstcompile’ı çalıştırıyoruz. input olarak 33 göndereceğiz, outputumuz otuz uc olacak.

fstcompile –acceptor –isymbols=osyms.txt –osymbols=osyms.txt –keep_isymbols –keep_osymbols inputtersi.txt inputtersi.fst

Son olarak yapılması gereken fstcompose komutunu kullanmak. Fakat inputtersi.fst ile direkt compose etmek, sembol tabloları sayilartersi.fst içinde gömülü olmadığı için sorun yaratıyor. Bunun için önce fstsymbols komutunu kullanmamız gerekiyor. Sırasıyla

fstsymbols –isymbols=osyms.txt –osymbols=isyms.txt sayilartersi.fst sayilartersi.fstfstcompose inputtersi.fst sayilartersi.fst outputtersi.fst

Oluşan outputtersi.fst’ye bakarsak, istediğimiz sonucu elde ettiğimizi görürüz.

outputtersi

Yorum bırakın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Scroll to Top