Introduction
Uzun Kısa Süreli Bellek (LSTM), derin öğrenme alanında yaygın olarak kullanılan bir yapay sinir ağı türüdür. LSTM, RNN'in kaybolan/patlayan gradyan probleminden kaçınmak için geliştirilmiştir. Ancak, LSTM ağları hala patlayan gradyan probleminden muzdarip olabilir. Özel hafıza yeteneği sayesinde, LSTM genellikle zaman serisi tahmini için kullanılır. Bu makalede, LSTM mimarisinden ve bu mimariyi PyTorch ile inşa etmekten bahsetmek istiyorum.
Mimari
LSTM'de iki tür bellek vardır. Bunlardan biri, şekilde yeşil çizgi ile gösterilen uzun süreli bellek. Kırmızı çizgi ise kısa süreli belleği gösterir. Ayrıca, LSTM'de giriş, çıkış ve unutma kapısı bulunur.
Hesaplamalar
Son uzun süreli değerinin 2 (yeşil), kısa süreli değerinin 1 (kırmızı) ve girişin 1 (gri) olduğunu varsayıyoruz. Ayrıca, başlangıç ağırlıklarını ve biaslarını yazdım.
Şimdi çıktıyı hesaplayalım.
Unutma Kapısı (Forget Gate)
(1 x 2.2) + (1 x 2.7) = 4.9
4.9 + 2.3 = 7.2
sigmoid(7.2) = 1
Hatırlatma;
Unutma kapısı (forget gate) çıktımız 1'dir. Bunu 2 ile çarptığımızda, ilk uzun süreli bellek değerimiz 2 olur.
Giriş kapısı (Input Gate)
Yeşil Hücre
(1 x 1.1) + (1 x 0.8) = 1.9
1.9 + 0.8 = 2.7
sigmoid(2.7) = 0.937
Sarı Hücre
(1 x 0.4) + (1 x 1.2) = 1.6
1.6 + 0.9 = 2.5
tanh(2.5) = 0.987
Hatırlatma;
Bu iki hücreyi çarpıp uzun süreli belleğe ekleriz.
2 + 0.987 = 2.987
Çıkış Kapısı (Output Gate)
Gri hücre
(1 x 0.3) + (1 x 2.9) = 3.2
3.2 + 2.1 = 5.3
sigmoid(5.3) = 0.995
Pembe hücre
tanh(2.987) = 0.995
Bu değeri yeşil hücre çıktısıyla çarparız.
0.995 x 0.995 = 0.9899
Son olarak, yeni kısa bellek değerimiz 0.9899 olur. Bu hesaplama, yeni giriş değerleriyle devam eder. Ve tekrar tekrar aynı süreç işler.
Bu, ileri yayılmadır (forward propagation). Algoritma son çıktıyı hesapladığında, geri yayılım (back propagation) devreye girer. Geri yayılımın görevi, kaybı azaltmaktır.
Şimdi Sıra Kodlarda
Kütüphaneler
Öncelikle, gerekli kütüphaneleri içe aktarmamız gerekiyor. Lightning kütüphanesi, mimariyi oluşturmamıza yardımcı oluyor.
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.optim import Adam
import lightning as L
Ağırlıklar ve biaslar
Şimdi ağırlıkları ve biasları yerleştirmemiz gerekiyor. Bundan önce, Lightning modülünü içeren bir sınıf tanımlıyorum.
class SimpleLSTM(L.LightningModule):
def __init__(self):
super().__init__()
mean = torch.tensor(0.0)
std = torch.tensor(1.0)
# Blue cell weights and biases
self.wbc1 = nn.Parameter(torch.normal(mean=mean,std=std),requires_grad=True)
self.wbc2 = nn.Parameter(torch.normal(mean=mean,std=std),requires_grad=True)
self.bbc1 = nn.Parameter(torch.tensor(0.),requires_grad=True)
# Green cell weights and biases
self.wgc1 = nn.Parameter(torch.normal(mean=mean,std=std),requires_grad=True)
self.wgc2 = nn.Parameter(torch.normal(mean=mean,std=std),requires_grad=True)
self.bgc1 = nn.Parameter(torch.tensor(0.),requires_grad=True)
# Yellow cell weights and biases
self.wyc1 = nn.Parameter(torch.normal(mean=mean,std=std),requires_grad=True)
self.wyc2 = nn.Parameter(torch.normal(mean=mean,std=std),requires_grad=True)
self.byc1 = nn.Parameter(torch.tensor(0.),requires_grad=True)
# Gray cell weights and biases
self.wpc1 = nn.Parameter(torch.normal(mean=mean,std=std),requires_grad=True)
self.wpc2 = nn.Parameter(torch.normal(mean=mean,std=std),requires_grad=True)
self.bpc1 = nn.Parameter(torch.tensor(0.),requires_grad=True)
"requires_grad = True" özelliği, geri yayılım sırasında değerlerin kayba göre değişeceğini belirtir. Ağırlıkları ve biasları, örnekte yaptığımız gibi yerleştirdim.
class SimpleLSTM(L.LightningModule):
def __init__(self):
super().__init__()
self.wbc1 = 2.7
self.wbc2 = 2.2
self.bbc1 = 2.3
self.wgc1 = 1.1
self.wgc2 = 0.8
self.bgc1 = 0.8
self.wyc1 = 0.4
self.wyc2 = 1.2
self.byc1 = 0.9
self.wgrc1 = 0.3
self.wgrc2 = 2.9
self.bgrc1 = 2.1
Hücreler
Giriş değeri, uzun süreli bellek ve kısa süreli belleği tanımladım. Ardından, tüm hücreleri şekildeki gibi birbirine bağladım.
def lstm_cells(self, input_value, long_memory, short_memory):
blue_cell = torch.sigmoid((short_memory * self.wbc1) +
(input_value * self.wbc2) +
self.bbc1)
green_cell = torch.sigmoid((short_memory * self.wgc1) +
(input_value * self.wgc2)+
self.bbc1)
yellow_cell= torch.tanh((short_memory * self.wyc1) +
(input_value * self.wyc2) + self.byc1)
updated_long_memory = ((long_memory * blue_cell) +
(green_cell * yellow_cell))
gray_cell= torch.sigmoid((short_memory * self.wgrc) +
(input_value * self.wgrc2) + self.bgrc1)
updated_short_memory = torch.tanh(updated_long_memory) * gray_cell
return ([updated_long_memory,updated_short_memory])
İleri yayılım (Forward Propagation)
Uzun süreli bellek değerlerini 2, kısa süreli belleği ise 1 olarak seçtim.
def forward(self, input):
long_memory = 2
short_memory = 1
value = input[0]
long_memory, short_memory = self.lstm_cells(value, long_memory, short_memory)
return short_memory
Tahmin
Modeli tanımladım ve değeri tahmin ettim.
class SimpleLSTM(L.LightningModule):
def __init__(self):
super().__init__()
self.wlr1 = 2.7
self.wlr2 = 2.2
self.blr1 = 2.3
self.wpr1 = 1.1
self.wpr2 = 0.8
self.bpr1 = 0.8
self.wp1 = 0.4
self.wp2 = 1.2
self.bp1 = 0.9
self.wo1 = 0.3
self.wo2 = 2.9
self.bo1 = 2.1
def lstm_cells(self, input_value, long_memory, short_memory):
blue_cell = torch.sigmoid((short_memory * self.wbc1) +
(input_value * self.wbc2) +
self.bbc1)
green_cell = torch.sigmoid((short_memory * self.wgc1) +
(input_value * self.wgc2)+
self.bbc1)
yellow_cell= torch.tanh((short_memory * self.wyc1) +
(input_value * self.wyc2) + self.byc1)
updated_long_memory = ((long_memory * blue_cell) +
(green_cell * yellow_cell))
gray_cell= torch.sigmoid((short_memory * self.wgrc) +
(input_value * self.wgrc2) + self.bgrc1)
updated_short_memory = torch.tanh(updated_long_memory) * gray_cell
return ([updated_long_memory,updated_short_memory])
def forward(self, input):
long_memory = 2
short_memory = 1
value = input[0]
long_memory, short_memory = self.lstm_cells(value, long_memory, short_memory)
return short_memory
input = 1.
model = SimpleLSTM()
model(torch.tensor([input]).detach())
-OUTPUT-
Predict is
tensor(0.9893)
Sonucun, yukarıdaki yaptığımız örnekle aynı olduğu görünüyor.
Geri yayılım (backpropagation)
Geri yayılım kullanıldığında, model bu şekilde görünür.
Adam'ı optimizasyon algoritması olarak tanımladık.
Model, optimum kayba ulaşana kadar ağırlıkları ve biasları güncellemeye devam eder.
class SimpleLSTM(L.LightningModule):
def __init__(self):
super().__init__()
mean = torch.tensor(0.0)
std = torch.tensor(1.0)
zero = torch.tensor(0.)
# Blue cell weights and biases
self.wbc1 = nn.Parameter(torch.normal(mean=mean,std=std),requires_grad=True)
self.wbc2 = nn.Parameter(torch.normal(mean=mean,std=std),requires_grad=True)
self.bbc1 = nn.Parameter(zero,requires_grad=True)
# Green cell weights and biases
self.wgc1 = nn.Parameter(torch.normal(mean=mean,std=std),requires_grad=True)
self.wgc2 = nn.Parameter(torch.normal(mean=mean,std=std),requires_grad=True)
self.bgc1 = nn.Parameter(zero,requires_grad=True)
# Yellow cell weights and biases
self.wyc1 = nn.Parameter(torch.normal(mean=mean,std=std),requires_grad=True)
self.wyc2 = nn.Parameter(torch.normal(mean=mean,std=std),requires_grad=True)
self.byc1 = nn.Parameter(zero,requires_grad=True)
# Gray cell weights and biases
self.wpc1 = nn.Parameter(torch.normal(mean=mean,std=std),requires_grad=True)
self.wpc2 = nn.Parameter(torch.normal(mean=mean,std=std),requires_grad=True)
self.bpc1 = nn.Parameter(zero,requires_grad=True)
def lstm_cells(self, input_value, long_memory, short_memory):
blue_cell = torch.sigmoid((short_memory * self.wbc1) +
(input_value * self.wbc2) +
self.bbc1)
green_cell = torch.sigmoid((short_memory * self.wgc1) +
(input_value * self.wgc2)+
self.bbc1)
yellow_cell= torch.tanh((short_memory * self.wyc1) +
(input_value * self.wyc2) + self.byc1)
updated_long_memory = ((long_memory * blue_cell) +
(green_cell * yellow_cell))
gray_cell= torch.sigmoid((short_memory * self.wgrc) +
(input_value * self.wgrc2) + self.bgrc1)
updated_short_memory = torch.tanh(updated_long_memory) * gray_cell
return ([updated_long_memory,updated_short_memory])
def forward(self, input):
long_memory = 0
short_memory = 0
value1 = input[0]
value2 = input[1]
value3 = input[2]
value4 = input[3]
long_memory, short_memory = self.lstm_cells(value1, long_memory, short_memory)
long_memory, short_memory = self.lstm_cells(value2, long_memory, short_memory)
long_memory, short_memory = self.lstm_cells(value3, long_memory, short_memory)
long_memory, short_memory = self.lstm_cells(value4, long_memory, short_memory)
return short_memory
def configure_optimizers(self):
return (Adam(self.parameters()))
def training_step(self, batch, batch_idx):
input_i, label_i = batch
output_i = self.forward(input_i[0])
loss = (output_i - label_i)**2
self.log("train_loss",loss)
if (label_i == 0):
self.log("out_0",output_i)
else:
self.log("out_1",output_i)
return loss
LSTM mimarisinden ve bunu PyTorch kullanarak nasıl inşa edileceğinden bahsettik. Umarım yazdıklarım anlaşılır olmuştur. Okuduğunuz için teşekkürler.
Comments