8.4. Yinelemeli Sinir Ağları
Open the notebook in Colab
Open the notebook in Colab
Open the notebook in Colab
Open the notebook in SageMaker Studio Lab

Section 8.3 içinde \(n\)-gramlık modelleri tanıttık; \(x_t\) kelimesinin \(t\) zaman adımındaki koşullu olasılığı sadece önceki \(n-1\) kelimeye bağlıdır. Eğer \(x_t\) üzerinde \(t-(n-1)\) zaman adımından daha önceki kelimelerin olası etkisini dahil etmek istiyorsanız, \(n\)’yi artırmanız gerekir. Bununla birlikte, model parametrelerinin sayısı da katlanarak artacaktır, çünkü \(\mathcal{V}\) kelime dağarcığı kümesi için \(|\mathcal{V}|^n\) tane değer depolamamız gerekir. Bu nedenle, \(P(x_t \mid x_{t-1}, \ldots, x_{t-n+1})\)’yı modellemek yerine bir saklı değişken modeli kullanılmak tercih edilir:

(8.4.1)\[P(x_t \mid x_{t-1}, \ldots, x_1) \approx P(x_t \mid h_{t-1}),\]

burada \(h_{t-1}\), \(t-1\) adıma kadar dizi bilgisi depolayan bir gizli durumdur (gizli değişken olarak da bilinir). Genel olarak, herhangi bir \(t\) zaman adımındaki gizli durum, şimdiki girdi \(x_{t}\) ve önceki gizli durum \(h_{t-1}\) temel alınarak hesaplanabilir:

(8.4.2)\[h_t = f(x_{t}, h_{t-1}).\]

(8.4.2) içindeki yeterince güçlü bir \(f\) işlevi için, saklı değişken modeli bir yaklaşım değildir. Sonuçta, \(h_t\) şimdiye kadar gözlemlediği tüm verileri saklayabilir. Ancak, potansiyel olarak hem hesaplamayı hem de depolamayı pahalı hale getirebilir.

Section 4 içinde gizli birimli gizli katmanları tartıştığımızı anımsayın. Gizli katmanların ve gizli durumların iki çok farklı kavramı ifade etmeleri önemlidir. Gizli katmanlar, açıklandığı gibi, girdiden çıktıya giden yolda gözden gizlenen katmanlardır. Gizli durumlar teknik olarak belirli bir adımda yaptığımız işleme girdilerdir ve yalnızca önceki zaman adımlarındaki verilere bakarak hesaplanabilirler.

Yinelemeli sinir ağları (RNN) gizli durumlara sahip sinir ağlarıdır. RNN modelini tanıtmadan önce, ilk olarak Section 4.1 içinde tanıtılan MLP modelini anımsayalım.

8.4.1. Gizli Durumu Olmayan Sinir Ağları

Tek bir gizli katmana sahip bir MLP’ye bir göz atalım. Gizli katmanın etkinleştirme işlevinin \(\phi\) olduğunu varsayalım. \(n\) küme boyutlu ve \(d\) girdili bir minigrup örneklemi \(\mathbf{X} \in \mathbb{R}^{n \times d}\) göz önüne alındığında, gizli katmanın çıktısı \(\mathbf{H} \in \mathbb{R}^{n \times h}\) şöyle hesaplanır:

(8.4.3)\[\mathbf{H} = \phi(\mathbf{X} \mathbf{W}_{xh} + \mathbf{b}_h).\]

(8.4.3)’te, \(\mathbf{W}_{xh} \in \mathbb{R}^{d \times h}\) ağırlık parametresine, \(\mathbf{b}_h \in \mathbb{R}^{1 \times h}\) ek girdi parametresine ve gizli katman için \(h\) gizli birim adedine sahibiz. Böylece, toplama esnasında yayınlama (bkz. Section 2.1.3) uygulanır. Ardından, çıktı katmanının girdisi olarak \(\mathbf{H}\) gizli değişkeni kullanılır. Çıktı katmanı şöyle gösterilir,

(8.4.4)\[\mathbf{O} = \mathbf{H} \mathbf{W}_{hq} + \mathbf{b}_q,\]

burada \(\mathbf{O} \in \mathbb{R}^{n \times q}\) çıktı değişkeni, \(\mathbf{W}_{hq} \in \mathbb{R}^{h \times q}\) ağırlık parametresi ve \(\mathbf{b}_q \in \mathbb{R}^{1 \times q}\) çıktı katmanının ek girdi parametresidir. Eğer bir sınıflandırma problemi ise, çıktı kategorilerinin olasılık dağılımını hesaplamak için \(\text{softmaks}(\mathbf{O})\)’i kullanabiliriz.

Bu, Section 8.1 içinde daha önce çözdüğümüz bağlanım problemine tamamen benzer, dolayısıyla ayrıntıları atlıyoruz. Öznitelik-etiket çiftlerini rastgele seçebileceğimizi ve ağımızın parametrelerini otomatik türev alma ve rasgele eğim inişi yoluyla öğrenebileceğimizi söylemek yeterli.

8.4.2. Gizli Durumlu Yinelemeli Sinir Ağları

Gizli durumlarımız olduğunda işler tamamen farklıdır. Yapıyı biraz daha ayrıntılı olarak inceleyelim.

\(t\) zaman adımında girdileri \(\mathbf{X}_t \in \mathbb{R}^{n \times d}\) olan bir minigrubumuz olduğunu varsayalım. Başka bir deyişle, \(n\) dizi örneklerinden oluşan bir minigrup için, \(\mathbf{X}_t\)’nin her satırı, dizinin \(t\) adımındaki bir örneğine karşılık gelir. Ardından, \(\mathbf{H}_t \in \mathbb{R}^{n \times h}\) ile \(t\) zaman adımındaki gizli değişkeni belirtelim. MLP’den farklı olarak, burada gizli değişkeni \(\mathbf{H}_{t-1}\)’yi önceki zaman adımından kaydediyoruz ve şimdiki zaman adımında önceki zaman adımının gizli değişkeni nasıl kullanılacağını açıklamak için \(\mathbf{W}_{hh} \in \mathbb{R}^{h \times h}\) yeni ağırlık parametresini tanıtıyoruz. Özellikle, şimdiki zaman adımının gizli değişkeninin hesaplanması, önceki zaman adımının gizli değişkeni ile birlikte şimdiki zaman adımının girdisi tarafından belirlenir:

(8.4.5)\[\mathbf{H}_t = \phi(\mathbf{X}_t \mathbf{W}_{xh} + \mathbf{H}_{t-1} \mathbf{W}_{hh} + \mathbf{b}_h).\]

(8.4.3) ile karşılaştırıldığında, (8.4.5) bir terim daha, \(\mathbf{H}_{t-1} \mathbf{W}_{hh}\), ekler ve böylece (8.4.2)’den bir örnek oluşturur. Bitişik zaman adımlarındaki \(\mathbf{H}_t\) ve \(\mathbf{H}_{t-1}\) gizli değişkenlerinin arasındaki ilişkiden, bu değişkenlerin dizinin tarihsel bilgilerini şu anki zaman adımına kadar yakaladığını ve sakladığını biliyoruz; tıpkı sinir ağının şimdiki zaman adımının durumu veya hafızası gibi. Bu nedenle, böyle bir gizli değişken gizli durum olarak adlandırılır. Gizli durum şu anki zaman adımında önceki zaman adımının aynı tanımını kullandığından, (8.4.5)’nın hesaplanması yinelemedir. Bu nedenle, yinelemeli hesaplamalara dayalı gizli durumlara sahip sinir ağları yinelemeli sinir ağlarıdır. RNN’lerde (8.4.5)’ün hesaplanmasını gerçekleştiren katmanlar yinelemeli katmanlar olarak adlandırılır.

RNN oluşturmak için birçok farklı yol vardır. (8.4.5) içinde tanımlanan gizli bir duruma sahip RNN’ler çok yaygındır. Zaman adımı \(t\) için çıktı katmanının çıktısı MLP’deki hesaplamaya benzer:

(8.4.6)\[\mathbf{O}_t = \mathbf{H}_t \mathbf{W}_{hq} + \mathbf{b}_q.\]

RNN parametreleri gizli katmanın \(\mathbf{W}_{xh} \in \mathbb{R}^{d \times h}, \mathbf{W}_{hh} \in \mathbb{R}^{h \times h}\) ağırlıkları ve \(\mathbf{b}_h \in \mathbb{R}^{1 \times h}\) ek girdisi ile birlikte çıktı katmanının \(\mathbf{W}_{hq} \in \mathbb{R}^{h \times q}\) ağırlıklarını ve \(\mathbf{b}_q \in \mathbb{R}^{1 \times q}\) ek girdilerini içerir. Farklı zaman adımlarında bile, RNN’lerin her zaman bu model parametrelerini kullandığını belirtmek gerekir. Bu nedenle, bir RNN parametrelendirmenin maliyeti zaman adım sayısı arttıkça büyümez.

Fig. 8.4.1, bitişik üç zaman adımında bir RNN’nin hesaplama mantığını göstermektedir. Herhangi bir \(t\) zaman adımında, gizli durumun hesaplanması şu şekilde düşünülebilir: (i) \(t\) şimdiki zaman adımındaki \(\mathbf{X}_t\) girdisi ile önceki \(t-1\) zaman adımındaki \(\mathbf{H}_{t-1}\) gizli durumu bitiştirme; (ii) bitiştirme sonucunu \(\phi\) etkinleştirme fonksiyonlu tam bağlı bir katmana besleme. Bu şekilde tam bağlı bir katmanın çıktısı, \(t\) şimdiki zaman adımı \(\mathbf{H}_t\) gizli durumudur. Bu durumda, model parametrelerinin hepsi (8.4.5)’teki \(\mathbf{W}_{xh}\) ve \(\mathbf{W}_{hh}\)’ün bitiştirilmesi ve \(\mathbf{b}_h\) ek girdisidir. Şimdiki \(t\) zaman adımının \(\mathbf{H}_t\) gizli durumu, sonraki \(t+1\) adımının \(\mathbf{H}_{t+1}\) gizli durumunun hesaplanmasına katılacaktır. Dahası, \(\mathbf{H}_t\), \(t\) şimdiki zaman adımının \(\mathbf{O}_t\) çıktısını hesaplamak için tam bağlı çıktı katmanına da beslenir.

../_images/rnn.svg

Fig. 8.4.1 Gizli duruma sahip bir RNN.

Gizli durum \(\mathbf{X}_t \mathbf{W}_{xh} + \mathbf{H}_{t-1} \mathbf{W}_{hh}\) hesaplamasının \(\mathbf{X}_t\) ve \(\mathbf{H}_{t-1}\) ile \(\mathbf{W}_{xh}\) ve \(\mathbf{W}_{hh}\) bitişik matrislerinin çarpmasına eşdeğer olduğunu belirttik. Bu matematiksel olarak kanıtlanmış olsa da, aşağıda kısaca bunu göstermek için basit bir kod parçacığı kullanıyoruz. Başlangıç olarak, şekilleri (3, 1), (1, 4), (3, 4) ve (4, 4) olan X, W_xh, H ve W_hh matrislerini tanımlıyoruz. Sırasıyla X ile W_xh’yi ve H ile W_hh’yi çarpıyoruz ve daha sonra bu iki çarpımı toplayarak (3, 4) şekilli bir matris elde ederiz.

from d2l import mxnet as d2l
from mxnet import np, npx

npx.set_np()

X, W_xh = np.random.normal(0, 1, (3, 1)), np.random.normal(0, 1, (1, 4))
H, W_hh = np.random.normal(0, 1, (3, 4)), np.random.normal(0, 1, (4, 4))
np.dot(X, W_xh) + np.dot(H, W_hh)
array([[-0.21952915,  4.256434  ,  4.5812645 , -5.344988  ],
       [ 3.447858  , -3.0177274 , -1.6777471 ,  7.535347  ],
       [ 2.2390068 ,  1.4199957 ,  4.744728  , -8.421293  ]])
import torch
from d2l import torch as d2l

X, W_xh = torch.normal(0, 1, (3, 1)), torch.normal(0, 1, (1, 4))
H, W_hh = torch.normal(0, 1, (3, 4)), torch.normal(0, 1, (4, 4))
torch.matmul(X, W_xh) + torch.matmul(H, W_hh)
tensor([[ 0.3322,  1.6809,  0.7737,  2.3295],
        [ 4.1095,  4.0970, -2.6380,  4.0622],
        [ 3.0638, -3.0190,  1.5716,  0.1028]])
import tensorflow as tf
from d2l import tensorflow as d2l

X, W_xh = tf.random.normal((3, 1), 0, 1), tf.random.normal((1, 4), 0, 1)
H, W_hh = tf.random.normal((3, 4), 0, 1), tf.random.normal((4, 4), 0, 1)
tf.matmul(X, W_xh) + tf.matmul(H, W_hh)
<tf.Tensor: shape=(3, 4), dtype=float32, numpy=
array([[ 2.1165783 ,  3.1748667 , -1.2845695 , -0.36299136],
       [-1.6181667 ,  0.3945769 , -1.4171336 , -2.990293  ],
       [-2.4005675 , -0.65433574,  0.97808754,  0.28706658]],
      dtype=float32)>

Şimdi X ve H matrislerini sütunlar boyunca (eksen 1) ve W_xh ve W_hh matrislerini satırlar boyunca (eksen 0) bitiştiririz. Bu iki bitiştirme, sırasıyla (3, 5) ve (5, 4) şekilli matrisler ile sonuçlanır. Bu iki bitiştirilmiş matrisi çarparak, yukarıdaki gibi (3, 4) şekilli aynı çıktı matrisini elde ederiz.

np.dot(np.concatenate((X, H), 1), np.concatenate((W_xh, W_hh), 0))
array([[-0.21952918,  4.256434  ,  4.5812645 , -5.344988  ],
       [ 3.4478583 , -3.0177271 , -1.677747  ,  7.535347  ],
       [ 2.2390068 ,  1.4199957 ,  4.744728  , -8.421294  ]])
torch.matmul(torch.cat((X, H), 1), torch.cat((W_xh, W_hh), 0))
tensor([[ 0.3322,  1.6809,  0.7737,  2.3295],
        [ 4.1095,  4.0970, -2.6380,  4.0622],
        [ 3.0638, -3.0190,  1.5716,  0.1028]])
tf.matmul(tf.concat((X, H), 1), tf.concat((W_xh, W_hh), 0))
<tf.Tensor: shape=(3, 4), dtype=float32, numpy=
array([[ 2.1165783 ,  3.1748667 , -1.2845696 , -0.36299136],
       [-1.6181666 ,  0.39457688, -1.4171335 , -2.990293  ],
       [-2.4005678 , -0.65433586,  0.9780875 ,  0.28706652]],
      dtype=float32)>

8.4.3. RNN Tabanlı Karakter Düzeyinde Dil Modelleri

Section 8.3 içindeki dil modellemesi için şimdiki ve geçmiş andıçlara dayanarak bir sonraki simgeyi tahmin etmeyi amaçladığımızı hatırlayın, böylece orijinal diziyi etiketler olarak bir andıç kaydırıyoruz. Bengio ve ark. önce dil modelleme için bir sinir ağı kullanmayı önerdi (Bengio et al., 2003). Aşağıda, bir dil modeli oluşturmak için RNN’lerin nasıl kullanılabileceğini gösteriyoruz. Minigrup boyutu bir olsun ve metnin sırası “makine” (machine) olsun. Sonraki bölümlerdeki eğitimi basitleştirmek için, metni sözcükler yerine karakterler haline getiririz ve karakter düzeyinde bir dil modelini göz önünde bulundururuz. Fig. 8.4.2, karakter düzeyinde dil modellemesi için bir RNN aracılığıyla şimdiki ve önceki karakterlere dayanarak bir sonraki karakterin nasıl tahmin edileceğini gösterir.

../_images/rnn-train.svg

Fig. 8.4.2 RNN’ye dayalı karakter düzeyinde bir dil modeli. Girdi ve etiket dizileri sırasıyla “machin” ve “achine” dir.

Eğitim işlemi sırasında, çıktı katmanından çıktıda her zaman adım için bir softmaks işlemi çalıştırırız ve daha sonra model çıktısı ile etiket arasındaki hatayı hesaplamak için çapraz entropi kaybını kullanırız. Gizli katmandaki gizli durumun yinelemeli hesaplanması nedeniyle, Fig. 8.4.2, \(\mathbf{O}_3\)’teki 3. zaman adımının çıktısı, “m”, “a” ve “c” metin dizisi ile belirlenir. Eğitim verilerindeki dizinin bir sonraki karakteri “h” olduğu için, 3. zaman adımının kaybı, “m”, “a”, “c”’ye göre oluşturulan bir sonraki karakterin olasılık dağılımına ve bu zaman adımının “h” etiketine bağlı olacaktır.

Uygulamada, her andıç bir \(d\) boyutlu vektör ile temsil edilir ve grup boyutu olarak \(n>1\) kullanırız. Bu nedenle, \(t\)’deki \(\mathbf X_t\) girdisi Section 8.4.2 içinde tartıştığımız gibi \(n\times d\) şekilli bir matris olacaktır.

8.4.4. Şaşkınlık

Son olarak, sonraki bölümlerde RNN tabanlı modellerimizi değerlendirmek için kullanılacak dil modelinin kalitesini nasıl ölçeceğimizi tartışalım. Bir yol, metnin ne kadar şaşırtıcı olduğunu kontrol etmektir. İyi bir dil modeli, daha sonra ne göreceğimizi yüksek hassasiyetli andıçlarla tahmin edebilir. Farklı dil modelleri tarafından önerilen “Yağmur yağıyor” ifadesinin aşağıdaki devamlarını göz önünde bulundurun:

  1. “Dışarıda yağmur yağıyor”

  2. “Muz ağacı yağıyor”

  3. “Piouw yağıyor; kcj pwepoiut”

Kalite açısından, örnek 1 açıkça en iyisidir. Sözcükler mantıklı ve mantıksal olarak da tutarlı. Hangi kelimenin anlamsal olarak takip ettiğini tam olarak doğru bir şekilde yansıtmayabilir (“San Francisco’da” ve “kışın” mükemmel şekilde makul uzantıları olurdu), ama model hangi kelimenin takip edebileceğini yakalayabilir. Örnek 2, mantıksız bir uzantı ürettiğinden oldukça kötüdür. Yine de, model en azından kelimelerin nasıl yazılacağını ve kelimeler arasındaki korelasyon derecesini öğrendi. Son olarak, örnek 3, veriye düzgün şekilde uymayan kötü eğitilmiş bir modeli gösterir.

Dizinin olabilirliğini hesaplayarak modelin kalitesini ölçebiliriz. Ne yazık ki bu, anlaşılması ve karşılaştırılması zor bir sayıdır. Sonuçta, daha kısa dizilerin daha uzun olanlara göre gerçekleşme olasılığı daha yüksektir, bu nedenle model Tolstoy’un şaheseri Savaş ve Barış’ı değerlendirirken kaçınılmaz olarak Saint-Exupery’nin “Küçük Prens” romanından çok daha küçük bir olabilirlik üretecektir. Eksik olan bir ortalama eşdeğeridir.

Bilgi teorisi burada işe yarar. Softmaks bağlanımını (Section 3.4.7) tanıttığımızda entropiyi, sürprizi ve çapraz entropiyi tanımladık ve bilgi teorisi üzerine çevrimiçi ek’de bilgi teorisi daha fazla tartışılmaktadır. Metni sıkıştırmak istiyorsak, geçerli andıç kümesi verilince bir sonraki andıcı tahmin etmeyi sorabiliriz. Daha iyi bir dil modeli, bizim bir sonraki andıcı daha doğru tahmin etmemizi sağlamalıdır. Böylece, diziyi sıkıştırmak için daha az bit harcamamıza izin vermelidir. Böylece, bir dizinin tüm \(n\) andıçları üzerinden ortalamasıyla çapraz entropi kaybıyla ölçebiliriz:

(8.4.7)\[\frac{1}{n} \sum_{t=1}^n -\log P(x_t \mid x_{t-1}, \ldots, x_1),\]

Burada \(P\) bir dil modeli tarafından verilir ve \(x_t\), diziden \(t\) adımında gözlenen gerçek andıçtır. Bu, farklı uzunluklardaki belgelerdeki performansları karşılaştırılabilir hale getirir. Tarihsel nedenlerden dolayı, doğal dil işlemedeki bilim adamları şaşkınlık (perplexity) adı verilen bir ölçüm kullanmayı tercih ederler. Kısacası, (8.4.7)’ün üssüdür:

(8.4.8)\[\exp\left(-\frac{1}{n} \sum_{t=1}^n \log P(x_t \mid x_{t-1}, \ldots, x_1)\right).\]

Şaşkınlık, en iyi hangi andıcı seçeceğimize karar verirken sahip olduğumuz gerçek seçeneklerin sayısının harmonik ortalaması olarak anlaşılabilir. Birkaç vakaya bakalım:

  • En iyi senaryoda, model her zaman etiket andıcı olasılığını 1 olarak mükemmel şekilde tahmin eder. Bu durumda modelin şaşkınlığı 1’dir.

  • En kötü senaryoda, model her zaman etiket andıcı olasılığını 0 olarak öngörür. Bu durumda şaşkınlık pozitif sonsuzdur.

  • Referans olarak model, sözcük dağarcığının tüm kullanılabilir andıçları üzerinde tekdüze bir dağılım öngörür. Bu durumda, şaşkınlık, kelime dağarcığının benzersiz andıçlarının sayısına eşittir. Aslında, diziyi herhangi bir sıkıştırma olmadan saklarsak, kodlamak için yapabileceğimiz en iyi şey bu olurdu. Bu nedenle, bu, herhangi bir yararlı modelin yenmesi gereken bariz bir üst sınır sağlar.

Aşağıdaki bölümlerde, karakter düzeyi dil modelleri için RNN’leri uygulayacağız ve bu modelleri değerlendirmek için şaşkınlığı kullanacağız.

8.4.5. Özet

  • Gizli durumlar için yinelemeli hesaplama kullanan bir sinir ağı, yinelemeli bir sinir ağı (RNN) olarak adlandırılır.

  • Bir RNN’nin gizli durumu, dizinin şimdiki zaman adımına kadarki geçmiş bilgilerini tutabilir.

  • Zaman adımlarının sayısı arttıkça RNN model parametrelerinin sayısı artmaz.

  • Bir RNN kullanarak karakter düzeyinde dil modelleri oluşturabiliriz.

  • Dil modellerinin kalitesini değerlendirmek için şaşkınlığı kullanabiliriz.

8.4.6. Alıştırmalar

  1. Bir metin dizisindeki bir sonraki karakteri tahmin etmek için bir RNN kullanırsak, bir çıktı için gerekli boyut nedir?

  2. RNN’ler bir zaman adımındaki andıcın metin dizisindeki önceki tüm andıçlara dayalı koşullu olasılığını nasıl ifade edebilir?

  3. Uzun bir dizide geri yayarsak gradyana ne olur?

  4. Bu bölümde açıklanan dil modeliyle ilgili sorunlar nelerdir?