When training with random data, the loss and model parameters do not change in the for loop.
So, the accuracy is always the same. What’s wrong with my code? Thank you for checking it out.
random data
import torch
X_train = torch.randn(10000, 20, 4)
y_train = (torch.rand(10000) > 0.5).float()
X_test = torch.randn(2000, 20, 4)
y_test = (torch.rand(2000) > 0.5).float()
Dataset
import torch
from torch.utils.data import TensorDataset
train_dataset = TensorDataset(X_train, y_train)
test_dataset = TensorDataset(X_test, y_test)
DataLoader
from torch.utils.data import DataLoader
BATCH_SIZE = 1024
train_loader = DataLoader(train_dataset, batch_size = BATCH_SIZE, shuffle = True)
test_loader = DataLoader(test_dataset, batch_size = BATCH_SIZE, shuffle = False)
Model
import torch.nn as nn
import torch.nn.functional as F
class Model(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(Model, self).__init__()
self.gru = nn.GRU(input_size=input_size, hidden_size=hidden_size,
num_layers=2, batch_first=True)
self.linear1 = nn.Linear(hidden_size, hidden_size)
self.linear2 = nn.Linear(hidden_size, output_size)
def forward(self, x):
x, _ = self.gru(x)
x = x[:, -1, :]
x = F.relu(self.linear1(x))
x = F.relu(self.linear2(x))
return x
x = torch.randn(10, 20, 4)
model = Model(input_size=4, hidden_size=32, output_size=1)
print(model(x))
Train
import torch
import torch.nn as nn
import torch.nn.functional as F
import tqdm
import time
import copy
from sklearn.metrics import confusion_matrix, classification_report
from sklearn.metrics import accuracy_score, roc_auc_score
class Trainer:
def __init__(self, net, train_loader, test_loader, criterion, optimizer,
epochs=100, lr = 0.001, l2=0, cutoff=0.5, device=None):
self.net = net
self.train_loader = train_loader
self.test_loader = test_loader
self.criterion = criterion
self.optimizer = optimizer(self.net.parameters(), lr=lr, weight_decay=l2)
self.epochs = epochs
self.lr = lr
self.cutoff = cutoff
if device is not None:
self.device = device
else:
self.device = 'cuda:0' if torch.cuda.is_available() else 'cpu'
self.train_auc = []
self.train_acc = []
self.val_auc = []
self.val_acc = []
self.best_model_wts = copy.deepcopy(self.net.state_dict())
self.best_acc = 0.
def fit(self):
since = time.time()
for epoch in range(self.epochs):
running_loss = 0.
self.net.train()
ys = []
y_preds = []
for i, (X_batch, y_batch) in enumerate(tqdm.tqdm(self.train_loader, total = len(self.train_loader))):
X_batch = X_batch.to(self.device, dtype=torch.float)
y_batch = y_batch.to(self.device, dtype=torch.float)
y_pred_batch = self.net(X_batch).reshape(-1,)
loss = self.criterion(y_pred_batch, y_batch)
self.optimizer.zero_grad()
loss.backward()
self.optimizer.step()
running_loss += loss.item()
y_pred_batch = (y_pred_batch > self.cutoff).float()
ys.append(y_batch)
y_preds.append(y_pred_batch)
ys = torch.cat(ys)
y_preds = torch.cat(y_preds)
train_acc_ = accuracy_score(ys.to('cpu'), y_preds.to('cpu'))
train_auc_ = roc_auc_score(ys.to('cpu'), y_preds.to('cpu'))
self.train_acc.append(train_acc_)
self.train_auc.append(train_auc_)
# 검증 데이터의 예측 정확도
val_acc_, val_auc_ = self.eval_net(self.test_loader, self.device)
self.val_acc.append(val_acc_)
self.val_auc.append(val_auc_)
# epoch 결과 표시
print('epoch: {}/{}, \ntrain_acc: {:.2f}%, test_acc: {:.2f}%, train_auc: {:.2f}%, test_auc: {:.2f}%'.format(epoch + 1, self.epochs,
self.train_acc[-1] * 100, self.val_acc[-1] * 100, self.train_auc[-1]*100, self.val_auc[-1]*100))
print('best acc : {:.2f}%'.format(self.best_acc * 100))
def eval_net(self, data_loader, device):
self.net.eval()
ys = []
y_preds = []
for X_batch, y_batch in data_loader:
X_batch = X_batch.to(device, dtype=torch.float)
y_batch = y_batch.to(device, dtype=torch.float)
with torch.no_grad():
y_pred_batch = self.net(X_batch).reshape(-1,)
y_pred_batch = (y_pred_batch > self.cutoff).float()
ys.append(y_batch)
y_preds.append(y_pred_batch)
ys = torch.cat(ys)
y_preds = torch.cat(y_preds)
acc = accuracy_score(ys.to('cpu'), y_preds.to('cpu'))
auc = roc_auc_score(ys.to('cpu'), y_preds.to('cpu'))
if acc.item() > self.best_acc:
self.best_acc = acc
self.best_model_wts = copy.deepcopy(self.net.state_dict())
return acc.item(), auc
from torch import optim
loss = nn.BCEWithLogitsLoss()
optimizer = optim.Adam
trainer = Trainer(model, train_loader, test_loader,
criterion=loss, optimizer=optimizer,
epochs=10, cutoff=0.5, lr=0.001)
trainer.fit()