밑바닥부터 시작하는 딥러닝
딥러닝 분야 부동의 베스트셀러!머리로 이해하고 손으로 익히는 가장 쉬운 딥러닝 입문서 이 책은 딥러닝의 핵심 개념을 ‘밑바닥부터’ 구현해보며 기초를 한 걸음씩 탄탄하게 다질 수 있도
www.google.com
1. 서론
XOR 문제는 신경망 연구에서 중요한 전환점이 된 사례 중 하나다. 단층 퍼셉트론이 선형적으로 분리할 수 없는 문제를 해결하지 못한다는 한계를 보였고, 이를 극복하기 위해 다층 퍼셉트론(MLP, Multi-Layer Perceptron)이 필요하다는 사실이 밝혀졌다. 이번 글에서는 다층 퍼셉트론이 XOR 문제를 어떻게 해결하는지 살펴보겠다.
2. XOR 문제와 단층 퍼셉트론의 한계
XOR 문제란?
XOR(Exclusive OR)은 두 개의 이진 입력값이 서로 다를 때 출력이 1, 같을 때 출력이 0이 되는 논리 연산이다.
입력(x1, x2) 출력(y)
(0, 0) | 0 |
(0, 1) | 1 |
(1, 0) | 1 |
(1, 1) | 0 |
XOR 문제를 시각적으로 보면, 데이터를 선형 분리할 수 없는 형태로 분포되어 있다. 즉, 하나의 직선(선형 결정 경계)으로 0과 1을 나눌 수 없다는 것이 문제다.
단층 퍼셉트론의 한계
단층 퍼셉트론은 입력값에 대해 가중치를 적용한 후 활성화 함수를 거쳐 출력을 내보낸다. 하지만 이 방식은 데이터가 선형적으로 분리 가능해야만 학습할 수 있다. AND나 OR 게이트는 단일 직선으로 분리할 수 있어 단층 퍼셉트론으로 해결할 수 있지만, XOR 게이트는 이를 만족하지 않기 때문에 단층 퍼셉트론만으로는 해결할 수 없다.
3. 다층 퍼셉트론(MLP)의 구조
은닉층의 필요성
XOR 문제를 해결하려면, 데이터를 선형적으로 분리할 수 있도록 특징 공간을 변형해야 한다. 이 과정에서 은닉층(hidden layer)이 중요한 역할을 한다. 은닉층이 존재하면 입력 데이터를 비선형적으로 변형할 수 있어, 선형적으로 분리되지 않는 문제도 해결할 수 있다.
활성화 함수
은닉층을 추가한 뒤, 단순한 선형 변환만 수행하면 다시 선형 모델과 다를 바가 없다. 따라서 활성화 함수(Activation Function)를 사용하여 비선형성을 추가해야 한다. 대표적인 활성화 함수로는 다음과 같은 것들이 있다.
- Sigmoid: 값을 (0,1) 범위로 변환하여 확률적인 해석이 가능하지만, 기울기 소실 문제(Vanishing Gradient Problem)가 발생할 수 있다.
- Tanh: (-1,1) 범위로 변환하며 Sigmoid보다 강한 비선형성을 가지지만, 여전히 기울기 소실 문제가 있다.
- ReLU (Rectified Linear Unit): 0 이하의 입력에서는 0을, 0보다 큰 입력에서는 그대로 출력하는 함수로, 기울기 소실 문제를 완화하며 현재 가장 널리 사용된다.
4. XOR 문제 해결을 위한 다층 퍼셉트론 구성
MLP 구조
XOR 문제를 해결하기 위해 최소한 하나의 은닉층을 추가해야 한다. 대표적인 구성은 다음과 같다.
- 입력층: 두 개의 입력 뉴런(x1, x2)
- 은닉층: 두 개의 뉴런 (h1, h2)과 활성화 함수 적용
- 출력층: 하나의 뉴런(y)과 활성화 함수 적용
각 층의 작동 원리
- 입력층: data = torch.tensor([[0, 0], [0, 1], [1, 0], [1, 1]], dtype=torch.float32)
- XOR 문제의 입력 데이터를 받는다.
- 은닉층: self.hidden = nn.Linear(2, 2)
- 두 개의 입력을 받아 두 개의 뉴런을 통해 변환.
- forward 함수에서 self.activation(self.hidden(x))를 통해 활성화 함수 적용.
- 출력층: self.output = nn.Linear(2, 1)
- 은닉층의 출력을 받아 최종적인 XOR 출력을 생성.
- forward 함수에서 self.activation(self.output(x))를 통해 활성화 함수 적용.
이 과정이 반복되면서 모델이 XOR 문제를 학습하게 된다.
5. OR, NAND, AND 게이트를 이용한 다층 퍼셉트론
XOR 게이트는 OR, NAND, AND 게이트의 조합으로도 구현할 수 있다. 이를 다층 퍼셉트론으로 구성하면 다음과 같다.
- 1단계 (은닉층): 입력값을 사용하여 NAND와 OR 게이트의 출력을 구함
- 2단계 (출력층): NAND와 OR의 출력을 입력값으로 하여 AND 게이트를 수행
구현 코드
import numpy as np
def step_function(x):
return np.where(x > 0, 1, 0)
def perceptron(x, w, b):
return step_function(np.dot(x, w.T) + b)
# NAND 게이트
w_nand = np.array([[-1, -1]])
b_nand = np.array([1.5])
# OR 게이트
w_or = np.array([[1, 1]])
b_or = np.array([-0.5])
# AND 게이트
w_and = np.array([[1, 1]])
b_and = np.array([-1.5])
def xor_gate(x):
nand_out = perceptron(x, w_nand, b_nand)
or_out = perceptron(x, w_or, b_or)
return perceptron(np.hstack((nand_out, or_out)), w_and, b_and)
# XOR 입력값 테스트
x_data = np.array([[0,0], [0,1], [1,0], [1,1]])
for x in x_data:
print(f'입력: {x}, 출력: {xor_gate(x)}')
이 모델에서는 OR, NAND, AND를 사용하여 XOR 연산을 수행할 수 있도록 다층 퍼셉트론을 구성하였다. 이는 XOR 문제를 해결하는 또 다른 방법을 보여준다.
6. 퀴즈
퀴즈 1:
단층 퍼셉트론(Single-Layer Perceptron)이 XOR 문제를 해결하지 못하는 이유는 무엇인가?
- 단층 퍼셉트론은 가중치를 조정할 수 없기 때문이다.
- XOR 문제는 선형적으로 분리되지 않기 때문이다.
- 단층 퍼셉트론은 활성화 함수를 사용할 수 없기 때문이다.
- XOR 문제는 학습이 불가능한 문제이기 때문이다.
퀴즈 2:
다음 입력값 (1, 1)을 XOR 게이트에 넣었을 때 나오는 출력값은 무엇인가?
- 0
- 1
- 입력값과 동일한 값
- 랜덤한 값