월간 데이콘 소설 작가 분류 AI 경진대회

알고리즘 | NLP | 분류 | 자연어 | LogLoss

  • moneyIcon 상금 : 100만원+애플워치
  • 1,351명 마감

 

질문드립니다!! 에러 없이 잘 수행되는데 결과가 너무 안좋네요..

2020.12.02 14:47 5,419 조회

안녕하세요~ 딥러닝을 시작한지 얼마 안된 초보입니다.

pytorch로 코드를 짜봤는데, train, validation loss 는 좋지는 않지만 제 예상과 비슷한 값이 나옵니다...

그런데 test만 하면 loss가 1이 넘어버리네요...

혹시 제가 어떤 부분에서 실수를 해서 test시 제대로 안되는지 여쭤보고싶습니다.

답변 부탁드려요!!!! 여유가 있으신 분이시라면 혹시 어떤 방식으로 loss를 더 줄일 수 있는지 알려주시면 감사하겠습니다~!!



import re

from copy import deepcopy


import torch

import torch.nn as nn

import torch.nn.functional as F

import torch.optim as optim

from torchtext import data



batch_size = 32

embedded_size = 128

hidden_size = 150

n_classes = 5

EPOCHS = 7



TEXT = data.Field(sequential=True,

         use_vocab=True,

         tokenize=str.split, 

         lower=True,

         batch_first=True,

         fix_length=None)


LABEL = data.Field(sequential=False,

          use_vocab=False,

          is_target=True)


from torchtext.data import TabularDataset


train_data = TabularDataset(

  path = './data/train.nltk.csv',

  format = 'csv',

  fields = [('text', TEXT), ('label', LABEL)],

  skip_header = True)



test_data = TabularDataset(

  path = './data/test_x.nltk.1.csv',

  format = 'csv',

  fields = [('text', TEXT)],

  skip_header = True)


print(vars(train_data[0]))

TEXT.build_vocab(train_data, min_freq=7, max_size=20000, vectors = "fasttext.en.300d")

train_data, valid_data = train_data.split(split_ratio=0.8, stratified=True)


from torchtext.data import BucketIterator


train_loader, valid_loader = BucketIterator.splits(

  (train_data, valid_data),

  batch_size = batch_size,

  device='cuda:0',

  shuffle = True,

  sort_key=lambda x:len(x.text),

  sort_within_batch=True

)


test_loader = BucketIterator(

  test_data,

  batch_size = batch_size,

  device='cuda:0',

  shuffle = False,

  sort_key=lambda x:len(x.text),

  sort_within_batch=True

)



from tqdm import tqdm

model = LSTM(len(TEXT.vocab), embedded_size, hidden_size, n_classes).to('cuda:0')


crit = nn.NLLLoss().to('cuda:0')

optimizer = optim.Adam(model.parameters(), lr=0.001)

best_loss = 999999

best_model = None


for i in range(EPOCHS):

  train_loss = 0

  train_accuracy = 0

  model.train()

  for x, y in tqdm(train_loader):

    optimizer.zero_grad()

    x, y = x.to('cuda:0'), y.to('cuda:0')


    y_hat = model(x)

    loss = crit(y_hat, y)

    loss.backward()

    optimizer.step()

    if isinstance(y, torch.LongTensor) or isinstance(y, torch.cuda.LongTensor):

      accuracy = (torch.argmax(y_hat, dim=-1) == y).sum() / float(y.size(0))

    else:

      accuracy = 0

    train_loss += float(loss) / len(train_loader)

    train_accuracy += accuracy / len(train_loader)


  valid_loss = 0

  valid_accuracy = 0

  with torch.no_grad():

    model.eval()

    for x, y in valid_loader:

      x, y = x.to('cuda:0'), y.to('cuda:0')

      y_hat = model(x)

      loss = crit(y_hat, y)

       

      if isinstance(y, torch.LongTensor) or isinstance(y, torch.cuda.LongTensor):

        accuracy = (torch.argmax(y_hat, dim=-1) == y).sum() / float(y.size(0))

      else:

        accuracy = 0

      valid_loss += float(loss) / len(valid_loader)

      valid_accuracy += accuracy / len(valid_loader)

       

    if valid_loss < best_loss:

      best_loss = valid_loss

      best_model = deepcopy(model.state_dict())

       

       

  print("EPOCHS: {:2d} | train_accuracy: {:.4f} / train_loss: {:.4f} / valid_accuracy: {:.4f} / valid_loss: {:.4f} / best_loss: {:.4f}".format

       (i+1, train_accuracy, train_loss, valid_accuracy, valid_loss, best_loss))


test_model = LSTM(len(TEXT.vocab), embedded_size, hidden_size, n_classes).to('cuda:0')

test_model.load_state_dict(best_model)


test_model.eval()

y_hats = []

with torch.no_grad():

  for x_batch in test_loader:

    x = x_batch.text.to('cuda:0')

    y_hat = test_model(x).cpu()

    y_hats += y_hat

  y_hats = torch.stack(y_hats).exp()

test_pred = y_hats.numpy()


import pandas as pd

sub = pd.read_csv('./data/sample_submission.csv', index_col=0)


sub[sub.columns] = test_pred

sub.head()

sub.to_csv('./data/submission2.csv')

로그인이 필요합니다
0 / 1000
torque
2020.12.02 21:21

torch.save(model, PATH + 'model.pt') 사용해서 모델을 통으로 세이브/로드하는게 어떨까 싶습니다. 모델 웨이트가 업데이트가 안되는거 같네요. 

장민혁98
2020.12.03 11:52

답변 감사합니다~!! 
이것 저것 시도해보니까 문제를 해결했습니다!
제가 바보같이 test셋까지 shuffle해주어 결과가 다르게 나왔었네요ㅎㅎ  감사합니다~!