머신러닝&딥러닝/실습

[머신러닝&딥러닝] 논리회귀(단층 퍼셉트론)

거북이07 2024. 1. 18. 09:30

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

 

위 문제가 주어졌을 때 논리회귀를 이용하여 AND 문제를  풀어보자.

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

 

우선 위 이미지처럼 [A,B]를 Input 값이라고 가정했을때 각 A, B를 x로 Output을 y로 선언해준다.

AND 문제란 두 값이 전부  1일때 값이 1 로 출력되어야한다.

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

 

nn.Sequential을 사용하여 nn.Linear 선형 레이어와 Sigmoid() 함수를 이용하여 신경망을 정의해줍니다.

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

 

SGD는 확률적 경사 하강법 옵티마이저를  이용하여  객체를 만들어줍니다.

epochs = 1000
for epoch in range(epochs + 1):
    y_pred = model(X)
    loss = nn.BCELoss()(y_pred, y)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    if epoch % 100 == 0:
        y_bool = (y_pred >= 0.5).float()
        accuracy = (y == y_bool).float().sum() / len(y) * 100
        print(f'Epoch {epoch:4d}/{epochs} Loss: {loss:.6f} Accuray: {accuracy:.2f}%')

 

epochs를 1000번으로  지정해준 수 만큼 학습을 진행해줍니다. 여기서 BCELoss는 이진분류를 할 때 사용하는 함수이다 해당 문제에서는 y가 0아니면 1로  출력되기 때문에 BCELoss를 사용해준다.

Epoch    0/1000 Loss: 0.800176 Accuray: 50.00%
Epoch  100/1000 Loss: 0.147906 Accuray: 100.00%
Epoch  200/1000 Loss: 0.083013 Accuray: 100.00%
Epoch  300/1000 Loss: 0.057188 Accuray: 100.00%
Epoch  400/1000 Loss: 0.043427 Accuray: 100.00%
Epoch  500/1000 Loss: 0.034925 Accuray: 100.00%
Epoch  600/1000 Loss: 0.029168 Accuray: 100.00%
Epoch  700/1000 Loss: 0.025020 Accuray: 100.00%
Epoch  800/1000 Loss: 0.021893 Accuray: 100.00%
Epoch  900/1000 Loss: 0.019453 Accuray: 100.00%
Epoch 1000/1000 Loss: 0.017498 Accuray: 100.00%

 

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

X = torch.FloatTensor([[0, 0], [0, 1], [1, 0], [1, 1]])
y = torch.FloatTensor([[0], [1], [1], [1]])
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)
    loss = nn.BCELoss()(y_pred, y)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    if epoch % 100 == 0:
        y_bool = (y_pred >= 0.5).float()
        accuracy = (y == y_bool).float().sum() / len(y) * 100
        print(f'Epoch {epoch:4d}/{epochs} Loss: {loss:.6f} Accuray: {accuracy:.2f}%')

 

OR 문제는  AND와 같다. 

 

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

컴퓨터는 두 가지의 디지털 값, 즉 0과 1을 입력해 하나의 값을 출력하는 회로가 모여 만들어지는데, 이 회로를 ‘게이트(gate)’라고 부릅니다.

표 6-1은 AND 게이트, OR 게이트 그리고 XOR 게이트에 대한 값을 정리한 것입니다. AND 게이트는 x1와 x2 둘 다 1일 때 결괏값이 1로 출력됩니다. OR 게이트는 둘 중 하나라도 1이면 결괏값이 1로 출력됩니다. XOR 게이트는 둘 중 하나만 1일 때 1이 출력됩니다.

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


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)
    loss = nn.BCELoss()(y_pred, y)

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

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

 

or, and 방식과 같은 방법으로 학습을 진행하면

Epoch    0/1000 Loss: 0.706952 Accuracy: 50.00%
Epoch 1000/1000 Loss: 0.693147 Accuracy: 50.00%

 

위  출력 내용처럼  학습이 제대로 되지 않는 모습을 확인할 수 있는데. 그 이유는 아래 이미지처럼 하나의 직선으로는 흰점과  검은점을 구분할 수 없어서 위 같은 문제가 발생하였습니다.

 

✨ 참고

https://ang-love-chang.tistory.com/26

 

[인공지능]다층 퍼셉트론으로 XOR문제 해결하기

이 책에 있는 내용을 정리 한 것임. 모두의 딥러닝 개정2판: 3 코딩으로 XOR 문제 해결하기 - 4 thebook.io 2 퍼셉트론의 과제 사람의 뇌가 작동하는 데 1,000억 개나 되는 뉴런이 존재해야 하는 이유는

ang-love-chang.tistory.com

 

AND와 OR 게이트는 직선을 그어 결괏값이 1인 값(검은점)을 구별할 수 있습니다. 그러나 XOR의 경우 선을 그어 구분할 수 없습니다.

이는 인공지능 분야의 선구자였던 MIT의 마빈 민스키(Marvin Minsky) 교수가 1969년에 발표한 <퍼셉트론즈(Perceptrons)>라는 논문에 나오는 내용입니다. ‘뉴런 → 신경망 → 지능’이라는 도식을 따라 ‘퍼셉트론 → 인공 신경망 → 인공지능’이 가능하리라 꿈꾸던 당시 사람들은 이것이 생각처럼 쉽지 않다는 사실을 깨닫게 됩니다. 알고 보니 간단한 XOR 문제조차 해결할 수 없었던 것입니다. 이 논문 이후 인공지능 연구가 한동안 침체기를 겪게 됩니다. 10여 년이 지난 후에야 이 문제가 해결되는데, 이를 해결한 개념이 바로 다층 퍼셉트론(multilayer perceptron)입니다.

 

다층 퍼셉트론

앞서 종이 위에 각각 엇갈려 놓인 검은점 두 개와 흰점 두 개를 하나의 선으로는 구별할 수 없다는 것을 살펴보았습니다. 언뜻 보기에 해답이 없어 보이는 이 문제를 해결하려면 새로운 접근이 필요합니다.

어릴 적 친구들에게 장난처럼 들었던 문제인데 의외로 기발한 해답에 기억에 오래 남는 것이 하나 있습니다. 바로 ‘성냥개비 여섯 개로 정삼각형 네 개를 만들 수 있는가’라는 문제였습니다.

 

골똘히 연구해도 답을 찾지 못했던 이 문제는 2차원 평면에서만 해결하려는 고정관념을 깨고 피라미드 모양으로 성냥개비를 쌓아 올리니 해결되었습니다.

 

 

인공지능 학자들은 인공 신경망을 개발하기 위해서 반드시 XOR 문제를 극복해야만 했습니다. 이 문제 역시 고정관념을 깬 기발한 아이디어에서 해결점이 보였습니다. 그림 7-3은 전혀 새로운 방법으로 이를 해결하는 모습을 보여 줍니다.

 

 

로 종이를 휘어 주는 것이 답이었습니다. 즉, 좌표 평면 자체에 변화를 주는 것입니다. XOR 문제를 해결하기 위해서 우리는 두 개의 퍼셉트론을 한 번에 계산할 수 있어야 합니다. 이를 가능하게 하려면 숨어있는 층, 즉 은닉층(hidden layer)을 만들면 됩니다.

 

 

입력층과 은닉층의 그래프를 집어넣어 보면 그림 7-5와 같습니다. 은닉층이 좌표 평면을 왜곡시키는 결과를 가져옵니다.

 

입력 값(input)을 놓고 파란색과 빨간색의 영역을 구분한다고 할 때, 그림 7-5의 왼쪽 그림을 보면 어떤 직선으로도 이를 해결할 수 없습니다. 하지만 은닉층을 만들어 공간을 왜곡하면 두 영역을 가로지르는 선이 직선으로 바뀝니다.

 

다층 퍼셉트론이 입력츠오가  출력층 사이에 숨어있는 은닉층을 만드는 것을 도식으로 나타내면 아래 그림과 같습니다.

 

가운데 숨어있는 은닉층으로 퍼셉트론이 각각 자신의 가중치(w)와 바이어스(b) 값을 보내고, 이 은닉층에서 모인 값이 한 번 더 시그모이드 함수(기호로 σ라고 표시합니다)를 이용해 최종 값으로 결과를 보냅니다. 은닉층에 모이는 중간 정거장을 노드(node)라고 하며, 여기서는 n1과 n2로 표현하였습니다.


다중 퍼셉트론을 이용한  XOR 문제 풀이

model = nn.Sequential(
    nn.Linear(2, 64), # 2의 배수 아무거나 써도 괜찮음
    nn.Sigmoid(), # 곡선으로 꺾어주는데 쓰임
    nn.Linear(64, 32), # 히든레이어
    nn.Sigmoid(),
    nn.Linear(32, 16), # 히든레이어
    nn.Sigmoid(),
    nn.Linear(16, 1), # 출력레이어
    nn.Sigmoid()
)

 

히든레이어가 한개 이상 있는걸 딥러닝이라고 하며 은닉층은 많을수록 디테일해진다.

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

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

epochs = 5000

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

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

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

 

위 방법을 이용하면 학습이 잘 되는 모습을 확인할 수 있다.

Epoch    0/5000 Loss: 0.694146 Accuracy: 50.00%
Epoch 1000/5000 Loss: 0.693046 Accuracy: 50.00%
Epoch 2000/5000 Loss: 0.692580 Accuracy: 50.00%
Epoch 3000/5000 Loss: 0.519290 Accuracy: 50.00%
Epoch 4000/5000 Loss: 0.000645 Accuracy: 100.00%
Epoch 5000/5000 Loss: 0.000290 Accuracy: 100.00%