모델을 학습시킬 때, 우리는 학습의 과적합을 막고 그 성능을 높이고자 다양한 기법들을 사용 한다. 데이터를 조건에 맞게 scaling 하거나 학습 과정을 변경할 수도 있다. 그 중에서도, 자주 사용하는 방법을 크게 2가지로 나눠보면 아래와 같다.
batch normalization 은 layer의 연산 결과를 다음 입력으로 보내기 전에 평균 0, 표준편차 1로 정규화하는데 사용한다. 각 층의 network마다 들어오는 입력의 분포가 제각각 다른 것을 어느 정도 맞춰주어 학습이 한쪽으로 쏠리는 것을 방지할 수 있다. 아래의 코드처럼 비선형 함수 앞, 연산을 수행하는 layer 뒤에 위치하여 연산의 결과를 원하는 분포로 나오게 한다.
keras.Sequential([
# ...
model.add(Conv2D(filters = 50, ... ))
model.add(BatchNormalization())
model.add(Activation('relu'))
# ...
])
학습 결과를 scaling 하는 위의 개념과는 다르게, 학습 중인 weight 값 자체에 제약을 거는 방법이다. cs231n에서는 학습에 penalty 를 준다고 설명했는데 좋은 표현이라고 생각한다. dropout 으로 예를 들면 이해하기 쉬울 것 같아서 아래 그림과 글, keggle의 dropout 을 시각화하고 적용한 코드를 가져왔다.
keras.Sequential([
# ...
model.add(Flatten())
model.add(Dense(50, activation = 'relu', ... ))
model.add(Dropout(0.5)) # apply 50% dropout to next layer
# ...
])
비선형 함수까지 거친 뒤에 sum하는 과정에서 dropout layer를 넣어 network 중 일부를 생략하고 계산하는 방법이 dropout이다. 여기서 rate = 0.5이므로 절반의 확률로 값들이 sum됨을 알 수 있다. 이는 랜덤 선택된 network는 학습에 영향을 끼치지 않게 하여 너무 딱 맞게 학습되는 것을 막아준다. 또한 각각의 network가 서로에게 주는 영향이 줄어들기 때문에 좀 더 좋은 feature를 얻을 수 있게 한다.
l1 ,l2 도 regularization의 한 방법이라고 생각할 수 있다.
l1 norm(Manhattan distance) : 절댓값을 사용하여 두 벡터의 차이를 구한 것
l2 norm(Euclidean distance) : 제곱한 두 벡터의 차를 모두 더해 루트 씌운 것
이제 l1/l2 norm 과 유사하게 l1/l2 loss를 구할 수 있다. l1 loss는 l1 norm에서 벡터가 들어가는 자리에 예측값과 정답값을 넣어주면 된다. 즉, 정답과 예측의 차이의 절댓값. 절대값이기에 loss 입장에서 보면 이상치값에 크게 민감하지 않다고 생각할 수 있다. 이와 다르게 l2 loss는 둘의 차이에 절대값이 아닌 제곱을 취하여 차이가 클수록 그 결과가 크게 반영되어 robust 하지 않다고 할 수 있다.
여기서 더 나가면 l1/l2 regulization이 되는데, loss에 람다값을 추가하여 더 큰 영향을 주는 방법이다. 람다가 클수록 loss가 그만큼 커지게 되니 학습시 과도한 변화를 막을 수 있어 정규화시킨다고 표현할 수 있을 것이다. l1/l2 regularization을 사용하는 linear regression 모델을 lasso, ridge 모델이라고 한다.
위에서는 여러가지 방법으로 구분했지만 결국 하나의 목적은, 제너럴한 모델을 위해 overfitting을 막고 더 나은 학습을 위한다는 점에서 같다. 그 외에도 일반적으로 성능을 높이기 위해서는 data augmentaion, ensemble, early stopping 등이 있다. 앞으롷 할 일은 그 방법들을 적절한 곳에 잘 활용할 수 있도록 하는 것이겠다.