XOR Problem

퍼셉트론은 초기 인공 신경망 모델 중 하나로, 입력값을 받아 가중치와 활성화 함수를 통해 출력을 계산하는 구조를 갖느다. 하지만 퍼셉트론은 선형적으로 분리 가능한 문제만 해결할 수 있으며, XOR 문제와 같은 비선형 문제를 해결할 수 없는 한계가 있다.

XOR 문제는 두 개의 이진 입력(0 또는 1)을 받아 하나의 이진 출력을 생성하는 문제이다. XOR 연산의 출력은 입력 중 하나만이 1일 때 1이 되며, 두 입력이 동시에 0이거나 동시에 1일 때는 0이 된다.

퍼셉트론은 선형 분리가 가능한 문제를 해결할 수 있으므로, AND나 OR 같은 문제는 잘 처리할 수 있다. 예를 들어, AND 연산은 두 입력이 모두 1일 때 1을 출력하며, OR 연산은 두 입력 중 하나 이상이 1일 때 1을 출력한다. 이런 연산은 직선으로 분리가 가능한 문제이다.

하지만 XOR 문제는 입력값들을 직선 하나로는 분리할 수 없는 비선형 문제이다. 따라서 퍼셉트론 하나로는 XOR 문제를 해결할 수 없다.

XOR 문제를 해결하려면 퍼셉트론을 여러 개 조합하여 비선형 구조를 만들어야 한다. Multi-layer Perceptron (MLP)과 같이 여러 층의 퍼셉트론을 조합한 구조로는 XOR 문제를 해결할 수 있다.

image

Single-layer Perceptron

우선 단층 레이어로 학습시켜 XOR를 풀 수 없다는 것을 확인해보자.

import torch
import torch.nn as nn

device = 'cuda' if torch.cuda.is_available() else 'cpu'

X = torch.FloatTensor([[0, 0],
                      [0, 1],
                      [1, 0],
                      [1, 1]]).to(device)

y = torch.FloatTensor([[0],
                       [1],
                       [1],
                       [0]]).to(device)

linear = nn.Linear(2, 1, bias=True) # input 2개, output 1개
sigmoid = nn.Sigmoid()
model = nn.Sequential(linear, sigmoid)

criterion = torch.nn.BCELoss().to(device) # binary cross entropy 손실함수
optimizer = torch.optim.SGD(model.parameters(), lr=0.1)

for epoch in range(10000):
    y_pred = model(X)
    loss = criterion(y_pred, y)

    loss.backward()
    optimizer.step()
    optimizer.zero_grad()

# prediction
with torch.no_grad():
    y_hat = (y_pred > 0.5).float()
    accuracy = (y_hat == y).float().mean()
    print(accuracy.item())
0.5

정확도가 0.5로 제대로 학습이 되지 않는것을 볼 수 있다. 실제 값과 예측 값을 한 번 확인해보자

y_hat.detach()
tensor([[0.],
        [0.],
        [0.],
        [0.]])
y.detach()
tensor([[0.],
        [1.],
        [1.],
        [0.]])

제대로 예측하지 못 한 것을 눈으로 확인할 수 있다.

Multi-layer Perceptron

그렇다면 이제 코드를 조금 변경해 Multi-layer Perceptron을 만들어보자.

# nn.Sequential을 사용하여 모델을 정의한다.
model = nn.Sequential(
    # 첫 번째 레이어: 입력 크기가 2이고 출력 크기가 4인 선형 변환 레이어
    nn.Linear(2, 4, bias=True),
    # 활성화 함수: Sigmoid 함수
    nn.Sigmoid(),
    # 두 번째 레이어: 입력 크기가 4이고 출력 크기가 1인 선형 변환 레이어
    nn.Linear(4, 1, bias=True), 
    # 활성화 함수: Sigmoid 함수
    nn.Sigmoid()
).to(device)

모델 부분에 레이어 층을 하나 추가해주고, 나머지 코드는 동일하다.

# prediction
with torch.no_grad():
    y_hat = (y_pred > 0.5).float()
    accuracy = (y_hat == y).float().mean()
    print(accuracy.item())
1.0

accuracy가 1.0이 나온것을 보아 제대로 예측한 것을 알 수 있다. 실제로 값이 같은지 한 번 확인해보자.

y_hat.detach()
tensor([[0.],
        [1.],
        [1.],
        [0.]])
y.detach()
tensor([[0.],
        [1.],
        [1.],
        [0.]])

정확히 값이 같은것을 볼 수 있다. 이처럼 단층 레이어가 아닌 멀티 레이어 구조를 사용하면 XOR Problem을 해결할 수 있다.

댓글남기기