PyTorch версия простой модели Keras LSTM - PullRequest
0 голосов
/ 21 февраля 2019

Попытка перевести простую модель LSTM в Keras в код PyTorch.Модель Keras сходится после всего лишь 200 эпох, в то время как модели PyTorch:

  • требуется гораздо больше эпох, чтобы достичь того же уровня потерь (200 против ~ 8000)
  • , кажется, соответствуетвходные данные, потому что прогнозируемое значение не близко к 100

Это код Keras:

from numpy import array
from keras.models import Sequential
from keras.layers import LSTM
from keras.layers import Dense

X = array([10,20,30,20,30,40,30,40,50,40,50,60,50,60,70,60,70,80]).reshape((6,3,1))
y = array([40,50,60,70,80,90])
model = Sequential()
model.add(LSTM(50, activation='relu', recurrent_activation='sigmoid',  input_shape=(3, 1)))
model.add(Dense(1))
model.compile(optimizer='adam', loss='mse')
model.fit(X, y, epochs=200, verbose=1)
x_input = array([70, 80, 90]).reshape((1, 3, 1))
yhat = model.predict(x_input, verbose=0)
print(yhat)

И это эквивалентный код PyTorch:

from numpy import array
import torch
import torch.nn as nn
import torch.nn.functional as F

X = torch.tensor([10,20,30,20,30,40,30,40,50,40,50,60,50,60,70,60,70,80]).float().reshape(6,3,1)
y = torch.tensor([40,50,60,70,80,90]).float().reshape(6,1)

class Model(nn.Module):
  def __init__(self):
    super(Model, self).__init__()
    self.lstm = nn.LSTM(input_size=1, hidden_size=50, num_layers=1, batch_first=True)
    self.fc = nn.Linear(50, 1)

  def forward(self, x):
    batches = x.size(0)
    h0 = torch.zeros([1, batches, 50])
    c0 = torch.zeros([1, batches, 50])
    (x, _) = self.lstm(x, (h0, c0))
    x = x[:,-1,:]  # Keep only the output of the last iteration. Before shape (6,3,50), after shape (6,50)
    x = F.relu(x)
    x = self.fc(x)
    return x

model = Model()
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters())

n_epochs = 8000
for epoch in range(n_epochs):
  model.train()
  optimizer.zero_grad()
  y_ = model(X)
  loss = criterion(y_, y)
  loss.backward()
  optimizer.step()
  print(f"Epoch {epoch+1}/{n_epochs}, loss = {loss.item()}")

model.eval()
x_input = torch.tensor([70, 80, 90]).float().reshape((1, 3, 1))
yhat = model(x_input)
print(yhat)

Единственная возможная разница - это начальные значения веса и смещения, но я не думаю, что слегка отличающиеся веса и смещения могут объяснить такую ​​большую разницу в поведении.Чего мне не хватает в коде PyTorch?

1 Ответ

0 голосов
/ 22 февраля 2019

Различие в поведении связано с функцией активации в LSTM API.Изменяя активацию на tanh, я могу воспроизвести проблему и в Keras.

model.add (LSTM (50, активация = 'tanh' , recurrent_activation = 'sigmoid', input_shape =(3, 1)))

Нет возможности изменить функцию активации на 'relu' в API-интерфейсе pytorch LSTM.https://pytorch.org/docs/stable/nn.html#lstm

Если взять отсюда реализацию LSTM, https://github.com/huggingface/torchMoji/blob/master/torchmoji/lstm.py и изменить hardsigmoid / tanh на sigmoid / relu, модель также сходится в pytorch.

...