Doğal Dil İşleme Serisi 4: Makine Çevirisi (Giriş Seviyesi)

Yusuf ANI
novaresearchlab
Published in
6 min readSep 28, 2020

Merhabalar, yazı serimizde Deep Learning AI ekibinin “ Natural Language Processing with Classification and Vector Spaces” adlı NLP kursunun geniş özetini bulacaksınız. 4 haftadan oluşan bu kursun ana başlıkları şu şekilde:

1- Sentiment Analysis with Logistic Regression — Lojistik Regresyon ile Duygu Analizi

2- Sentiment Analysis with Naïve Bayes — Naïve Bayes ile Duygu Analizi

3- Vector Space Models — Vektör Uzayı Modelleri

4- Machine Translation — Makine Çevirisi (Giriş Seviyesi)

Bu yazıda kursun dördüncü bölümü olan Machine Translation konusunu özetledik. Yazımızın sonunda Github kodumuzu bulabileceksiniz. Ayrıca diğer yazılara profillerimizden ulaşabilirsiniz. Keyifli okumalar :)

Günümüzde makine çevirisini kullanmayanımız yoktur herhalde. Google Translate, Yandex Translate gibi başarılı uygulamaların arkasındaki derin yapının temellerini inceleyelim.

Makine Çevirisi Nedir? Temel Düzeyde Nasıl İşler?

Şekil-1

Makine çevirisi kısaca bir dildeki kelimeleri diğer dile anlamlı olarak çevirme işlemidir. Örnek olarak “cat” kelimesinin Fransızca karşılığı olan “chat” kelimesine çevrilmesi verilebilir.

Önceki yazılarımızda işlediğimiz gibi elimizde iki dilin ayrı ayrı word embeddings (Kelime Temsilleri) var. Her bir kelimenin diğer kelimelerle olan bağlantılarını içeren vektörler elimizde ise süreç ise şöyle işliyor:

  • Kaynak kelimenin vektörünü bul.
  • Bir matris ile çarpıp hedef dildeki vektörü bul.
  • Elde ettiğin vektörün hedef dildeki en yakın komşusunu bularak tahmini yap.
Şekil-2 Adımların Matematiksel Gösterimi X: Kaynak Vektör ( 1 * n ) R: Matris ( n*m ) Y: Tahmin Edilmiş Vektör. (1*m) n: Kaynak Dildeki Kelime Temsili Büyüklüğü m: Hedef Dildeki kelime temsili büyüklüğü

Peki bu R matrisini nasıl elde edeceğiz? Nasıl Eğiteceğiz?

Asıl meşakkatli olan kısım burası elbette çünkü R matrisi hakkında ilk başlarda hiçbir fikrimiz yok. Bu yüzden rastgele olarak başlatalım.

Şekil-3 R Matrisini Eğitimi

X kaynak kelime vektörü ile R matrisimizi çarparak bir kelime vektörü oluşturalım. Ardından kelimenin hedef dildeki gerçek değeri ile Frobenius normunu hesaplayarak loss (kayıp) değerini elde edelim. Burada Frobenius normunun nasıl hesaplanacağı merak konusu :D

Çok basit şekilde düşünürsek elimizde belirli işlemler sonucunda tahmin ettiğimiz bir değer olan 2 olsun. Fakat gerçekte tahmin etmemiz gerekenin 10 olduğunu varsayalım. Burada her iki değer de skaler değerler olduğu için aradaki farkın ne kadar olduğunu (10–2) bulabiliyoruz. Buna göre önceki işlemlerin değerlerini güncelleyerek daha iyi sonuçlar elde edebiliriz.

Frobenius Norm elimizde 2,10 gibi skalar değerler yerine matrisler olunca loss değerini hesaplamanın yollarından birisidir.

Şekil-4 Frobenius Norm Formülü

XR-Y ifadesi sonucunda oluşan matrise A dersek Şekil-4'teki gibi bir hesaplama yapabiliriz.

Loss fonksiyonunu anladıktan sonra Şekil-3'e geri dönersek, loss fonksiyonunun R matrisine göre türevini alarak gradyanı hesaplamamız, ardından R matrisinden gradyanı çıkararak güncelleme yapabiliriz. Tabii ki gradyanı learning rate (öğrenme katsayısı) ile çarpmayı unutmamak gerekiyor.

Şu ana kadar ilk 2 adımı gerçekleştirdik. Artık elimizde bir kelime vektörü var. Peki bu kelime vektörü hedef dildeki hangi kelimeye daha çok benziyor sorunun cevabına bakalım.

En Yakın Kelimeyi Bulmak

Bu kısım için akla gelen ilk çözüm elde ettiğimiz vektörü bir önceki yazımızda bahsetmiş olduğumuz Euclidean distance (Öklid Uzaklığı) veya Cosine similarity (Kosinüs Benzerliği) hesaplamalarını kullanarak hedef dildeki diğer vektörlerle benzerliğini hesaplamak (Brute Force Çözüm). Bu çözüm her ne kadar yapılabilir bir çözüm olsa da çok verimli olduğu söylenemez. Çünkü hedef dildeki kelime sayısı çok fazla olursa hesaplama maliyeti çok fazla olacak. Bunun için farklı çözümlere bakalım.

Gereksiz hesaplamalardan kaçınmak için ilk yapılması gereken bilgisayar biliminde sık kullandığımız böl ve yönet algoritmalarını kullanmak. Diğer bir deyişle ben Türkiye’de bir il gezisi yapmak istiyorsam, Avrupa’daki illeri hesaba katmamam gerekiyor. Bu yüzden verimizi “k” adet bölgeye bölerek K-Nearest Neighbours algoritmasını kullanmış olacağız. Bölgelere bölme işlemi için ise hash yapısından faydalanacağız.

Eğer hash yapısına hakimseniz 1 paragraf geçebilirsiniz.

Hash yapısının asıl amacı aradığınız veriye en hızlı şekilde ulaşmanızı sağlamaktır. Bunun için Hash fonksiyonuna göre yerleştirme yapılır. Şekil-5'teki örnek üzerinden gidelim. Varsayalım ki kelime vektörleri yerine elimizde 10,14,17,97,100 değerleri olsun. Burada hash fonksiyonunun yaptığı işlem elde edilen sayıları toplam istenen kutu sayısı kadar alana yerleştirmek. Burada toplam 10 rakam (yani kutu) var. Bu yüzden bu değerlerin mod 10 işlemi sonucu alınarak yerleştirme yapabiliriz.

Şekil-5 Hash Yapısı

Hash yapısını anladıysak akıllardaki şu soru oluşabilir: “Eee bizim elimizde değerler yok ki, birden fazla değerli vektörler var.” Bunun için de Locality Sensitive Hashing(LSH) kullanıyoruz.

LSH algoritmasını basitleştirmek için vektörlerimizi 2 boyutta düşünelim. ( !REKLAMLAR! İsterseniz bir önceki yazımdaki PCA algoritmasına bakarak boyut düşürme hakkında fikir elde edebilirsiniz. !REKLAMLAR! ). Şekil-6'daki her bir nokta bir kelime vektörünü ifade ediyorsa, biz bu noktaları düzlemlere ( Plane ) bölerek aradığımız kelime vektörünün yakınındaki noktalara ulaşabiliriz.

Şekil-6 Locality Sensitive Hashing 2 Boyutta Gösterimi

Bu düzlemler üzerinde turuncu ve mavi vektörler gibi zıt yönlü veya eflatun vektör gibi düzleme dik normal vektörler oluşturabiliriz. İşte bu vektörler yukarıda bahsettiğim hash değerlerini kelime vektörlerinden çıkarmamıza çok yardımcı olacak.

Şekil-7 Düzlemlerin Gösterimi

Şimdi diyelim ki V1,V2,V3 olmak üzere 3 adet vektörümüz, eflatun çizgili olarak gösterilmiş bir düzlemimiz ve buna dik olan normal vektörümüz P1 var.

Şekil-8

Eğer biz bu vektörlerle P normal vektörünü çarparsak ilginç bir sonuç elde edeceğiz.

PV1 = 1*1 + 1*2 = 3

PV2 = 1*-1 + 1*1 = 0

PV2 = 1*-2 + 1*-1 = -3

Eğer fark ettiyseniz düzlemin bir tarafında olan vektörlerin sonucu pozitif, düzleme paralel olanlar 0, düzlemin diğer tarafında olanlar ise negatif sonuç vermektedir. Bu sayede birbirlerine yakın olan vektörler aynı tip sonuçları verecek ve aramamız çok daha kolaylaşacak :D

Locality Sensitive Hashing’i kavradıysak bunu çoklu düzlemlerde uygulayalım.

Şekil-8 Çoklu Düzlemde LSH uygulaması

Şekil-8'de eflatun, mavi ve turuncu olmak üzere 3 farklı düzlem var ve her bir işareti birer vektör olarak varsayarsak düzlemin hangi tarafında olduğunu bulmayı öğrendik.

Bir kelime vektörünün işareti pozitif veya sıfır ise 1 değerini aksi halde 0 değerini vererek “h” değerini elde edelim. Şekil-8'deki gibi 1,1,0 değerlerini elde ettik. Yapmamız gereken tek işlem 2'nin kuvvetleri ile çarparak sonucu toplamak. Bu değeri kelime vektörümüzün hash değeri diyebiliriz :D

Şekil-9 Çoklu Düzlemde LSH Formülü

Değinmemiz gereken son bir konu kaldı. Bu düzlemleri neye göre oluşturacağız? Oluşturduğumuz düzlemler ideal mi?

Bizim Brute Force çözüm yerine bu kadar zahmete girmemizin sebebi performans ve zaman kazancı. Eğer en ideal düzlemi hesaplarsam bu işi yapmam mantıksız olur. Bu yüzden birbirinden tamamen ayrı olarak istediğim sayıda hash yapısı tutarız. Bu yapıyı paralel evrenler gibi düşünebiliriz. Birbirinden bağımsız olarak hedef dildeki bulunan tüm komşu noktaları birleştirir, ardından bu noktalar üzerinde en yakın noktayı bulmaya çalışırız. Bu işleme de Approximate nearest neighbors adı verilir.

Şekil-10 Farklı Düzlem Örnekleri

Yazının bu kısmına kadar geldiyseniz sizleri tebrik ederim. Yukarıda bahsettiğim tüm bu algoritmaların Python dilinde kodlanmış haline buradan erişebilirsiniz. Eğer profesyonel anlamda bir makine çevirisi modeli oluşturmak istiyorsanız, Neural Machine Translation başlığı ile arama yapabilir, paper ve github kodlarından faydanabilirsiniz.

Yazı konusunda kafanıza takılan noktalar, eleştiriler veya öneriler için yorumlar kısmında cevap vermeye çalışacağım. Sağlıcakla kalın.

--

--

Yusuf ANI
novaresearchlab

Bilgiye sahip olarak doğmuş birisi değilim. Öğretmeyi seviyorum ve öğrenmeye çalışıyorum — Konfüçyüs