[AITech] 20220207 - MLP Basics
학습 내용
Neural Networks
What is Neural Network? 뉴럴 네트워크란 무엇일까요?
일반적으로, 우리는 이 뉴럴 네트워크, 그러니까 딥러닝 구조란 인간의 뇌의 구조를 모방한 데서 왔다고 이야기합니다. 이것이 틀렸다는 것은 아닙니다만, 이 강의에서는 약간 다른 인사이트를 전달해주시고 계십니다.
딥러닝이라는 것이 태동하던 시절에는 그 시작이 인간의 뇌/인지 과정에 대한 모방으로 시작했을지언정, 지금은 ‘굳이 인간의 뇌를 모방한 구조라고 설명해야 하나?’라고 할만큼 딥러닝은 많이 발전해왔고, 그 구조에서 차이를 보입니다. 예를 들면 Backpropagation과 같은 것들은, 딥러닝에서 학습을 위해 필연적으로 사용되지만 우리의 뇌에서 그것이 필수적인 학습 과정이라고 할 수는 없는 것이죠.
그래서, 이 강의에서는 이 Neural Network란 선형 변환과 비선형 변환 블록들이 쌓여 만들어진 근사 함수를 찾는 모델이라고 전달합니다. 개인적으로도, 이 인사이트가 현대의 뉴럴 네트워크 구조를 설명하는 데 더 적합한 것 같고 그 구조나 목적을 이해하기에 더 적합하다고 생각합니다.
아래 모델은 ResNet이라는 모델의 구조를 나타낸 것입니다.
Linear Neural Networks
이 포스팅에서는 많고 많은 뉴럴 네트워크 구조들 중 Linear Neural Network에 대해 살펴보면서 안에서 무슨 일이 일어나는지 간단히 살펴보겠습니다.
그 옛날 올드스쿨의 모델들이든, 작금의 최신 모델들이든 그 모델을 제대로 정의하기 위해서는 다음의 4가지가 필요합니다.
- Data: The data that the model can learn from
- Model: The model how to transform the data
- Loss: The loss function that quantifies the badness of the model
- Algorithm: The algorithm to adjust the parameters to minimize the loss
그리고 선형 모델의 그것들은 다음과 같이 나타낼 수 있습니다.
첫번째로, 우리는 주어진 입력을 이용해 출력을 만들어냅니다. 이 때 선형 모델은 출력을 만들기 위해 Affine transforms(어파인/아핀 변환, 직선, 길이의 비, 평행성을 보존하는 선형 변환으로 회전, 평행이동, 스케일 조정, 확대/축소, 반전 등을 포함)를 적용합니다.
선형 모델에서의 아핀 변환은 단순히 행렬곱/행렬 덧셈을 의미하며, 아핀 변환에 대해 더 자세히 알고 싶으신 분들은 아래 참고 자료 를 참조해주세요.
그리고 선형대수 시간에 배웠듯이, 어떤 벡터 x에 행렬을 곱해 다른 벡터 y로 만든다는 것은 x의 차원에서 y의 차원으로의 mapping이 일어나는 것으로 이해할 수 있습니다.
두번째로, 출력값을 얻고 나면 이 출력 값이 실제 정답과 얼마나 다른지를 나타내는 Loss를 계산합니다. 선형 모델의 Loss 식은 보통 MSE를 많이 사용하며, 위 그림에서 본 Loss 식에 해당합니다.
그런데 이 ‘얼마나 다른지’에 대해 우리가 알고만 있다면, 이는 그 어떤 의미도 없습니다. 이 얼마나 다른지를 통해 틀린 것을 계속해서 배워가는 것이 중요하겠죠. 뉴럴 네트워크에서는 이것이 Loss를 각 층의 가중치에 대해 미분함으로써 일어납니다.
세번째로, 위와 같이 계산한 미분치를 통해 해당 층의 가중치를 갱신합니다. 이를 통해 뉴럴 네트워크는 학습을 합니다.
그리고 이렇게 학습을 할 때는 ‘한 번에 얼마나 배울 것인지’를 지정해주는 step size(learning rate, 학습율)를 지정해줍니다.
이렇게 선형 모델에서 ‘학습’을 하는 과정에 대해 간단하게 살펴보았습니다.
Beyond Neural Networks
위에서 선형 모델에 대해 살펴보았는데, 이제 우리는 여기에 비선형성을 추가할 것입니다.
위의 행렬곱/행렬 덧셈 같은 선형 변환으로는 몇 번을 하든 비선형성을 만들어내지 못합니다. 어떤 벡터에 행렬을 몇 번을 곱하든, 그 결과는 행렬끼리 먼저 곱해진 결과 행렬을 어떤 벡터에 한 번 곱한 것과 같기 때문입니다.
따라서, 우리는 더 많은 함수들, 비선형성이 존재하는 많은 함수들을 근사하기 위해 중간에 activation function(비선형 함수) 층을 추가합니다. 이렇게 함으로써 우리의 뉴럴 네트워크는 훨씬 많은 종류의 함수들을 근사하는 것이 가능하게 됩니다.
많이 사용되는 비선형 함수에는 다음의 함수들이 있습니다.
강의에서는, 이렇게 선형 함수와 비선형 함수의 연속으로 이루어진 뉴럴 네트워크 모델이 거의 모든 함수를 표현할 수 있는 것은 맞지만, 이것이 우리가 만든 모델이 모든 함수를 적절히 표현할 수 있는 것과는 다르다는 것을 전달해주고 있습니다.
즉, 표현을 할 수는 있을테지만 실제로 내 모델이 그것을 표현하도록 만드는 것은 쉽지만은 않다는 것이죠.
Multi-Layer Perceptron
그리고, 이런 뉴럴 네트워크 모형은 깊~~게 쌓은 것을 MLP(Multi-Layer Perceptron)라고 합니다.
이렇게 깊은 신경망은 여러 task를 수행할 수 있으며, 그 목적에 따라 loss function 또한 달라지게 됩니다. 모델에 따라 또는 목적에 따라 ‘왜 그 손실 함수를 사용하느냐’에 대한 얘기는 통계학적인 관점에서 접근할 수 있으며, 그 인사이트는 단순하지만은 않습니다.
여기서는 그 내용에 대해서는 다루지 않고, 대표적인 task마다 가장 일반적으로 사용하는 loss function을 소개하면서 포스팅을 마치겠습니다.
MLP 실습
MLP를 간단히 code level에서 보도록 하겠습니다.
-
Define the MLP Model
class MultiLayerPerceptronClass(nn.Module): def __init__(self,name='mlp',xdim=784,hdim=256,ydim=10): super(MultiLayerPerceptronClass,self).__init__() self.name = name self.xdim = xdim self.hdim = hdim self.ydim = ydim # 입력층 - 은닉층 사이 네트워크 self.lin_1 = nn.Linear( # indim, outdim self.xdim, self.hdim ) # 은닉층 - 출력층 사이 네트워크 self.lin_2 = nn.Linear( # indim, outdim self.hdim, self.ydim ) self.init_param() # initialize parameters # 가중치 초기화 def init_param(self): nn.init.kaiming_normal_(self.lin_1.weight) nn.init.zeros_(self.lin_1.bias) nn.init.kaiming_normal_(self.lin_2.weight) nn.init.zeros_(self.lin_2.bias) # 순전파(입력 -> 출력 계산) def forward(self,x): net = x net = self.lin_1(net) # 입력층 -> 은닉층 선형 변환 net = F.relu(net) # 비선형 변환 net = self.lin_2(net) # 은닉층 -> 출력층 선형 변환 return net # logit M = MultiLayerPerceptronClass(name='mlp',xdim=784,hdim=256,ydim=10).to(device) loss = nn.CrossEntropyLoss() # 손실 함수 정의 optm = optim.Adam(M.parameters(),lr=1e-3) # 옵티마이저 정의
-
Train Model
M.init_param() # initialize parameters M.train() # train mode EPOCHS = 10 # Epoch: 전체 데이터를 한 번 도는 것 for epoch in range(EPOCHS): loss_val_sum = 0 for batch_in,batch_out in train_iter: ### Forward path # 1. 입력 -> 출력 계산 y_pred = M.forward(batch_in.view(-1, 28*28).to(device)) # reshape input data # 2. 손실값 계산 loss_out = loss(y_pred,batch_out.to(device)) ### Update # 3. reset gradient -> 그래디언트 초기화 optm.zero_grad() # 4. backpropagate -> 손실 함수 그래디언트 계산 loss_out.backward() # 5. optimizer update -> 각 가중치에 대해 업데이트 optm.step() loss_val_sum += loss_out loss_val_avg = loss_val_sum/len(train_iter) ...
참고 자료
- Linear Neural Networks
Leave a comment