PyTorch를 사용하여 XOR 문제를 해결

2024. 11. 29. 10:21AI

반응형

XOR 문제는 비선형 문제로, 선형 계층만으로는 해결할 수 없다. 따라서, 이 모델은 신경망 계층과 비선형 활성화 함수(시그모이드)를 조합하여 XOR 문제를 해결한다.


코드 분석

1. 클래스 정의

class XORModel(nn.Module):
  • XORModel은 PyTorch의 nn.Module을 상속받아 정의된 사용자 정의 신경망 클래스이다.

2. 초기화 메서드 (__init__)

def __init__(self):
    super(XORModel, self).__init__()
    self.layer1 = nn.Linear(2, 2)  # 입력 노드 2개, 출력 노드 2개
    self.layer2 = nn.Linear(2, 1)  # 입력 노드 2개, 출력 노드 1개
    self.sigmoid = nn.Sigmoid()   # 시그모이드 활성화 함수
  • super(XORModel, self).__init__():
    • 부모 클래스(nn.Module)의 초기화를 호출하여 PyTorch의 모듈 기능을 활성화한다.
  • self.layer1:
    • 입력 차원이 2, 출력 차원이 2인 선형 계층 (fully connected layer).
    • 첫 번째 계층으로, XOR 문제의 입력 데이터(x1, x2)를 받아 처리한다.
  • self.layer2:
    • 두 번째 계층으로, layer1의 출력을 입력으로 받아 최종 결과(0 또는 1)를 출력한다.
  • self.sigmoid:
    • 시그모이드 활성화 함수는 출력값을 [0,1][0, 1] 범위로 정규화한다.
    • 비선형성을 도입하여 XOR 문제를 해결할 수 있게 한다.

3. 순전파 메서드 (forward)

def forward(self, x):
    x = self.sigmoid(self.layer1(x))  # 첫 번째 계층 + 시그모이드
    x = self.sigmoid(self.layer2(x))  # 두 번째 계층 + 시그모이드
    return x
  • self.layer1(x):
    • 입력 데이터(x)를 첫 번째 선형 계층(layer1)에 전달한다.
    • 출력은 선형 변환: y=Wx+by = Wx + b 형태이다.
  • self.sigmoid:
    • 첫 번째 계층의 출력을 비선형 시그모이드 함수에 통과시켜 활성화한다.
  • self.layer2(x):
    • 첫 번째 계층에서 활성화된 출력값을 두 번째 선형 계층에 전달한다.
    • 최종 출력값을 계산한다.
  • 반환값:
    • [0,1][0, 1] 범위의 값이 반환된다.
    • XOR 문제의 출력으로 사용된다.

 

import torch
import torch.nn as nn

class XORModel(nn.Module):
    def __init__(self):
        super(XORModel, self).__init__()
        self.layer1 = nn.Linear(2, 2)  # 입력 2개, 출력 2개
        self.layer2 = nn.Linear(2, 1)  # 입력 2개, 출력 1개
        self.sigmoid = nn.Sigmoid()    # 시그모이드 활성화 함수

    def forward(self, x):
        x = self.sigmoid(self.layer1(x))  # 첫 번째 계층 + 시그모이드
        x = self.sigmoid(self.layer2(x))  # 두 번째 계층 + 시그모이드
        return x

사용 예시

# 모델 생성
model = XORModel()

# XOR 문제의 입력 데이터
x = torch.tensor([[0.0, 0.0],
                  [0.0, 1.0],
                  [1.0, 0.0],
                  [1.0, 1.0]])

# 출력 예측
output = model(x)
print(output)

모델 구조

  • 입력 계층: 2개의 입력 노드.
  • 은닉 계층: 2개의 출력 노드를 가진 선형 계층 + 시그모이드 활성화 함수.
  • 출력 계층: 1개의 출력 노드를 가진 선형 계층 + 시그모이드 활성화 함수.
  • XOR 문제를 해결하기 위해 비선형 활성화 함수를 사용하여 학습 가능.

 

 

 

 

 XOR 문제를 해결하기 위해 정의된 모델을 학습시키는 과정

 

1. 에포크 반복

for epoch in range(10001):
  • XOR 문제의 학습을 10,001번 반복한다.
  • epoch: 현재 학습 단계(몇 번째 반복인지)를 나타낸다.

2. 순전파 (Forward pass)

outputs = model(x_data)
  • 입력 데이터 x_data를 모델에 전달하여 출력값 outputs를 계산한다.
  • 순전파 과정은 모델의 forward 메서드에 의해 정의된 연산을 수행한다.

3. 손실 계산

loss = criterion(outputs, y_data)
  • criterion: 손실 함수로, 예측값(outputs)과 실제값(y_data)의 차이를 계산한다.
  • XOR 문제에서는 보통 이진 교차 엔트로피 손실(nn.BCELoss)을 사용한다.
  • 손실 값은 학습 과정에서 모델이 얼마나 잘못 예측했는지를 나타낸다.

4. 역전파 (Backward pass) 및 최적화

optimizer.zero_grad()
loss.backward()
optimizer.step()
  • optimizer.zero_grad(): 이전 에포크에서 계산된 그래디언트를 초기화한다. 그래디언트는 매번 누적되기 때문에 초기화가 필요하다.
  • loss.backward(): 현재 에포크에서 계산된 손실값을 기준으로 그래디언트를 계산한다.
  • optimizer.step(): 그래디언트를 사용하여 모델의 가중치와 편향을 업데이트한다. 이 과정이 학습이다.

5. 중간 출력

if epoch % 1000 == 0:
    print(f'Epoch [{epoch}/10000], Loss: {loss.item():.4f}')
  • 매 1,000 에포크마다 현재 에포크 번호와 손실값을 출력한다.
  • loss.item(): 텐서 형태의 손실 값을 숫자로 변환하여 출력한다.

 

import torch
import torch.nn as nn
import torch.optim as optim

# XOR 데이터셋
x_data = torch.tensor([[0.0, 0.0],
                       [0.0, 1.0],
                       [1.0, 0.0],
                       [1.0, 1.0]])
y_data = torch.tensor([[0.0],
                       [1.0],
                       [1.0],
                       [0.0]])

# 모델 정의 (XORModel은 이전에 정의한 클래스 사용)
class XORModel(nn.Module):
    def __init__(self):
        super(XORModel, self).__init__()
        self.layer1 = nn.Linear(2, 2)
        self.layer2 = nn.Linear(2, 1)
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        x = self.sigmoid(self.layer1(x))
        x = self.sigmoid(self.layer2(x))
        return x

model = XORModel()

# 손실 함수와 옵티마이저 정의
criterion = nn.BCELoss()  # Binary Cross Entropy Loss
optimizer = optim.SGD(model.parameters(), lr=0.1)  # Stochastic Gradient Descent

# 학습 루프
for epoch in range(10001):
    # 순전파
    outputs = model(x_data)
    loss = criterion(outputs, y_data)

    # 역전파 및 최적화
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    # 중간 결과 출력
    if epoch % 1000 == 0:
        print(f'Epoch [{epoch}/10000], Loss: {loss.item():.4f}')

# 학습 결과 확인
print("\nTraining complete!")
with torch.no_grad():
    for x, y in zip(x_data, y_data):
        prediction = model(x).item()
        print(f"Input: {x.tolist()}, Predicted: {prediction:.4f}, Actual: {y.item():.4f}")

 

  1. 데이터 정의:
    • x_data: XOR 문제의 입력 데이터.
    • y_data: XOR 문제의 출력 라벨.
  2. 모델 및 손실 함수:
    • XORModel은 이전에 정의한 모델.
    • criterion: 이진 교차 엔트로피 손실을 사용하여 출력값과 실제값의 차이를 계산.
  3. 학습 과정:
    • 10,001번 학습하며 손실을 줄이는 방향으로 모델 가중치를 업데이트.
  4. 학습 결과:
    • 학습이 끝나면 각 입력 데이터에 대해 예측값과 실제값을 비교하여 출력.

학습 결과 예시 출력

Epoch [0/10000], Loss: 0.6931
Epoch [1000/10000], Loss: 0.5023
Epoch [2000/10000], Loss: 0.2789
...
Epoch [10000/10000], Loss: 0.0176

Training complete!
Input: [0.0, 0.0], Predicted: 0.0251, Actual: 0.0000
Input: [0.0, 1.0], Predicted: 0.9736, Actual: 1.0000
Input: [1.0, 0.0], Predicted: 0.9738, Actual: 1.0000
Input: [1.0, 1.0], Predicted: 0.0273, Actual: 0.0000

 

 
 

 

 

반응형