본문 바로가기
ML & DL/Deep Learning

[DL] PyTorch로 인공신경망(ANN) 구현하기

by 홍월이_ 2023. 1. 11.

아래 내용들은 제가 혼자 학습하면서 정리한 내용들입니다.

'부족한 내용' 혹은 '잘못된 내용'이 있을 수 있습니다.

댓글 남겨주시면 더욱 공부하고 수정하도록 하겠습니다.

감사합니다.


간단한 분류 모델 구현 예제 : XOR 문제 풀이

PyTorch로 간단한 ANN을 구성하여 XOR 문제를 풀이하는 모델을 만들어보자!!

 

데이터셋 만들기

  • Scikit-Learn의 make_blobs 모듈을 사용해서 XOR 문제의 데이터들을 생성하기
  • Train 데이터는 80개, Test 데이터는 20개 생성
from sklearn.datasets import make_blobs

# Train : 80개
x_train, y_train = make_blobs(
    random_state = 100,
    n_samples = 80,                 # 생성할 데이터 수
    n_features = 2,                 # 특성 갯수(차원)
    centers = [[1, 1], [-1, -1], 
               [1, -1], [-1, 1]],   # 중심점
    shuffle = True, 
    cluster_std = 0.3               # 중심점으로부터의 표준편차
)

# Test : 20개
x_test, y_test = make_blobs(
    random_state = 100,
    n_samples = 20,
    n_features = 2,
    centers = [[1, 1], [-1, -1], 
               [1, -1], [-1, 1]],
    shuffle = True,
    cluster_std = 0.3
)

 

  • XOR 문제로 풀 것이기 때문에 4개의 Label을 2개로 합쳐주었다.
import numpy as np

# 이진분류 모델 만들기 : 4개의 레이블 -> 2개로 합치기
def label_map(y_, from_, to_):
    y = np.copy(y_)
    for f in from_:
        y[y_ == f] = to_
    return y
y_train = label_map(y_train, [0, 1], 0)
y_train = label_map(y_train, [2, 3], 1)

y_test = label_map(y_test, [0, 1], 0)
y_test = label_map(y_test, [2, 3], 1)

 

데이터셋 확인

import matplotlib.pyplot as plt

plt.title('Train data')
plt.scatter(x_train[:, 0], x_train[:, 1], marker='o', c=y_train, s=100,
            edgecolor='k', linewidth=2)
plt.xlabel('')
plt.ylabel('')
plt.show()

인공신경망 모델 설계

  • PyTorch는 TensorFlow와는 다르게 Class 형태로 모델을 설계한다. (Sequential 한 구현도 가능)
  • 모델을 설계할 때는 nn.Module을 상속받는다.
  • 이번 모델에서 활성화 함수는 ReLU와 Sigmoid를 사용
  • 만들어둔 데이터셋은 PyTorch에서 사용하기 위해 Tensor로 변환
import torch
from torch import nn, optim

x_train = torch.FloatTensor(x_train)
y_train = torch.FloatTensor(y_train)
x_test = torch.FloatTensor(x_test)
y_test = torch.FloatTensor(y_test)

 

기본 신경망 구조 설계

  • 입력층과 하나의 은닉층, 출력층으로 이루어져있는 인공신경망
  • input_size와 hidden_size 는 입력값과 은닉층에서의 출력값의 수로 설정. 매개변수로 받아온다.
  • Layer는 모두 Fully Connected된 Linear로 구성
  • 만들어진 데이터가 이진분류 문제이므로 마지막은 Simoid로 출력한다.
# 신경망 Class 정의
class NeuralNet(torch.nn.Module):
    # 생성자
    def __init__(self, input_size, hidden_size):
        super(NeuralNet, self).__init__()

        self.input_size = input_size
        self.hidden_size = hidden_size

        # 인공신경망 레이어 정의
        self.linear1 = nn.Linear(self.input_size, self.hidden_size)   # (입력 size, 출력 size)
        self.relu = nn.ReLU()                                         # Activation Function
        self.linear2 = nn.Linear(self.hidden_size, 1)                 # (앞 Layer의 출력값, Class수)
        self.sigmoid = nn.Sigmoid()                                   # Activation Function

    # 순전파
    def forward(self, input_tensor):
        h1 = self.linear1(input_tensor)
        h2 = self.relu(h1)
        h3 = self.linear2(h2)
        output = self.sigmoid(h3)

        return output

 

변수 설정

  • 모델링에 사용할 변수 설정
    • lr : 학습률
    • epochs : 반복 횟수
    • Loss Function은 Binary Cross Entropy
# 변수 설정
lr = 0.03
epochs = 2000
criterion = nn.BCELoss()  # Binary Cross Entropy

 

신경망 모델 생성

  • 모델 객체를 생성하고 optimizer를 생성해주었다.
  • optimizer 는 확률적 경사하강법(SGD)
# 신경망 객체 생성
model = NeuralNet(2, 5)
# optimizer 정의 : 확률적 경사하강법
# model.parameters() : 모델 내부의 가중치 추출
optimizer = optim.SGD(model.parameters(), lr = lr)

 

모델 학습하기

for epoch in range(epochs):
    model.train()
    optimizer.zero_grad()

    # 학습 데이터 입력, 결과값 개선
    train_output = model(x_train)

    # 오차 계산
    train_loss = criterion(train_output.squeeze(), y_train)

    if epoch % 100 == 0:
        print(f'train loss at {epoch} : {train_loss.item()}')

    # 오차 역전파
    train_loss.backward()
    optimizer.step() # 호출할 때마다 가중치를 학습률만큼 갱신
train loss at 0 : 0.027139227837324142
train loss at 100 : 0.026356041431427002
train loss at 200 : 0.025614794343709946
train loss at 300 : 0.024913163855671883
train loss at 400 : 0.024248961359262466
train loss at 500 : 0.023618832230567932
train loss at 600 : 0.02301996573805809
train loss at 700 : 0.02245008945465088
train loss at 800 : 0.02190718613564968
train loss at 900 : 0.021389367058873177
train loss at 1000 : 0.02089502103626728
train loss at 1100 : 0.020422592759132385
train loss at 1200 : 0.019970588386058807
train loss at 1300 : 0.019537832587957382
train loss at 1400 : 0.019123094156384468
train loss at 1500 : 0.018725339323282242
train loss at 1600 : 0.01834356226027012
train loss at 1700 : 0.01797674223780632
train loss at 1800 : 0.01762394607067108
train loss at 1900 : 0.017284326255321503

 

모델 성능 측정

model.eval() # 평가 모드 바꾸기
test_loss = criterion(torch.squeeze(model(x_test)), y_test)
print(f'학습 후 loss는 {test_loss.item()}')

>>> 학습 후 loss는 0.017321284860372543

 

모델 저장 및 불러오기

  • 마지막으로 만들어진 모델을 저장하고 불러와서 적용시키는 법을 알아보자

모델 저장

# model.state_dict() : 모델의 가중치 저장(딕셔너리)
torch.save(model.state_dict(), './model.pt')

 

모델 불러오기

# 학습된 모델의 가중치 적용
new_model = NeuralNet(2, 5)
new_model.load_state_dict(torch.load('./model.pt'))

>>> <All keys matched successfully>

 

새 모델로 성능 평가

new_model.eval()
test_data = torch.FloatTensor([-1, 1])
new_model(test_data ).item()

>>> 0.9995137453079224

 

 

Reference

 

GitHub - yellowjs0304/3-min-pytorch_study: 3분 딥러닝 파이토치맛 - 오픈소스 개인 스터디용

3분 딥러닝 파이토치맛 - 오픈소스 개인 스터디용. Contribute to yellowjs0304/3-min-pytorch_study development by creating an account on GitHub.

github.com

 

 

Module — PyTorch 1.13 documentation

Shortcuts

pytorch.org

 

... 끝!!

 

 

'ML & DL > Deep Learning' 카테고리의 다른 글

[DL] Keras fit vs fit_generator  (0) 2023.02.14
[DL] Tensoflow.Keras ImageDataGenerator  (0) 2023.02.14

댓글