1. 뉴런(neuron)
1-1. 생물학적 뉴런
- 인간의 뇌는 수십억 개의 뉴런을 가지고 있음
- 뉴런은 화학적, 전기적 신호를 처리하고 전달하는 연결된 뇌신경 세포
1-2. 인공 뉴런
- 1943년에 워렌 맥컬록, 월터 피츠가 단순화된 뇌세포 개념을 발표
- 신경 세포의 이진 출력을 가진 단순한 개념 -> 논리 게이트라고 설명
- 생물학적 뉴런의 모델에 기초한 수학적 기능으로 각 뉴런이 입력을 받아 개별적으로 가중치를 곱하여 나온 합계를 비선형 함수로 전달하여 출력을 생성
2. 퍼셉트론(Perceptron)
- 1957년 인공 신경망의 가장 기본적인 형태로 처음 소개됨
- 입력과 출력을 가진 단일 뉴런 모델을 기반
- 초기에 기계 학습 알고리즘 중 하나로 이진 분류 문제를 해결하기 위해 설계
2-1. 논리 회귀(단층 퍼셉트론)로 AND 문제 풀기
AND | 0 | 1 |
0 | 0 | 0 |
1 | 0 | 1 |
AND는 A와 B를 값을 받고 True 와 False를 입력받고
하나로 False가 나오면 false 가 나옵니다.
import torch
import torch.nn as nn
import torch.optim as optim
X = torch.FloatTensor([[0, 0], [0, 1], [1, 0], [1, 1]])
y = torch.FloatTensor([[0], [0], [0], [1]])
0,0 -> 0 (false)
0, 1 -> 0 (false)
1, 0 ->0 (false)
1, 1 -> 1 (true)
#모델만들기
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} Accuracy: {accuracy: .2f}%')
100바퀴때부터 100.00%로 나오는것을 확인할 수 있습니다.
즉 세포 하나로 잘 풀었다는거고 변수 2개만으로 잘 나오는것을 확인할 수 있습니다.
2-2. 논리 회귀(단층 퍼셉트론)로 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} Accuracy: {accuracy: .2f}%')
바뀐것은 위에 or문자로 변경된 값 입니다.
OR | 0 | 1 |
0 | 0 | 1 |
1 | 1 | 1 |
2-3. 논리 회귀(단층 퍼셉트론)로 XOR 문제 풀기
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 = 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 % 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} Accuracy: {accuracy: .2f}%')
여기는 아무리해도~~~ 에포크를 아무리 많이 돌려도 정확 예측값이 50%이상 늘어나지 않는다는것을 확인할 수 있습니다.
왜 그럴까요...?
1,1 일대만 1이기때문에 이걸 직선으로 그어서 분류를하면 직선으로 잘 나누어지는것을 확인할 수 있습니다.
or도 마찬가지로 직선으로 그으면 분류가 잘 되는것을 확인할 수 있습니다.
그렇지만 xor을 그래프로 나타내면
직선으로 나눌수가 없다는것을 확인할 수 있습니다. (Linear 사용이 불가함..)
차원을 구부리면 만날 수 있다는것을 이용해서 차원을 구부려주면 분류할 수 있습니다.
이렇게 차원을 구부리면 만날 수 있는것을 확인할 수 있습니다. (종이접기 생각하기)
#xor값 변경
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 % 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} Accuracy: {accuracy: .2f}%')
이렇게 해도 마찬가지로 50,50,50,50,75,등등 나오고 절대로 100이 나올 수 없습니다..
저 값이 나온것도 그냥 찍은거라서 결과학습이 잘 되지않습니다.
그래서 차원을 늘려서 확인을 해야합니다.
2-4. 다층 퍼셉트론으로 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()
)
model
#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()
#)
지금보면 2개를 넣어서 64개로 뿜어내고
그 다음 시그모이드 적어놓고 다음으로 64개 받은것을 32개로 output하고
다시 input에 32개 , output은 16개
다시 inpiut에 16개, output에 1개
원래 OUTPUT은 1개로 끝내줍니다~
여기는 입력층이 하나(2,64) 있고 출력층(16,1)이 하나 있는것을 확인할 수 있습니다.
그런데 그 사이에 있는것들은 뭐라고 하냐면 히든레이어 라고 합니다.
이런 층들이 많아질수록 복잡하고 더 학습이 잘 됩니다.
머신러닝과 딥러닝의 차이
머신러닝과 딥러닝의 차이는
안에 히든레이어 즉 숨겨진 층들이 있는것을 의미하고 머신러닝은 숨겨진 층이없는것을 머신러닝이라고
합니다.
그 후 모델생성의 출력값을 보면 층이 잘 쌓여있는것으로 확인할 수 있습니다.
차원이 한 층 더 쌓였으니 잘 만들어졌는지 확인해보겠습니다.
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 % 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} Accuracy: {accuracy: .2f}%')
모델은 위에서 만들었으니까 삭제했습니다.
돌려보니 마지막쯤에 학습이 100%로 잘 된것으로 확인됩니다.
만약 100%가 되지않는다면 히든 레이어를 쌓아서 학습률을 높일 수 있습니다.
'AI 컴퓨터 비전프로젝트 > [ML,DL]머신러닝,딥러닝' 카테고리의 다른 글
[DL] CNN 기초, 체험사이트 (0) | 2024.07.27 |
---|---|
[DL] 비선형 활성화 함수, 역전파 (0) | 2024.07.26 |
[ML/DL] 데이터로더의 의미를 확인 후 손글씨 데이터셋으로 테스트해보기 (3) | 2024.07.25 |
[ML/DL] 파이토치,텐서,GPU (0) | 2024.07.18 |
[ML/DL] 파이토치로 구현한 선형회귀_단항,최적화, 다중 선형회귀 (2) | 2024.07.18 |