AI/딥러닝

MLP(Multi-Layer Perceptron)과 CNN(Convolutional Neural Network) 정리

daeunnniii 2024. 3. 17. 16:08
728x90
반응형

MLP (Multi-Layer Perceptron)

  • MLP란 여러 개의 퍼셉트론 뉴런을 여러 층으로 쌓은 다층신경망 구조이다.
  • 입력층과 출력층 사이에 하나 이상의 은닉층을 가지고 있는 신경망이다.
  • 인접한 두 층의 뉴런 간에는 완전 연결(fully connected) 된다.

MLP 연산 과정 정리

 

이미지 데이터 처리 시 MLP의 문제점

 

  • MLP에서는 2차원 이상의 텐서를 1차원으로 flatten시켜 신경망 모델에 특성이 입력된다. 그림과 같이 이미지 데이터가 28 x 28 픽셀로 이루어져 있다면 이 특성들을 784개의 특성으로 1차원으로 줄인 후에 신경망 모델에 784개의 특성이 입력되는 것이다.

문제점

  • 가중치의 수가 이미지 픽셀만큼 생기므로 고해상도 이미지를 분석하는 경우, 최적의 가중치를 추정하지 못하거나 모델의 수렴 속도가 매우 느려질 수 있다.
  • 가중치의 수를 줄이면 정보의 병목 현상이 발생하여 가중치를 추정하기 어려워진다.
  • 가중치의 수를 지나치게 많이 사용하므로 과대적합(overfitting)의 문제가 발생할 수 있다.
  • 2차원 이상의 이미지 데이터(컬러는 3차원)를 1차원으로 flatten하면서 정보가 왜곡될 수도 있다.

CNN (Convolutional Neural Network) 

  • 이미지의 특정한 패턴의 특징이 어디서 나타나는지를 확인하는 도구인 필터를 학습시키는 것이다.
  • 예를 들어 위 사진과 같이 어떤 필터로 이미지를 보는지에 따라 이미지는 다르게 나타나게 된다. 이렇게 필터로 보는 이미지를 특징맵(feature map)이라고 한다.
  • CNN은 이미지를 가장 잘 분류할 수 있는 최적의 필터를 찾는 과정이다. 

CNN 연산 과정 필기 내용

 

  • 필터는 3차원 형태(channel, height, width)의 가중치의 모음이다. 필터 하나는 앞선 레이어의 결과인 특징맵 전체를 본다.
  • 필터의 개수 만큼 특징맵이 만들어진다.

Convolution Layer

  • 필터의 크기를 3으로 지정하면 3 x 3크기의 필터가 생성된다.
  • Stride는 이미지에 대해 필터를 적용할 때 필터의 이동량을 의미한다. 그림에서는 필터가 한 칸씩 옮겨가므로 stirde=1이다.
  • 아래 그림과 같은 연산을 하게 되면 5x5크기의 이미지가 4x4로 줄어들게 되고, 이미지의 가장자리에 위치한 픽셀들의 정보는 점점 사라지게 된다. 이러한 문제점을 해결하기 위해 이용되는 것이 패딩(padding)이다. 입력 이미지의 가장자리에 0으로 된 픽셀을 추가한다.

 

Pooling Layer

  • 이미지의 크기를 계속 유지한 채 Fully Connected Layer로 가게 된다면 연산량이 매우 많아질 것이다.
  • 따라서 이미지의 크기를 줄이고, 특정 feature를 강조하기 위해 Pooling Layer를 사용한다.
  • 처리 방법으로는 Max Pooling, Average Pooling, Min Pooling 세 가지가 있다. CNN에서는 가장 유의미한(픽셀의 강도가 높은) feature를 강조하기 위해 주로 Max Pooling이 사용된다.
  • 아래 그림은 filter size = 2, stride = 2인 Max Pooling 과정이다.
    • 채널의 수는 유지한 채 feature map의 크기(행, 열)만 줄임. 컨볼루션에서 식과 동일하게 사이즈가 줄어든다.

 

Fully Connected Layer

  • Convolution, Pooling Layer를 거친 후 마지막으로 나온 특징맵을 1열로 flatten시킨 후 MLP에서와 같은 연산을 하는 Layer이다.
  • flatten을 하게 되면 가중치의 개수가 많아지므로 보통 이 과정에서의 연산량이 제일 많다. 
  • 즉, fully connected layer에 들어가기 전 노드 수를 줄이기 위해 , 가중치의 수를 줄이기 위해 컨볼루션, 풀링 과정을 거친다고 보면 된다.

Pytorch로 CNN 구현하기

import torch
import torchvision
import torchvision.transforms as transforms
from torch.utils.data import DataLoader
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
 
# ToTensor -> 이미지 데이터를 텐서로 변환
# Normalize -> RGD 3개의 채널에 대한 픽셀을 각각 평균이 0.5, 표준편차가 0.5가 되도록 정규화
transform = transforms.Copmose(
    [transforms.ToTensor(),
     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
 
# 데이터 불러와서 배치 크기를 8로 설정
trainset = torchvision.datasets.CIFAR10(root='./data', train=True,
                                        download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=8, shuffle=True)
testset = torchvision.datasets.CIFAR10(root='./data', train=False,
                                       download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=8, shuffle=False)
 
# CNN 모델 정의
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()              # 입력 채널 수: RGB로 3개
        self.conv1 = nn.Conv2d(3, 6, 5)          # convolution (입력 채널수 3, 출력 채널수 6, 필터크기 5x5 , stride=1(defualt))
        self.pool1 = nn.MaxPool2d(2, 2)          # maxpooling (필터크기 2, stride=2)
        self.conv2 = nn.Conv2d(6, 16, 5)         # convolution (입력 채널수 6, 출력 채널수 16, 필터크기 5x5 , stride=1(defualt))
        self.pool2 = nn.MaxPool2d(2, 2)          # maxpooling (필터크기 2, stride=2)
        ### Fully Connected Layer 과정 ###
        self.fc1 = nn.Linear(16 * 5 * 5, 120)    # 5x5 피쳐맵 16개를 일렬로 피면 16*5*5개의 노드가 생성
        self.fc2 = nn.Linear(120, 10)            # 120개 노드에서 클래스의 개수인 10개의 노드로 연산
 
    # convolution -> ReLU -> Pooling 연산을 순서대로 진행.
    def forward(self, x):
        x = self.pool1(F.relu(self.conv1(x))) # conv1 -> ReLU -> pool1
        x = self.pool2(F.relu(self.conv2(x))) # conv2 -> ReLU -> pool2
        x = x.view(-1, 16 * 5 * 5)        # 5x5 피쳐맵 16개를 view()로 flatten 시킴.
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
 
        return x
 
# 비용함수와 옵티마이저 정의
criterion = nn.CrossEntropyLoss()                     # CrossEntropyLoss는 softmax 계산까지 포함되어 있으므로 모델의 마지막 output node에 별도의 활성화 함수를 사용하지 않아도 된다.
optimizer = optim.SGD(net.parameters(), lr=1e-3, momentum=0.9)
 
loss_ = []
n = len(trainloader) # 배치 개수
 
# 학습 진행
for epoch in range(10):
 
    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
 
        inputs, labels = data[0].to(device), data[1].to(device)
         
        optimizer.zero_grad()                   # optimizer 초기화
        # CPU인 경우
        # model = Net()
        # outputs = model.forward(inputs)
        outputs = net(inputs)                   # 예측값 산출 : 위에서 정의한 net class 사용
        loss = criterion(outputs, labels)       # 손실함수 계산
        loss.backward()                         # 역전파 과정 진행
        optimizer.step()                        # 가중치 업데이트
 
        # print statistics
        running_loss += loss.item()
 
    loss_.append(running_loss / n)
    print('[%d] loss: %.3f' %(epoch + 1, running_loss / len(trainloader)))
 
print('Finished Training')

 

 

 

728x90
반응형