Derin Öğrenme Tabanlı (seq2seq) Türkçe Kelime Kök Ayırıcı

Günümüzde Yapay Sinir Ağları (YSA), Doğal Dil İşleme (DDİ / NLP) alanında da kendini net şekilde göstermeye başladı. Özellikle, Derin Öğrenme algoritmalarının kullanıldığı yeni çözümleri etrafımızda sıkça görmemiz mümkün.

DDİ yaklaşımlarında, elimizdeki metin verisini temizlemek adına bazı işlemlerden geçiriyoruz. Tüm kaynaklar dikkate alındığında ön işleme (preprocessing) adımları aşağıdaki gibi:

  1. Kelimeleri ayır (Tokenization)
  2. Kelimelerin kökünü/gövdesini bul (Stemming)
  3. Anlama etki etmeyen genel kelimeleri at (Stop-words elimination)

Ön işleme adımlarının temel amacı “genel anlamı bozmadan” kelime sayısını (number of terms/features) azaltmaktır. Eğer ön işleme yapılmazsa bir modeldeki kelime sayısı yüksek boyutlara ulaşır (high dimensionality) ve modelin karmaşıklaşarak çalıştırılamaz hale gelmesi kaçınılmaz olur.

Tabi bu noktada dillerin morfolojik yapısı önem teşkil ediyor. Örneğin, İngilizce dilinin morfolojik yapısı basit olduğu için bu dilde kök bulma işlemi hem algoritmik tasarım açısından kolay hem de hata oranı az. Fakat sondan eklemeli bir dil olan Türkçe’de yapısı gereği sondan eklerle bazen fazlasıyla anlam değişikliği oluyor. Bu yüzden yapılacak çalışmada buna dikkat etmek gerekiyor.
 
Örneğin;

gözüm ağrıyordu. göz doktoruna gitttim. gözlük numaram değişmiş.
 
gözlüğümün çerçeveside eskimişti. gözlükçüye gidince, yeni bir gözlük çerçevesi de aldım.

göz, gözüm, gözlük, gözlüğümün gözlükçüye, gözlük … diye geçen kelimelerin hepsinin köküne göz demek anlamı bozar.

Bunun yerine aşağıdaki gibi farklı bir yaklaşım deneyelim:

gözüm => göz
 gözlüğümün => gözlük 
 gözlükçüye => gözlükçü

Evet, bu yaklaşım sanki daha doğru oldu… Elbette bir anlam kaybı var ama nispeten daha doğru olduğunu söylemek mümkün. Tabi anlamları farklı, yazılışları aynı kelimeler için bir çözüm olmadığını da belirtmemiz lazım.

Ortada çözümü olmayan genel bir optimizasyon problemi var.

Eğer sadece kökü kullanırsanız, bazı anlamları kaybetme ihtimaliniz var, öte yandan kelimenin tamamını kullandığınızda ise kelime sayınız astronomik sayılara çıkıyor.
 
Kelime vektörleri bu işi çözmez mi? Kelime vektörleri dediğimiz yaklaşımda kelimeler sabit uzunlukta vektörler olarak ifade ediliyor. Temelindeki fikir şudur: Aynı anlamı ifade eden kelimeler aynı bağlamda — context — de kullanılır. Büyük derlemde — corpus — kelimeler birlikte kullanıldıkları kelimelere göre optimize edilerek her birisi için sabit bir vektöre ulaşılıyor. Yakın anlamlı kelimeler kelime vektör uzayında birbirine yakın konumlarda oluyorlar. Burada şöyle bir problem var her kelimenin her türlü ekiyle birlikte yeterli miktarda derlemde olması pek mümkün değil.
 
Şu ana kadar anlattıklarımız size sıkı gelmiş olabilir, kusura bakmayın :)Fakat problemi net olarak ortaya koymamız ve bu probleme çözüm olarak sunduğumuz çalışmamızın farkını ortaya koymamız lazımdı…Çalışmamızda, kök bulma işlemini seq2seq bir modele öğretmeye çalıştık. Modeli eğitirken Ahmet Aksoy beyin yayınladığı bir veriyi kullandık. Sistemi genel kullanıma açabilmek adına Yavuz Kömeçoğlu ile birlikte bu model için etkileşimli bir web sayfası hazırladık.

Mevcut haliyle kullanıcının vereceği kelime için model çalıştırılıp bir cevap dönüyor. Kullanıcı cevabın doğru ya da yanlış olup olmadığını ve doğrusunu geri bildirimle sisteme girebiliyor.

  • Bu projenin özelliği ne peki ? Yukarıdaki girizgahtan tahmin edeceğiniz gibi çok zor bir problemi çözdük gibi bir iddiamız yok.
Bu projenin ana özelliği klasik yaklaşımın dışında bir çözüm getirmesi.
  • Klasik yaklaşımda şöyle olursa nasıl yaparım böyle olursa nasıl yaparım diye kurallar silsilesi kurgulamanız lazım. Hatta karşımıza kurguladığımız hiç bir kurala uymayan bir kelime çıkarsa, 
    if kelime BU ise kök ŞU dur” demek zorunda kalıyorsunuz.

    Modern yaklaşımlarda olabildiğince çok veri bularak, birbirini takip eden bir yapının diziliminden örüntüler çıkarıp istenen sonuca ulaşılmaya çalışılır. Biz bu projede bunu yapmaya çalıştık. Verimizi sağlıklı bir şekilde büyütebilirsek, modelin başarısı artacağını umuyoruz.
  • Bir başka büyük özelliği etkileşimli bir şekilde sunuluyor olması. Günümüzde Türkçede DDİ üzerine çalışma yapacak kişinin, ilk toslayacağı duvar, elde hazırda verinin olmayışıdır. Sağ olsunlar Yıldız Üniversitesinden Kemik gurubunun yıllar önce yaptıkları dışında açık şekilde ulaşılabilir bir veri seti maalesef yok. Bu çalışmayla gönüllülerin girdiği yeni kelimeler ve düzeltmelerle çok daha geniş bir veri setine ulaşabilme imkanını sunuyor.

Bu proje bir rol model olarak düşünülüp çok daha kompleks DDİ problemleri için bir çözüm ve veri seti toplama sistemi olarak düşünülebilir.
 
Elbette bunu özel sektörde çalışan ben ve master tezini vermeye uğraşan Yavuz, tek başımıza yapamayız. Kullananlar olması lazım. Kullanıcaların yazdıklarının toparlanıp ayıklanması lazım. Sistemin yeniden eğitilmesi lazım. Epey bir emek gerekiyor. Hatta bence bu tip bir proje ve elbette daha gelişmişleri, akademik olarak sahiplenilmesi gereken projelerden. Biz projeyi çalıştırdık. Kodumuzuda Deep Learning Türkiye gurubunun github hesabında yayınladık.

Bundan sonra Proje sahiplerini bekliyor.

Derin Öğrenme Kısmı:

Gelelim işin teknik kısmına:

Modelimiz Seq2Seq denen yapıda bir ağ olup, gerçekleştiriminde Keras kullanıldı. Kelimeler harf bazlı kodlandı. Harf çeşit sayımız 34. Yani bir harfi 34 uzunluğunda vektör olarak kodluyoruz. Maksimum kelime uzunluğu eldeki veri setine göre 22 olarak belirlendi.

RNN tipi ağ katmanları veriyi zaman bazında istiyor. Bizim durumumuzda kelime uzunluğu 22 olduğundan 22 seferde 34 uzunluklu vektörler. Ağın çıkışı da aynı şekilde kodlanmış olarak sadece Kök kısmını üretiliyor.
 
Ağın genel yapısına bakalım:

Çok sade bir çoklu girişten çoklu çıkış -seq2seq- üreten RNN li bir model. 
Fazladan diyebileceğimiz sadece başta Dikkat — Attention — kısmı var. Girişdeki verilerin önem derecesini öğrenmesi için bir YSA katmanı yerleştiriyoruz ve katmanın çıkışını veri için bir önek katsayısı olarak kullanıyoruz.

Modeli sade tuttuk çünkü eğitim eğrisi gayet güzel, test verisi başarısı da epey yüksek.

Elbette verilerin çoğalması ile modele de ilaveler gerekebilir. Kodda Keras’ın çeşitli callback fonksiyonları kullanıldı. Onlardan da bahsedelim.

  • EarlyStopping : Eğitim esnasında takip ettiğiniz değerde belirleyeceğiniz adım — epoch — boyunca iyileşme yoksa eğitim veridiğiniz adım sayısından önce durduruluyor. Bizim kodumuzda 9 adım boyunca test verisi başarımında bir iyileşme olmuyorsa duryor.
  • ReduceLROnPlateau : Eğitim esnasında takip ettiğiniz değerde belirleyeceğiniz adım — epoch — boyunca iyileşme yoksa Öğrenme hızını sizin belirleyeceğiniz bir katsayıyla çarparak küçültüyor. Bizim kodumuzda 2 adım boyunca test verisi başarımında bir iyileşme olmuyorsa öğrenme hızı 0.5 çarpılarak yarıya indiriliyor.
  • ModelCheckpoint : Eğitim esnasında her adım sonunda belirleyeceğiniz şartlara göre modelin komple yada sadece ağırlıklarının kaydedilmesi işini yapar. Bizim kodumuzda test verisi başarım değerinde bir yükselme olmuşsa kaydediyor.
  • CSVLogger : Eğitim esnasında her adım sonunda, hem eğitim hem test verisi için, hata değeri — loss — başarım değeri — acc — ve öğrenme hızı — learning rate — değerlerini kaydeder.

Bizim anlatacaklarımız bu kadar. Buraya kadar sabırla okuduğunuz için teşekkürler. Her türlü görüş ve önerilerinizi bekleriz.