슬.공.생

BoostCourse(DL)(week4)- CNN with Custom_Dataset 본문

study/DeepLearning

BoostCourse(DL)(week4)- CNN with Custom_Dataset

AGT (goh9510@naver.com) 2022. 8. 17. 17:11

합성곱 신경망 (CNN)의 Custom_Dataset 입력


이전 과정에서는 기존에 존재하는 dataset(MNIST)를 받아 쓰는 형식으로 학습과정에 적용하곤 하였다.

따라서 직접 data를 수집하여 dataset을 불러오는 과정을 진행해본다.

 

아래와 같이 image를 다루는데 기본적인 요소와 시각화 하는데 기본적인 요소들을 가져온다.

import torchvision
from torchvision import transforms

from torch.utils.data import DataLoader
from matplotlib.pyplot import imshow

 

 

data는 다음과 같은 grey, red 색상의 의자 image들이다.

아래 사진의 크기나 형태정보는 다음과 같다.

<PIL.Image.Image image mode=RGB size=512x256 at 0x2540DB75F10> 1

  • 3채널의 RGB
  • 512x256 크기
  • grey(0), red(1) 의 라벨

 

위의 이미지들은 512x256 크기를 가지고 있어 연산에 있어서는 상당히 크기가 큰 상태로 torchvision의 transform을 통해 이미지의 크기를 조절해준다.

 

trans = transforms.Compose([ 
    transforms.Resize((64, 128))
    ])

train_data = torchvision.datasets.ImageFolder('origin_data/',
                                              transform=trans) 
'''
IMAGEFLODER를 활용하여 data 가져옴  ##transform=None
예시 ) 550 <PIL.Image.Image image mode=RGB size=512x256 at 0x2540DBDE850> 1  

transform=trans 과정을 거쳐 data 가져옴
예시 ) 550 <PIL.Image.Image image mode=RGB size=128x64 at 0x2540DBDEAC0> 1
image size를 transforms을 이용해 축소함
'''

위의 과정으로 (512x256) ==> (64x128) 의 크기로 image를 조절할 수 있다.

 

 


 

 

 

크기를 조절한 이미지를 학습 data로 활용하기 위해 새롭게 저장하는 과정을 거치게 된다.

for num, value in enumerate(train_data):
    
    data, label = value
    print(num, data, label)
    
    if (label == 0):
        data.save('train_data/grey/%d_%d.jpeg'%(num, label))            
    else :
        data.save('train_data/red/%d_%d.jpeg'%(num, label))

 

 


 

 

합성곱 신경망 (CNN) 구성


이후 준비된 dataset을 이용해 학습을 진행시키며 아래와 같은 CNN model를 구성하여 학습을 진행하게 된다.

 

 

 

class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        
        self.fc1 = nn.Linear(6032, 120)
        self.fc2 = nn.Linear(120, 2)
       
        ##torch.nn.init.xavier_uniform_(self.fc1.weight)
        ##torch.nn.init.xavier_uniform_(self.fc2.weight)
       
        self.layer1 = nn.Sequential(
            nn.Conv2d(3, 6, kernel_size = 5, stride = 1),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size = 2, stride = 2)
            
            )
        self.layer2 = nn.Sequential(
            nn.Conv2d(6, 16, kernel_size = 5, stride = 1),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size = 2, stride = 2)
            
            )
        self.layer3 = nn.Sequential(
            self.fc1, 
            nn.ReLU(), 
            self.fc2)
        
        
    def forward(self, x):
        #print(x.shape)
        out = self.layer1(x)
        #print(out.shape)
        out = self.layer2(out)
        #print(out.shape)
        out = out.view(out.shape[0], -1)
        #print(out.shape)
        out = self.layer3(out)
        #print(out.shape)
        return out

'''
torch.Size([3, 3, 64, 128]) 64x128 이미지 RGB 3채널
torch.Size([3, 6, 30, 62])
torch.Size([3, 16, 13, 29])
torch.Size([3, 6032])
torch.Size([3, 2])
'''

 

 


 

 

 

이후 학습과정을 거치게 된다.

cnn = CNN().to(device)
'''
test_input = (torch.Tensor(3,3,64,128)).to(device)
test_out = cnn(test_input)
'''
optimizer = optim.Adam(cnn.parameters(), lr=0.00005)
loss_func = nn.CrossEntropyLoss().to(device)
total_batch = len(data_loader)

cnn.train()
epochs = 10
for epoch in range(epochs):
    avg_cost = 0.0
    for num, data in enumerate(data_loader):
        imgs, labels = data
        imgs = imgs.to(device)
        labels = labels.to(device)
        optimizer.zero_grad()
        out = cnn(imgs)
        loss = loss_func(out, labels)
        loss.backward()
        optimizer.step()
        
        avg_cost += loss / total_batch
        
    print('[Epoch:{}] cost = {}'.format(epoch+1, avg_cost))
print('Learning Finished!')
#[Epoch:1] cost = 0.6717714071273804
#[Epoch:2] cost = 0.5067784786224365
#[Epoch:3] cost = 0.24532923102378845
#[Epoch:4] cost = 0.06239330768585205
#[Epoch:5] cost = 0.019717982038855553
#[Epoch:6] cost = 0.009683300741016865
#[Epoch:7] cost = 0.00574050797149539
#[Epoch:8] cost = 0.003747222013771534
#[Epoch:9] cost = 0.0024205707013607025
#[Epoch:10] cost = 0.0018726482521742582
#Learning Finished!

 


 

합성곱 신경망 (CNN) 결과 출력(visdom)

import visdom
vis = visdom.Visdom()

vis.text("Hello, world!", env = "main")

이전에 visdom을 이용하여 학습결과를 그래프로 출력한 경우가 있다.

 

BoostCourse(DL)(week4)- MNIST and Convolutional Neural Network

합성곱 신경망 (CNN)의 사용 배경과 목적 일반적으로 다수의 층을 쌓아 신경망 구조를 구성하게 되는데 이때 해당 신경망으로 입력되는 정보는 다음과 같다. Y 라는 손글씨(행렬 텐서)를 아래와

wisepubliclife.tistory.com

이를 통해 위의 과정을 출력해보기 위해 아래와 같은 코드를 구성한다.

import visdom
vis = visdom.Visdom()

vis.text("Hello, world!", env = "main")

 visdom을 import 한뒤 main환경에서 "Hello, world"라는 구문을 출력하게된다.

 


 

loss를 계속 출력 할수 있는 함수를 선언하고

실시간 loss와 batch별 평균 loss를 출력할 그래프를 하나씩 선언한다.

def loss_tracker(loss_plot, loss_value, num):
    '''num, loss_value, are Tensor'''
    vis.line(X=num,
             Y=loss_value,
             win = loss_plot,
             update='append'
             )
    
plt1 = vis.line(Y=torch.Tensor(1).zero_())
plt2 = vis.line(Y=torch.Tensor(1).zero_())

이후 학습을 진행하는 반복문 내에서 다음과 같이 visdom으로 index값과 출력값을 전송하여 아래와 같은 그래프를 그리도록 한다.

cnn.train()
epochs = 10
cnt1 = 0
cnt2 = 1
for epoch in range(epochs):
    avg_cost = 0.0
    
    for num, data in enumerate(data_loader):
        imgs, labels = data
        imgs = imgs.to(device)
        labels = labels.to(device)
        optimizer.zero_grad()
        out = cnn(imgs)
        loss = loss_func(out, labels)
        loss.backward()
        optimizer.step()
        cnt2 = cnt2 + 1
        avg_cost += loss / total_batch
        loss_tracker(plt1, torch.Tensor([loss]), torch.Tensor([cnt2]))
        
   
    print('[Epoch:{}] cost = {}'.format(epoch+1, avg_cost))
    loss_tracker(plt2, torch.Tensor([avg_cost]), torch.Tensor([epoch]))
print('Learning Finished!')

 

Comments