#python #tensorflow #machine-learning #pytorch #regression
#python #tensorflow #машинное обучение #pytorch #регрессия
Вопрос:
Я изучаю pytorch, чтобы сделать базовую линейную регрессию по этим данным, созданным таким образом здесь:
from sklearn.datasets import make_regression
x, y = make_regression(n_samples=100, n_features=1, noise=15, random_state=42)
y = y.reshape(-1, 1)
print(x.shape, y.shape)
plt.scatter(x, y)
Я знаю, что с помощью tensorflow этот код может решить:
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Dense(units=1, activation='linear', input_shape=(x.shape[1], )))
model.compile(optimizer=tf.keras.optimizers.SGD(lr=0.05), loss='mse')
hist = model.fit(x, y, epochs=15, verbose=0)
но мне нужно знать, каким будет эквивалент pytorch, я пытался сделать это:
# Model Class
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.linear = nn.Linear(1,1)
def forward(self, x):
x = self.linear(x)
return x
def predict(self, x):
return self.forward(x)
model = Net()
loss_fn = F.mse_loss
opt = torch.optim.SGD(modelo.parameters(), lr=0.05)
# Funcao para treinar
def fit(num_epochs, model, loss_fn, opt, train_dl):
# Repeat for given number of epochs
for epoch in range(num_epochs):
# Train with batches of data
for xb, yb in train_dl:
# 1. Generate predictions
pred = model(xb)
# 2. Calculate Loss
loss = loss_fn(pred, yb)
# 3. Campute gradients
loss.backward()
# 4. Update parameters using gradients
opt.step()
# 5. Reset the gradients to zero
opt.zero_grad()
# Print the progress
if (epoch 1) % 10 == 0:
print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch 1, num_epochs, loss.item()))
# Training
fit(200, model, loss_fn, opt, data_loader)
Но модель ничему не учится, я больше не знаю, что я могу сделать.
Размеры ввода / вывода равны (1/1)
Ответ №1:
Набор данных
Прежде всего, вы должны определить torch.utils.data.Dataset
import torch
from sklearn.datasets import make_regression
class RegressionDataset(torch.utils.data.Dataset):
def __init__(self):
data = make_regression(n_samples=100, n_features=1, noise=0.1, random_state=42)
self.x = torch.from_numpy(data[0]).float()
self.y = torch.from_numpy(data[1]).float()
def __len__(self):
return len(self.x)
def __getitem__(self, index):
return self.x[index], self.y[index]
Он преобразует numpy
данные в tensor
внутри __init__
PyTorch и преобразует данные в float
( numpy
имеет double
по умолчанию, в то время как PyTorch по умолчанию float
, чтобы использовать меньше памяти).
Кроме того, он просто вернет tuple
функции и соответствующие цели регрессии.
Подходит
Почти получилось, но вам нужно сгладить вывод из модели (описано ниже). torch.nn.Linear
вернет тензоры формы (batch, 1)
, пока ваши цели имеют форму (batch,)
. flatten()
удалит ненужное 1
измерение.
# 2. Calculate Loss
loss = criterion(pred.flatten(), yb)
Модель
Это все, что вам нужно на самом деле:
model = torch.nn.Linear(1, 1)
Любой уровень может быть вызван напрямую, нет необходимости в forward
и наследовании для простых моделей.
Вызов
Остальное почти в порядке, вам просто нужно создать torch.utils.data.DataLoader
и передать экземпляр нашего набора данных. Что DataLoader
делает, это выдает __getitem__
dataset
несколько раз и создает пакет указанного размера (есть и другие забавные вещи, но это идея):
dataset = RegressionDataset()
dataloader = torch.utils.data.DataLoader(dataset, batch_size=32)
model = torch.nn.Linear(1, 1)
criterion = torch.nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=3e-4)
fit(5000, model, criterion, optimizer, dataloader)
Также обратите внимание, что я использовал torch.nn.MSELoss()
, поскольку мы передаем объект, в этом случае он выглядит лучше, чем функция.
Весь код
Чтобы упростить:
import torch
from sklearn.datasets import make_regression
class RegressionDataset(torch.utils.data.Dataset):
def __init__(self):
data = make_regression(n_samples=100, n_features=1, noise=0.1, random_state=42)
self.x = torch.from_numpy(data[0]).float()
self.y = torch.from_numpy(data[1]).float()
def __len__(self):
return len(self.x)
def __getitem__(self, index):
return self.x[index], self.y[index]
# Funcao para treinar
def fit(num_epochs, model, criterion, optimizer, train_dl):
# Repeat for given number of epochs
for epoch in range(num_epochs):
# Train with batches of data
for xb, yb in train_dl:
# 1. Generate predictions
pred = model(xb)
# 2. Calculate Loss
loss = criterion(pred.flatten(), yb)
# 3. Compute gradients
loss.backward()
# 4. Update parameters using gradients
optimizer.step()
# 5. Reset the gradients to zero
optimizer.zero_grad()
# Print the progress
if (epoch 1) % 10 == 0:
print(
"Epoch [{}/{}], Loss: {:.4f}".format(epoch 1, num_epochs, loss.item())
)
dataset = RegressionDataset()
dataloader = torch.utils.data.DataLoader(dataset, batch_size=32)
model = torch.nn.Linear(1, 1)
criterion = torch.nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=3e-4)
fit(5000, model, criterion, optimizer, dataloader)
Вы должны обойти 0.053
потерю или около того, варьировать noise
или другие параметры для более сложной / легкой задачи регрессии.
Комментарии:
1. @manynothing Хотя благодарность естественна, здесь мы благодарим голосованием и принимаем ответ, который вы уже сделали (такие комментарии создают ненужный шум). Рад, что смог помочь, добро пожаловать в StackOverflow! 🙂