Я пытаюсь реализовать мини-пакетный градиентный спуск на популярном датасете iris, но как-то не получается получить точность модели выше 75-80%. Кроме того, потери не уменьшаются и застревают на уровне около 0,45, даже когда я устанавливаю количество итераций на 10000. Что-то мне здесь не хватает?
class NeuralNetwork(nn.Module):
def __init__(self):
super().__init__()
self.linear_stack = nn.Sequential(
nn.Linear(4,128),
nn.ReLU(),
nn.Linear(128,64),
nn.ReLU(),
nn.Linear(64,3),
)
def forward(self, x):
logits = self.linear_stack(x)
return logits
цикл обучения, размер пакета на эпоху = 10. transform_label сопоставляет [0,1,2] с метками.
lr = 0.01
model = NeuralNetwork()
optim = torch.optim.Adam(model.parameters(), lr=lr)
loss = torch.nn.CrossEntropyLoss()
n_iters = 1000
steps = n_iters/10
LOSS = []
for epochs in range(n_iters):
for i,(inputs, labels) in enumerate(train_loader):
out = model(inputs)
train_labels = transform_label(labels)
l = loss(out, train_labels)
l.backward()
#update weights
optim.step()
optim.zero_grad()
LOSS.append(l.item())
if epochs%steps == 0:
print(f"\n epoch: {int(epochs+steps)}/{n_iters}, loss: {sum(LOSS)/len(LOSS)}")
#if i % 1 == 0:
#print(f" steps: {i+1}, loss : {l.item()}")
выход:
эпоха: 100/1000, потеря: 1.0636296272277832
эпоха: 400/1000, потери: 0,5142968013338076
эпоха: 500/1000, потери: 0,49906910391073867
эпоха: 900/1000, потери: 0,4586030915751588
эпоха: 1000/1000, потери: 0,4543738731996598
Можно ли так рассчитать потери или мне следует использовать torch.max()? Если я это сделаю, я получаю эту ошибку:
Ожидаемый тип с плавающей запятой для цели с вероятностями класса, получил Long
вы не предоставили достаточно данных и кода для воспроизведения проблемы. Я написал полный и работающий код для обучения вашей модели набору данных IRIS.
Импорт и классы.
import torch
from torch import nn
import pandas as pd
from torch.utils.data import Dataset, DataLoader
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, LabelEncoder
from sklearn.metrics import classification_report
class MyDataset(Dataset):
def __init__(self, X, Y):
assert len(X) == len(Y)
self.X = X
self.Y = Y
def __len__(self):
return len(self.X)
def __getitem__(self, item):
x = self.X[item]
y = self.Y[item]
return x, y
class NeuralNetwork(nn.Module):
def __init__(self):
super().__init__()
self.linear_stack = nn.Sequential(
nn.Linear(4,128),
nn.ReLU(),
nn.Linear(128,64),
nn.ReLU(),
nn.Linear(64,3),
)
def forward(self, x):
logits = self.linear_stack(x)
return logits
Прочитайте и предварительно обработайте данные.
# Dataset was downloaded from https://archive.ics.uci.edu/ml/machine-learning-databases/iris/
df = pd.read_csv("iris.data", names=["x1", "x2", "x3", "x4", "label"])
X, Y = df[['x1', "x2", "x3", "x4"]], df['label']
# First, we transform the labels to numbers 0,1,2
encoder = LabelEncoder()
Y = encoder.fit_transform(Y)
# We split the dataset to train and test
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, random_state=123)
# Due to the nature of Neural Networks, we standardize the inputs to get better results
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
train_dataset = MyDataset(X_train, Y_train)
test_dataset = MyDataset(X_test, Y_test)
train_loader = DataLoader(train_dataset, batch_size=8)
test_loader = DataLoader(test_dataset, batch_size=8)
Обучите модель.
lr = 0.01
model = NeuralNetwork()
optim = torch.optim.Adam(model.parameters(), lr=lr)
loss = torch.nn.CrossEntropyLoss()
n_iters = 1000
steps = n_iters/10
LOSS = []
for epochs in range(n_iters):
for i,(inputs, labels) in enumerate(train_loader):
optim.zero_grad()
out = model(inputs.float())
l = loss(out, labels)
l.backward()
optim.step()
LOSS.append(l.item())
if epochs%steps == 0:
print(f"\n epoch: {int(epochs+steps)}/{n_iters}, loss: {sum(LOSS)/len(LOSS)}")
выход:
Затем нам нужно запустить модель на тестовых данных, чтобы рассчитать метрики.
preds = []
with torch.no_grad():
for i,(inputs, labels) in enumerate(test_loader):
out = model(inputs.float())
preds.extend(list(torch.argmax(out, axis=1).cpu().numpy()))
Чтобы получить метрики, вы можете использовать «classification_report».
print(classification_report(y_true=Y_test, y_pred=preds))
выход:
Я надеюсь, что мой ответ поможет вам.
Эй, большое спасибо за усилия. Ваш ответ очень помогает. Сначала я подумал, может быть, потому, что я не масштабировал ввод, как вы сделали с «scaler = StandardScaler()», но даже при удалении этой части он все равно дает лучшие результаты. Как-то это связано с тем, как я загружаю данные, я думаю, ваш способ сделать это кажется более эффективным и простым. Я пытался следовать этому руководству: pytorch.org/tutorials/beginner/basics/data_tutorial.html. Тем не менее, я очень благодарен за ваш ответ!