Skip to content

Latest commit

 

History

History
154 lines (115 loc) · 5.55 KB

8-2. Multi Layer Perceptron.md

File metadata and controls

154 lines (115 loc) · 5.55 KB

1. Review : XOR

  • XOR 문제는 Perceptron으로 해결할 수 없다.
  • XOR을 좌표상에 표시하면 '한 개의 선' 만으로는 분류를 할 수 없기 때문이다.



2. Multylayer Perceptron

  • XOR 문제를 해결하기 위해서는 MLP가 필요하다.
  • MLP : 한 개 이상의 레이어 층을 갖는 퍼셉트론
  • XOR을 좌표상에 표시하고 '두 개의 선'을 그으면 분류를 할 수 있게 된다!



3. Backpropagation이란?

  • Perceptron만 있었을 때는 사람들은 MLP는 구현되지 못하며, 인공신경망으로는 XOR 문제를 해결 못한다고 생각했다.
  • Backpropagation 알고리즘이 개발되면서 MLP를 학습할 수 있게 되었다!



4. Backpropagation 알고리즘 과정

(1) 인풋 X가 들어온다.

(2) 레이어 1을 지난다. Activation 함수를 통해 다음 레이어로 출력된다.

(3) 레이어 2를 지난다. Activation 함수를 통해 다음 레이어로 출력된다.

(4) 아웃풋인 예측값 Y가 계산된다.

(5) 실제값과 예측값을 통해 Loss(cost)를 계산한다.

(6) 레이어의 가장 뒷단부터 Loss값을 최소화 시킬 수 있도록 웨이트를 업데이트 해준다.




5. Backpropagation 수작업 코드 실습 - XOR

# XOR 데이터
X = torch.FloatTensor([[0, 0], [0, 1], [1, 0], [1, 1]]).to(device) 
Y = torch.FloatTensor([[0], [1], [1], [1], [0]]).to(device)

# MLP의 레이어들 선언 (nn.Linear를 2개 해서 써도 되지만 이번 실습에서는 직접 W, b를 입력해 봄)
w1 = torch.Tensor(2, 2)to(device) # 인풋 2 아웃풋 2인 레이어 선언
b1 = torch.Tensor(2).to(device)
w2 = torch.Tensor(2, 1).to(device) # 인풋 2 아웃풋 1인 레이어 선언 ex) XOR은 0, 1을 받아서 1을 출력하기 때문
b2 = torch.Tensor(1).to(device)

# 시그모이드도 PyTorch 내장함수가 아닌 직접 구현해서 이용!
def sigmoid(x):
  return 1.0 / (1.0 + torch.exp(-x))
  
def sigmoid_prime(x): # 시그모이드 미분
  return sigmoide(x) * (1 - sigmoid(x))
  
for step in range(10001):
  # MLP 모델
  l1 = torch.add(torch.matmul(X, w1), b1) # 첫번째 레이어(인풋 * w1)
  a1 = sigmoid(l1) # activation! (첫번째 레이어 결과값을 sigmoid화 함)
  l2 = torch.add(torch.matmul(a1, w2), b2) # 두번째 레이어(a1 * w2)
  Y_pred = sigmoid(l2) # activation! (두번째 레이어 결과값을 sigmoid화 함)
  
  # Binary cross entropy loss
  cost = -torch.mean(Y * torch.log(Y_pred) * (1 - Y) * torch.log(1 - Y_pred))
  
  # Backpropagation 직접 구현 시작 ㄱㄱ (Pytorch 함수 중 Backward의 내용)
  d_Y_pred = (Y_pred - Y) / (Y_pred * (1.0 - Y_pred) + 1e-7) # cost를 미분한 식
  
  # Backpropagation : Layer 2
  d_l2 = d_Y_pred * sigmoid_prime(l2) # sigmoid activation에 대한 미분
  d_b2 = d_l2 # bias에 대한 미분
  d_w2 = torch.matmul(torch.transpose(a1, 0, 1), d_b2) # weight에 대한 미분. matmul은 matrix의 곱이다. transpose는 두번째 인자값과 세번째 인자값의 차원을 swap시킨다. ex) 10 * 5 -> 5 * 10
  # 여기까지 진행하면 Layer 2에 대한 BP가 끝난 것이다.
  
  # Backpropagation : Layer 1
  d_a1 = torch.matmul(d_b2, torch.transpose(w2, 0, 1))
  d_l1 = d_a1 * sigmoid_prime(l1)
  d_b1 = d_l1
  d_w1 = torch.matmul(torch.transpose(x, 0, 1), d_b1)
  # Layer 1에 대한 BP 끝!

  # Weight Update 시키기(Pytorch 함수 중 step의 내용. Gradient descent)
  w1 = w1 - learning_rate * d_w1 # 기존의 weight - (learning_rate * 미분값)
  b1 = b1 - learning_rate * torch.mean(d_b1, 0)
  w2 = w2 - learning_rate * d_w2
  b2 = b2 - learning_rate * torch.mean(d_b2, 0)
  
  if step % 100 == 0:
    print(step, cost.item()) # Accuracy : 1.0 MLP가 XOR을 성공적으로 잘 분류했다!!



6. Backpropagation PyTorch 코드 실습 - XOR

X = torch.FloatTensor([[0, 0], [0, 1], [1, 0], [1, 1]]).to(device)
Y = torch.FloatTensor([[0], [1], [1], [0]]).to(device)

# 레이어 및 MLP 모델 정의
linear1 = torch.nn.Linear(2, 2, bias = True) # input 2 output 2의 레이어
linear2 = torch.nn.Linear(2, 1, bias = True) # input 2 output 1의 레이어
sigmoid = torch.nn.Sigmoid() # 시그모이드
model = torch.nn.Sequential(linear1, sigmoid, linear2, sigmoid).to(device) #모델

criterion = torch.nnBCELoss().to(device)
optimizer = torch.optim.SGD(model.parameters(), lr=1)

for step in range(10001):
  hypothesis = model(X)
  cost = criterion(hypothesis, Y)

  optimizer.zero_grad()  
  # 위에서 아주 길게 작성했던 Backpropagation과 Gradient descent Update를 단 두줄로 작성 가능..!!
  cost.backward()
  optimizer.step()
  
  if step % 100 == 0:
    print(step, cost.item()) # accuracy : 1.0. MLP로 XOR 문제 해결 가능!



7. 레이어 넓고 깊게 쌓아보기

  • 깊다는 뜻 : 여러 레이어 층으로 구성되어 있다.
  • 넓다는 뜻 : 한 레이어가 넓게 구성되어 있다.
X = torch.FloatTensor([[0, 0], [0, 1], [1, 0], [1, 1]])
Y = torch.FloatTensor([[0], [1], [1], [0]]).to(device)

# 4 MLP
linear1 = torch.nn.Linear(2, 10, bias = True) # input 2, output 10. ex) [0,1]의 2개가 들어와서 다음 레이어에 10개로 출력됨
linear2 = torch.nn.Linear(10, 10, bias = True) # input 10, output 10
linear3 = torch.nn.Linear(10, 10, bias = True) # input 10, output 10
linear4 = torch.nn.Linear(10, 1, bias = True) # input 10, output 1. ex) [0,1]의 2개가 들어와서 레이어들을 거쳐 1이 출력됨
sigmoid = torch.nn.Sigmoid

# 결과
# 2 MLP보다 4 MLP가 loss가 더 빨리 많이 줄어든다!