본문 바로가기
Artificial Intelligence/Keras

[Tensorflow 2][Keras] Week 2 - Custom loss functions

by 개발자J의일상 2021. 3. 18.
반응형

본 포스팅은 다음 과정을 정리 한 글입니다.

 

Custom Models, Layers, and Loss Functions with TensorFlow

www.coursera.org/specializations/tensorflow-advanced-techniques

 

지난 시간 리뷰

2021.03.13 - [Artificial Intelligence/Keras] - [Tensorflow 2][Keras] Programming Assignment: Multiple Output Models using Keras Functional API

 

여러분은 tensorflow에서 작업하는 동안 많은 손실함수들을 보았을 것입니다. 

 

일반적으로 model.compile을 호출하면서 특정한 parameter를 넣어 주었습니다. 아래 예처럼 lossoptimizer를 무엇을 쓸지 말입니다. 여기서는 어떤 것을 쓸지 string으로 정의된 것을 적어줍니다. 'mse', 'sgd' 처럼 말이죠.

 

 

아니면 다른 방법으로는 loss object를 사용할 수 도 있습니다.

아래 예제는 mean_squared_error를 tensorflow.keras.losses에서 import하여 string으로 된 loss function의 이름을 적어주는 대신 object를 지정해 주었습니다. 

일반적으로 동일한 작업을 수행할 수 있습니다. 

 

Loss object(손실 개체)를 사용하는 것과 string으로 정의된 function을 쓰는 것의 중요한 차이는 개체 호출에 매개변수를 추가할 수 있다는 점입니다. 

이는 hyper parameter (하이퍼 매개 변수) 조정과 같은 작업을 수행하는 데 훨씬 더 나은 유연성을 가질 수 있습니다. 

 

자신의 손실 함수를 만드는 것은생각보다 훨씬 쉽습니다. 

아래 예제를 통해 Custom loss function을 만드는것을 살펴봅시다.

 

첫 번째로, 사용자 지정 손실 함수를 만들려면 두 개의 매개 변수를 받아들이는 함수를 만들어야 합니다.

일반적으로 두 매개 변수는 각각 y_true, y_pred 라고 불리는 실제 레이블값과 현재 예측값입니다.

 

my_loss_function은 둘의 차이를 계산하는 일종의 함수가 될 것입니다.

우리는 모델의 예측이 y_true 값에 최대한 가까워지도록 해야 합니다. 

optimizer는 네트워크 내에서 가중치와 편향을 조정하는 작업을 하며, optimizer를 사용하여 현재 예측 값을 계산하고, 이것을 가지고 y_true와 비교할 수 있습니다.

예측 값(y_pred)가 정답 값(y_true)와 최대로 가깝다는 것은 loss가 가능한 최소로 작다는 의미입니다.

 

함수 안에 losses를 계산하는 방법은 생략이 되었습니다.

지금은 그냥 어떻게든 loss를 계산한 다음, return한다고 생각해 봅시다.

Optimizer는 이 return값(losses)을 가지고 training의 다음 epoch에 사용합니다.

 

그럼 다음으로는 huber loss를 예로 한번 custom loss function을 만들어 보려고 합니다.

Huber Loss란 아래와 같은 그래프 형태를 띄는 loss를 의미합니다.

Huber Loss에 대해 자세히 설명하지는 않겠지만 이를 구현하기 위해서는 이 것이 어떻게 동작하는지에 대해서 이해할 필요가 있습니다. 

 

공식과 자세한 내용은 아래 wikipedia를 참고 부탁드립니다.

 

en.wikipedia.org/wiki/Huber_loss

 

코드화할 때 고려해야 할 몇 가지 변수가 있습니다.

첫 번째는 threshold(한계치)입니다. 이는 델타 문자로 표기됩니다. 델타는 공식 내에서 위와 아래에 모두 나타나기 때문에 매우 중요합니다. 

두 번째는 Error(오류)입니다. 이 오류는 문자(a)로 표기됩니다. a는 숫자 값이고, 이 것은 단순하게 정답 값과 예측 값의 차이일 뿐입니다. 

 

 

그래서 loss 값은 에러의 절대 값 보다 threshold가 작거나 같을 때 1/2 곱하기 a^2을 갖게 됩니다. 

 

다른 경우는 

다른 경우는 아래와 같은 식을 갖게 됩니다. 뭔가 코드 같이 느껴지지 않나요? 

 

 

그럼 실제 코드를 한번 살펴보겠습니다.

my_huber_loss를 function으로 만들었고 위에서 배웠던 것 처럼 y_truey_predparameter로 받습니다.

첫 번째 line은 threshold를 1로 설정하는 것입니다. 왜 1로 설정하냐구요? 그냥요! 예를 들어보는 겁니다.

그 다음 에러를 계산하는데 이 것은 레이블과 예측을 빼서 구한 다는 것을 위에서 얘기했었죠? 바로 그 것을 코드로 옮긴 것입니다.

에러는 그대로 아래 식에 a에 해당하구요!

 

다음으로 is_small_error를 계산하는데 이 것은 에러의 절대 값이 threshold보다 작거나 같은지를 체크해서 위에 식을 사용할 지 아래 식을 사용할 지 결정하는 것입니다.

 

threshold보다 작으면 small_error_loss가 되는 것이고 이는 1/2 * a^2이므로 그 식을 코드로 작성합니다.

error의 절대값이 threshold보다 작거나 같지 않는 경우는 big_error_loss로 정의하고 아래 공식을 코드화 하여 넣어줍니다. 이는 에러가 큰 경우이기 때문에 big_error_loss라고 이름을 붙인 것 같습니다.

 

tf.where를 사용해서 3개의 parameter를 지정하고 첫 번째 parameter의 참/거짓 여부에 따라 참이면 두 번째 small_error_loss를 반환하고 거짓이면 세 번째 big_error_loss를 반환합니다.

자 이제 거의 끝났습니다. 이제 이 loss function을 어떻게 호출하는지 보여드리겠습니다. 

저자는 이 것을 기계학습의 "Hello World"라고 생각한다고 하는데요. 간단하게 x=y의 관계를 한 개의 뉴런으로 만들었습니다. 그리고 나서 mean_squared_error로 loss를 계산하고 optimizer로 'sgd'를 사용하는 코드입니다. 이제는 굉장히 익숙하실 거라고 생각합니다.

 

이제 여러분이 loss를 custom loss function으로 사용하고 싶다고 하시면 loss에 만들어 놓은 function의 이름을 string형태로 지정하시면 됩니다.

우리가 만든 함수는 my_huber_loss였으므로 loss='my_huber_loss'로 매개 변수에 지정하면 끝입니다.

 

정말 간단하죠?!

 

이 것으로 custom loss function을 만드는 방법에 대해서 설명을 드렸습니다.

긴 글 읽으시느라 고생하셨습니다.

 

감사합니다.

300x250

댓글