Custom Dataset 기반의 CNN 학습 및 예측 문제 질문드립니다

안녕하세요. pytorch로 처음 딥러닝을 접하고 있는 학생입니다.

제가 생성한 Custom dataset과 CIFAR10의 학습에 이용된 일부 코드를 병합하는 과정에서 다음과 같은 문제가 발생하여 글을 남겨봅니다.

# ****** Import pytorch Library ******
import pandas as pd

import time
import torch
import numpy as np
import torch.nn as nn
import torch.nn.functional as F
import torchvision.models as models
import torch.utils.data as data_utils
from torchsummary import summary as summary
from torch.utils.data import Dataset, DataLoader

import matplotlib.pyplot as plt
%matplotlib inline

# Device configuration
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print('Our device configuration : {}'.format(device))
# Hyperparameters
BatchSize = 10 # 4
LearingRate = 0.001
# ****** Class MyDataLoader ******
class MyDataLoader(Dataset):
  def __init__(self, csv_path):
    df = pd.read_csv(csv_path, header=None, index_col=False)

    # input of dataset
    if (csv_path == '/content/drive/MyDrive/mydataset/H_train_32.csv'):
        self.input = df.iloc[:,:1024].values.reshape(350000,1,32,32)
        self.ans = df.iloc[:,1024:].values

    elif (csv_path == '/content/drive/MyDrive/mydataset/H_valid_32.csv'):
        self.input = df.iloc[:,:1024].values.reshape(100000,1,32,32)
        self.ans = df.iloc[:,1024:].values

    else:
        self.input = df.iloc[:,:1024].values.reshape(50000,1,32,32)
        self.ans = df.iloc[:,1024:].values

    # torch.FloatTensor -> torch.float32
    self.input = torch.tensor(self.input, dtype = torch.float32)

    # LongTensor -> torch.long or torch.int
    self.ans = torch.tensor(self.ans, dtype = torch.float32)

  def __len__(self):
    return len(self.input)

  def __getitem__(self, index):
    return self.input[index], self.ans[index]
# ****** train_loader ******
train_dataset = MyDataLoader(csv_path = '/content/drive/MyDrive/mydataset/H_train_32.csv')
train_loader = DataLoader(dataset = train_dataset, batch_size = BatchSize, drop_last = True, shuffle = True, num_workers = 2)

# ****** valid_loader ******
valid_dataset = MyDataLoader(csv_path = '/content/drive/MyDrive/mydataset/H_valid_32.csv')
valid_loader = DataLoader(dataset = valid_dataset, batch_size = BatchSize, shuffle = True, num_workers = 2)

# ****** test_loader ******
test_dataset = MyDataLoader(csv_path = '/content/drive/MyDrive/mydataset/H_test_32.csv')
test_loader = DataLoader(dataset = test_dataset, batch_size = BatchSize, shuffle = True, num_workers = 2)
# CIFAR10 CNN model
class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv1 = nn.Conv2d(1, 6, 5)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.conv2_drop = nn.Dropout2d() # 추가됨
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        # flatten all dimensions except batch
        x = torch.flatten(x, 1)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x

# net (simple torch style)
cnn = CNN()
print('*** CNN architecture *** \n')
print(cnn)

loss_func = nn.MSELoss() # mean squared error
optimizer = torch.optim.Adam(cnn.parameters(), lr=LearingRate)
# train loop
from tqdm import tqdm
cnn.train()
# loop over the dataset multiple times
for epoch in range(1):
    running_loss = 0.0
    for i, data in tqdm(enumerate(train_loader),total = len(train_loader)):
        # get the inputs; data is a list of [inputs, labels]
        inputs, labels = data

        # zero the parameter gradients
        optimizer.zero_grad()

        # forward + backward + optimize
        outputs = cnn(inputs)
        loss = loss_func(outputs, labels)
        loss.backward()
        optimizer.step()

        # print statistics
        running_loss += loss.item()

        # print every 100 mini-batches
        if i % 5000 == 4999:
            print(f'[{epoch + 1}, {i + 1:5d}] loss: {running_loss / 5000:.3f}')
            running_loss = 0.0

# ****** Save and load the model via state_dict ******
PATH = "mymodel.pt"

# Save
torch.save(cnn, PATH)

print('Finished model saving!')  
print('Finished Training!')
# test (real label vs predicted label)
dataiter = iter(test_loader)
inputs, labels = dataiter.next()

cnn = CNN() 
cnn = torch.load(PATH)

outputs = cnn(inputs)

_, predicted = torch.max(outputs.data, 1)

print("$$$$$$$$$$$$$$$$$$$$$$$$$$ fully labels $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$")
print(labels.int()[:], '\n')

print("$$$$$$$$$$$$$$$$$$$$$$$$$$ predicted $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$")
print(predicted.int()[:], '\n')

이때, 첨부드린 코드에서 가장 하단의 lables.int()[:], predicted.int()[:]의 값을 각각 출력하면 다음과 같은 결과를 반환합니다.
$$$$$$$$$$$$$$$$$$$$$$$$$$ labels $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
tensor([[ 2, 6, 8, 9, 13, 19, 22, 23, 28, 29],
[ 1, 4, 9, 11, 12, 19, 20, 21, 28, 30],
[ 4, 7, 15, 16, 18, 25, 26, 28, 31, 32],
[ 9, 11, 15, 16, 17, 20, 23, 24, 25, 32],
[ 3, 4, 5, 10, 14, 15, 17, 19, 25, 27],
[ 3, 5, 14, 18, 19, 20, 22, 24, 27, 29],
[ 6, 7, 13, 14, 21, 25, 26, 28, 30, 31],
[ 4, 7, 10, 14, 15, 16, 17, 23, 29, 32],
[ 6, 10, 14, 16, 17, 19, 23, 24, 25, 32],
[ 2, 9, 11, 12, 16, 19, 22, 24, 27, 30]], dtype=torch.int32)

$$$$$$$$$$$$$$$$$$$$$$$$$$ predicted $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
tensor([9, 9, 9, 9, 9, 9, 9, 9, 9, 9], dtype=torch.int32)

왜 이렇게 되는지 그리고 어떻게 처리하면 predicted 값을 labels와 동일한 형태로 출력할 수 있는지가 궁금합니다.

torch.max()함수 때문에 shape가 달라지는 것으로 예상이 되는데요.
혹시 Loss는 잘 떨어지나요?

좋아요 2

회신해주셔서 감사합니다. 데이터셋을 포함해서 전체적으로 문제가 있었습니다.

말씀해주신 loss 부분에서도 문제가 발생했으나, 현재는 해결된 상태입니다.

답장 남겨주셔서 감사합니다 :smile:

좋아요 1