AI/딥러닝

[딥러닝] 퍼셉트론(Perceptron)

caramel-bottle 2024. 1. 10.

인간의 뇌는 수십억 개의 뉴런을 가지고 있습니다.

 

뉴런이란 화학적, 전기적 신호를 처리하고 전달하는 연결된 뇌신경 세포입니다.

 

인공 신경망(Artificial Neural Network)은 생물학적 뉴런을 기반으로 한 수학적 모델입니다.

 

이번 포스팅에선 초기 인공 신경망인 퍼셉트론(Perceptron)에 대해 이야기해보겠습니다.

1. 퍼셉트론(Perceptron)

초기 인공 신경망인 퍼셉트론(Perceptron)은 다수의 입력으로부터 하나의 결과를 내보내는 알고리즘입니다.

 

초기 기계 학습 알고리즘 중 하나로 이진 분류 문제를 해결하기 위해 설계되었습니다.

 

논리 회귀 분류를 통해 단층 퍼셉트론과 다층 퍼셉트론에 대해 알아보도록 하겠습니다.


2. 논리 회귀(단층 퍼셉트론)로 AND문제 풀기

2-1. AND

AND 게이트란 두 개의 입력이 모두 1인 경우에만 출력이 1인 논리 게이트입니다.

2-2. 코드

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

x = [[0, 0], [0, 1], [1, 0], [1, 1]]
y = [[0], [0], [0], [1]]

x_train = torch.FloatTensor(x)
y_train = torch.FloatTensor(y)

model = nn.Sequential(
    nn.Linear(2, 1),
    nn.Sigmoid()
)

optimizer = optim.SGD(model.parameters(), lr=1)
epochs = 1000

for epoch in range(epochs + 1):
    y_pred = model(x_train)
    loss = nn.BCELoss()(y_pred, y_train)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    if epoch % 100 == 0:
        y_bool = ((y_pred >= 0.5) == y_train).float().sum() / len(y_pred) * 100

        print(f'Epoch {epoch:4d}/{epochs} Loss: {loss:.6f} Accuracy: {y_bool:.2f}%')

output>>

Epoch    0/1000 Loss: 0.665210 Accuracy: 75.00%
Epoch  100/1000 Loss: 0.143335 Accuracy: 100.00%
Epoch  200/1000 Loss: 0.081506 Accuracy: 100.00%
Epoch  300/1000 Loss: 0.056452 Accuracy: 100.00%
Epoch  400/1000 Loss: 0.042996 Accuracy: 100.00%
Epoch  500/1000 Loss: 0.034642 Accuracy: 100.00%
Epoch  600/1000 Loss: 0.028969 Accuracy: 100.00%
Epoch  700/1000 Loss: 0.024873 Accuracy: 100.00%
Epoch  800/1000 Loss: 0.021780 Accuracy: 100.00%
Epoch  900/1000 Loss: 0.019364 Accuracy: 100.00%
Epoch 1000/1000 Loss: 0.017426 Accuracy: 100.00%

 

로지스틱 회귀 모델은 2개의 입력과 1개의 출력을 갖는 선형 모델에 Sigmoid 활성화함수를 나열한 모델입니다.

model = nn.Sequential(
    nn.Linear(2, 1),
    nn.Sigmoid()
)

 

최적화 함수는 SGD(Stochastic Gradient Descent)를 사용하였습니다.

optimizer = optim.SGD(model.parameters(), lr=1)

 

손실함수(비용함수)는 이진 분류에 사용하는 크로스엔트로피 함수인 BCELoss()를 사용하였습니다.

loss = nn.BCELoss()(y_pred, y_train)

 

2-3. 결과

 

직선 하나로 4개의 입력을 2개로 분류가 가능합니다.

 

어떻게 학습을 했건 100%의 정확도를 가질 수 있는 경우인 것이지요.


3. 논리 회귀(단층 퍼셉트론)로 or 문제 풀기

3-1. OR

OR 게이트는 두 입력 모두 0인 경우를 제외한 모든 출력이 1인 논리 게이트입니다.

 

3-2. 코드

x = [[0, 0], [0, 1], [1, 0], [1, 1]]
y = [[0], [1], [1], [1]]

x_train = torch.FloatTensor(x)
y_train = torch.FloatTensor(y)

model = nn.Sequential(
    nn.Linear(2, 1),
    nn.Sigmoid()
)

optimizer = optim.SGD(model.parameters(), lr=1)

epochs = 1000

for epoch in range(epochs + 1):
    y_pred = model(x_train)
    loss = nn.BCELoss()(y_pred, y_train)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    if epoch % 100 == 0:
        y_bool = ((y_pred >= 0.5) == y_train).float().sum() / len(y_pred) * 100

        print(f'Epoch {epoch:4d}/{epochs} Loss: {loss:.6f} Accuracy: {y_bool:.2f}%')

output>>

Epoch    0/1000 Loss: 0.993666 Accuracy: 25.00%
Epoch  100/1000 Loss: 0.087962 Accuracy: 100.00%
Epoch  200/1000 Loss: 0.046496 Accuracy: 100.00%
Epoch  300/1000 Loss: 0.031249 Accuracy: 100.00%
Epoch  400/1000 Loss: 0.023439 Accuracy: 100.00%
Epoch  500/1000 Loss: 0.018719 Accuracy: 100.00%
Epoch  600/1000 Loss: 0.015566 Accuracy: 100.00%
Epoch  700/1000 Loss: 0.013314 Accuracy: 100.00%
Epoch  800/1000 Loss: 0.011627 Accuracy: 100.00%
Epoch  900/1000 Loss: 0.010316 Accuracy: 100.00%
Epoch 1000/1000 Loss: 0.009270 Accuracy: 100.00%

 

3-3. 결과

AND와 마찬가지로 이진 분류를 직선 하나로 할 수 있습니다.

 

역시나 100%로 분류를 할 수 있는 경우입니다.


4. 논리 회귀(단층 퍼셉트론)로 XOR 문제 풀기

4-1. XOR

XOR는 두 입력이 같으면 0 다르면 1을 출력하는 논리 게이트입니다.

4-2. 코드

x = [[0, 0], [0, 1], [1, 0], [1, 1]]
y = [[0], [1], [1], [0]]

x_train = torch.FloatTensor(x)
y_train = torch.FloatTensor(y)

model = nn.Sequential(
    nn.Linear(2, 1),
    nn.Sigmoid()
)

optimizer = optim.SGD(model.parameters(), lr=1)
epochs = 1000

for epoch in range(epochs + 1):
    y_pred = model(x_train)
    loss = nn.BCELoss()(y_pred, y_train)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    if epoch % 100 == 0:
        y_bool = ((y_pred >= 0.5) == y_train).float().sum() / len(y_pred) * 100

        print(f'Epoch {epoch:4d}/{epochs} Loss: {loss:.6f} Accuracy: {y_bool:.2f}%')

output>>

Epoch    0/1000 Loss: 0.813640 Accuracy: 50.00%
Epoch  100/1000 Loss: 0.693147 Accuracy: 75.00%
Epoch  200/1000 Loss: 0.693147 Accuracy: 75.00%
Epoch  300/1000 Loss: 0.693147 Accuracy: 75.00%
Epoch  400/1000 Loss: 0.693147 Accuracy: 50.00%
Epoch  500/1000 Loss: 0.693147 Accuracy: 50.00%
Epoch  600/1000 Loss: 0.693147 Accuracy: 50.00%
Epoch  700/1000 Loss: 0.693147 Accuracy: 50.00%
Epoch  800/1000 Loss: 0.693147 Accuracy: 50.00%
Epoch  900/1000 Loss: 0.693147 Accuracy: 50.00%
Epoch 1000/1000 Loss: 0.693147 Accuracy: 50.00%

 

4-3. 결과

AND, OR와 다르게 50%에서 멈춘 것을 볼 수 있습니다.

 

직선 하나만으로는 입력에 대한 출력을 분류할 수 없습니다.

 

단층 퍼셉트론은 이처럼 직선만으로는 분류할 수 없는 경우를 구현할 수 없습니다.


5. 다층 퍼셉트론

단층 퍼셉트론은 선형 분리만 가능합니다.

 

한계를 개선하기 위해 다층 퍼셉트론이 등장하였습니다.

 

다층 퍼셉트론은 말 그대로 층이 여러개입니다.

5-1. 논리 회귀 XOR 분류 모델

model = nn.Sequential(
    nn.Linear(2, 64),
    nn.Sigmoid(),
    nn.Linear(64, 32),
    nn.Sigmoid(),
    nn.Linear(32, 16),
    nn.Sigmoid(),
    nn.Linear(16, 1),
    nn.Sigmoid()
)

# 입력 - 은닉 - 출력

print(model)

output>>

Sequential(
  (0): Linear(in_features=2, out_features=64, bias=True)
  (1): Sigmoid()
  (2): Linear(in_features=64, out_features=32, bias=True)
  (3): Sigmoid()
  (4): Linear(in_features=32, out_features=16, bias=True)
  (5): Sigmoid()
  (6): Linear(in_features=16, out_features=1, bias=True)
  (7): Sigmoid()
)

5-2. 학습

x = [[0, 0], [0, 1], [1, 0], [1, 1]]
y = [[0], [1], [1], [0]]

x_train = torch.FloatTensor(x)
y_train = torch.FloatTensor(y)

optimizer = optim.SGD(model.parameters(), lr=1)
epochs = 5000

for epoch in range(epochs + 1):
    y_pred = model(x_train)
    loss = nn.BCELoss()(y_pred, y_train)

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

    if epoch % 1000 == 0:
        y_bool = (y_pred >= 0.5).float()
        accuracy = (y_train == y_bool).float().sum() / len(y) * 100
        print(f'Epoch {epoch:4d}/{epochs} Loss: {loss:.6f} Accuracy: {accuracy:.2f}%')

output>>

Epoch    0/5000 Loss: 0.693836 Accuracy: 50.00%
Epoch 1000/5000 Loss: 0.693107 Accuracy: 50.00%
Epoch 2000/5000 Loss: 0.693017 Accuracy: 50.00%
Epoch 3000/5000 Loss: 0.692406 Accuracy: 75.00%
Epoch 4000/5000 Loss: 0.021657 Accuracy: 100.00%
Epoch 5000/5000 Loss: 0.000675 Accuracy: 100.00%

50%였던 정확도가 100%로 올랐습니다.

 

이제 2개의 결과를 정확하게 분류할 수 있는 모델이 탄생했습니다.

5-2. 결과

아래 그림은 위 모델을 시각화한 것입니다.

다층 퍼셉트론

입력층: nn.Linear(2, 64), nn.Sigmoid()

은닉층: nn.Linear(64, 32), nn.Sigmoid(), nn.Linear(32, 16), nn.Sigmoid()

출력층: nn.Linear(16, 1), nn.Sigmoid()

 

단층 퍼셉트론과 다층 퍼셉트론의 차이점중 하나는 은닉층의 유무입니다.

 

은닉층이란 입력층과 출력층 사이에 존재하는 층을 말합니다.

 

중간중간에 있는 Sigmoid()함수는 활성화함수로 각 선형 함수들이 합쳐지지 않도록 해줍니다.

 

또한 선형 함수를 곡선화 시키는 역할을 합니다.

 

이처럼 은닉층이 2개 이상인 신경망을 심층 신경망(Deep Neural Network, DNN)이라고 하고, 심층 신경망을 학습시키는 것을 딥 러닝(Deep Learning)이라고 합니다. 


끝내며 🎲

본격적으로 딥러닝이 시작되었습니다.

 

대학교 3학년 이러닝 과목으로 딥러닝 기초 이론과 용어에 대해서 배웠던 기억이 있습니다.

 

(절대평가에 오픈북시험이라 공부를 거의 안 함..)

 

적어도 한번은 들어본 이름들이 나오니 반가운 마음에 더 열심히 공부하게 되네요.

 

수학적으로 깊게 탐구하기 위해선 시간이 더 필요하겠지만 지금은 제가 이해한 수준에서 쉽게 전달해보도록 하겠습니다.

 

감사합니다.


참고

https://wikidocs.net/60680

댓글