Eu criei um pequeno conjunto de dados onde se mantém uma relação linear exata. O código é o seguinte:
import numpy as np
def gen_data(n, k):
np.random.seed(5711)
beta = np.random.uniform(0, 1, size=(k, 1))
print("beta is:", beta)
X = np.random.normal(size=(n, k))
y = X.dot(beta).reshape(-1, 1)
D = np.concatenate([X, y], axis=1)
return D.astype(np.float32)
Agora eu ajustei uma rede neural pyTorch com otimizador SGD e perda MSE e ela convergiu aproximadamente para os valores verdadeiros dentro de 50 épocas e uma taxa de aprendizado de 1e-1
Tentei configurar exatamente o mesmo modelo no tensorflow:
import keras.layers
from sklearn.model_selection import train_test_split
from keras.models import Sequential
import tensorflow as tf
n = 10
k = 2
X = gen_data(n, k)
D_train, D_test = train_test_split(X, test_size=0.2)
X_train, y_train = D_train[:,:k], D_train[:,k:]
X_test, y_test = D_test[:,:k], D_test[:,k:]
model = Sequential([keras.layers.Dense(1)])
model.compile(optimizer=tf.keras.optimizers.SGD(lr=1e-1), loss=tf.keras.losses.mean_squared_error)
model.fit(X_train, y_train, batch_size=64, epochs=50)
Quando chamo model.get_weights ele mostra diferenças substanciais em relação aos valores verdadeiros e a perda ainda não chega nem perto de zero. Não sei por que este modelo não funciona tão bem quanto o modelo pytorch. Mesmo se você desconsiderar o modelo pytorch, a rede não deveria convergir para os valores verdadeiros neste pequeno conjunto de dados de brinquedo. Qual é o meu erro ao configurar o modelo?
EDIT: E aqui está meu código pytorch completo para comparação:
import torch
from torch.utils.data import DataLoader, Dataset, Sampler, SequentialSampler, RandomSampler
from torch import nn
from sklearn.model_selection import train_test_split
n = 10
k = 2
device = "cpu"
class Daten(Dataset):
def __init__(self, df):
self.df = df
self.ycol = df.shape[1] - 1
def __getitem__(self, index):
return self.df[index, :self.ycol], self.df[index, self.ycol:]
def __len__(self):
return self.df.shape[0]
def split_into(D, batch_size=64, **kwargs):
D_train, D_test = train_test_split(D, **kwargs)
df_train, df_test = Daten(D_train), Daten(D_test)
dl_train, dl_test = DataLoader(df_train, batch_size=batch_size), DataLoader(df_test, batch_size=batch_size)
return dl_train, dl_test
D = gen_data(n, k)
dl_train, dl_test = split_into(D, test_size=0.2)
class NeuralNetwork(nn.Module):
def __init__(self):
super().__init__()
self.linear = nn.Sequential(
nn.Linear(k, 1)
)
def forward(self, x):
ypred = self.linear(x)
return ypred
model = NeuralNetwork().to(device)
print(model)
loss_fn = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=1e-1)
def train(dataloader, model, loss_fn, optimizer):
size = len(dataloader.dataset)
model.train()
for batch, (X, y) in enumerate(dataloader):
X, y = X.to(device), y.to(device)
print(y.shape)
# Compute prediction error
pred = model(X)
loss = loss_fn(pred, y)
# Backpropagation
loss.backward()
optimizer.step()
optimizer.zero_grad()
if batch % 100 == 0:
loss, current = loss.item(), (batch + 1) * len(X)
print(f"loss: {loss:>7f} [{current:>5d}/{size:>5d}]")
epochs = 50
for t in range(epochs):
print(f"Epoch {t + 1}\n-------------------------------")
train(dl_train, model, loss_fn, optimizer)
print("Done!")
EDITAR:
Aumentei as épocas dramaticamente. Depois de épocas=1000 chegamos perto dos valores verdadeiros. Portanto, meu melhor palpite para a discrepância é que tf aplica alguma inicialização não ideal?