🏷️sec_deep_rnn
Şimdiye kadar, tek bir tek yönlü gizli katmanlı RNN'leri tartıştık. İçinde gizli değişkenlerin ve gözlemlerin nasıl etkileşime girdiğinin özgül fonksiyonel formu oldukça keyfidir. Farklı etkileşim türlerini modellemek için yeterli esnekliğe sahip olduğumuz sürece bu büyük bir sorun değildir. Bununla birlikte, tek bir katman ile, bu oldukça zor olabilir. Doğrusal modellerde, daha fazla katman ekleyerek bu sorunu düzelttik. RNN'ler içinde bu biraz daha zor, çünkü öncelikle ek doğrusal olmayanlığın nasıl ve nerede ekleneceğine karar vermemiz gerekiyor.
Aslında, birden fazla RNN katmanını üst üste yığabiliriz. Bu, birkaç basit katmanın kombinasyonu sayesinde esnek bir mekanizma ile sonuçlanır. Özellikle, veriler yığının farklı düzeylerinde alakalı olabilir. Örneğin, finansal piyasa koşulları (hisse alım ve satım piyasası) ile ilgili üst düzey verileri elimizde mevcut tutmak isteyebiliriz, ancak daha düşük bir seviyede yalnızca kısa vadeli zamansal dinamikleri kaydederiz.
Yukarıdaki soyut tartışmaların ötesinde, :numref:fig_deep_rnn
şeklini inceleyerek ilgilendiğimiz model ailesini anlamak muhtemelen en kolay yoldur.
:numref:fig_deep_rnn
içinde tasvir edilen
Bir
$$\mathbf{H}t^{(l)} = \phi_l(\mathbf{H}t^{(l-1)} \mathbf{W}{xh}^{(l)} + \mathbf{H}{t-1}^{(l)} \mathbf{W}_{hh}^{(l)} + \mathbf{b}_h^{(l)}),$$
:eqlabel:eq_deep_rnn_H
burada $\mathbf{W}{xh}^{(l)} \in \mathbb{R}^{h \times h}$ ve $\mathbf{W}{hh}^{(l)} \in \mathbb{R}^{h \times h}$ ağırlıkları
Sonunda, çıktı katmanının hesaplanması yalnızca son
$$\mathbf{O}_t = \mathbf{H}t^{(L)} \mathbf{W}{hq} + \mathbf{b}_q,$$
burada ağırlık
MLP'lerde olduğu gibi, eq_deep_rnn_H
denklemindeki gizli durum hesaplamalarını GRU veya LSTM ile değiştirerek bir derin geçitli RNN elde edebiliriz.
Neyse ki, bir RNN'nin birden fazla katmanını uygulamak için gerekli olan lojistik detayların çoğu, üst düzey API'lerde kolayca mevcuttur. İşleri basit tutmak için sadece bu tür yerleşik işlevleri kullanarak uygulamayı gösteriyoruz. Örnek olarak bir LSTM modelini ele alalım. Kod, daha önce :numref:sec_lstm
içinde kullandığımıza çok benzer. Aslında, tek fark, tek bir katmanlı varsayılanı seçmek yerine açıkça katman sayısını belirtmemizdir. Her zamanki gibi, veri kümesini yükleyerek başlıyoruz.
from d2l import mxnet as d2l
from mxnet import npx
from mxnet.gluon import rnn
npx.set_np()
batch_size, num_steps = 32, 35
train_iter, vocab = d2l.load_data_time_machine(batch_size, num_steps)
#@tab pytorch
from d2l import torch as d2l
import torch
from torch import nn
batch_size, num_steps = 32, 35
train_iter, vocab = d2l.load_data_time_machine(batch_size, num_steps)
#@tab tensorflow
from d2l import tensorflow as d2l
import tensorflow as tf
batch_size, num_steps = 32, 35
train_iter, vocab = d2l.load_data_time_machine(batch_size, num_steps)
Hiper parametre seçimi gibi mimari kararlar :numref:sec_lstm
içindekine çok benzer. Farklı andıçlara sahip olduğumuz için aynı sayıda girdi ve çıktı seçiyoruz, yani vocab_size
. Gizli birimlerin sayısı hala 256'dır. Tek fark, şimdi (apaçık olmayan gizli katmanların sayısını num_layers
değerini belirterek seçmemizdir.)
vocab_size, num_hiddens, num_layers = len(vocab), 256, 2
device = d2l.try_gpu()
lstm_layer = rnn.LSTM(num_hiddens, num_layers)
model = d2l.RNNModel(lstm_layer, len(vocab))
#@tab pytorch
vocab_size, num_hiddens, num_layers = len(vocab), 256, 2
num_inputs = vocab_size
device = d2l.try_gpu()
lstm_layer = nn.LSTM(num_inputs, num_hiddens, num_layers)
model = d2l.RNNModel(lstm_layer, len(vocab))
model = model.to(device)
#@tab tensorflow
vocab_size, num_hiddens, num_layers = len(vocab), 256, 2
num_inputs = vocab_size
device_name = d2l.try_gpu()._device_name
strategy = tf.distribute.OneDeviceStrategy(device_name)
rnn_cells = [tf.keras.layers.LSTMCell(num_hiddens) for _ in range(num_layers)]
stacked_lstm = tf.keras.layers.StackedRNNCells(rnn_cells)
lstm_layer = tf.keras.layers.RNN(stacked_lstm, time_major=True,
return_sequences=True, return_state=True)
with strategy.scope():
model = d2l.RNNModel(lstm_layer, len(vocab))
Şu andan itibaren LSTM modeli ile iki katman oluşturuyoruz, bu oldukça karmaşık mimari eğitimi önemli ölçüde yavaşlatıyor.
#@tab mxnet, pytorch
num_epochs, lr = 500, 2
d2l.train_ch8(model, train_iter, vocab, lr, num_epochs, device)
#@tab tensorflow
num_epochs, lr = 500, 2
d2l.train_ch8(model, train_iter, vocab, lr, num_epochs, strategy)
- Derin RNN'lerde, gizli durum bilgileri şu anki katmanın sonraki zaman adımına ve sonraki katmanın şu anki zaman adımına geçirilir.
- LSTM'ler, GRU'lar veya sıradan RNN gibi derin RNN'lerin birçok farklı seçenekleri vardır. Bu modellerin tümü, derin öğrenme çerçevesinin üst düzey API'lerinin bir parçası olarak mevcuttur.
- Modellerin ilklenmesi dikkat gerektirir. Genel olarak, derin RNN'ler doğru yakınsamayı sağlamak için önemli miktarda iş gerektirir (öğrenme hızı ve kırpma gibi).
- :numref:
sec_rnn_scratch
içinde tartıştığımız tek katmanlı uygulamayı kullanarak sıfırdan iki katmanlı bir RNN uygulamaya çalışın. - LSTM'yi GRU ile değiştirin ve doğruluk ve eğitim hızını karşılaştırın.
- Eğitim verilerini birden fazla kitap içerecek şekilde artırın. Şaşkınlık ölçeğinde ne kadar düşüğe inebilirsin?
- Metni modellerken farklı yazarların kaynaklarını birleştirmek ister misiniz? Bu neden iyi bir fikir? Ne ters gidebilir ki?
:begin_tab:mxnet
Tartışmalar
:end_tab:
:begin_tab:pytorch
Tartışmalar
:end_tab: