Deep Learning

CategoricalCrossentropy vs SparseCategoricalCrossentropy

둔진 2020. 5. 14. 07:19

  Tensorflow는 classification task에서 간편하게 사용할 수 있는 cross entropy loss 함수를 제공하고 있습니다. Binary classification이라면 BinaryCrossentropy를 사용하면 되고, Multi-class classification이면 CategoricalCrossentropy를 사용하면 됩니다. 그런데 API를 보면 비슷하게 생긴 SparseCategoricalCrossentropy라는 녀석도 있습니다. 차이가 뭘까요?

  결론부터 말씀드리면,

  • 훈련 데이터의 label(target)이 one-hot vector 이면 CategoricalCrossentropy
  • 훈련 데이터의 label(target)이 정수이면 SparseCategoricalCrossentropy

  를 사용하면 됩니다.

 

  간단한 예를 살펴보겠습니다.

model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Dense(32, input_shape=(128,)))
model.add(tf.keras.layers.Dense(3))
model.summary()

  세 개의 class 중 하나를 찾는 아주 간단한 neural net을 가정해보겠습니다. 훈련 데이터는 아래처럼 생겼다고 해보죠.

1 0.1 0.2 0.1 0.3 ... 0.2
0 0.3 0.1 0.3 0.1 ... 0.1
0 0.4 0.7 0.1 0.7 ... 0.9
2 0.2 0.1 0.5 0.1 ... 0.0
2 0.2 0.1 0.8 0.1 ... 0.0

  첫번째 열이 label이고요. 즉 label은 0, 1, 2 중에 하나가 되겠죠. 만약에 label이 1인 경우

  • one-hot vector로 표현하면 [0, 1, 0]이 될 것이고,
  • 정수로 표현한다면 1이 될 겁니다.

  label 2는 [0, 0, 1]과 2가 각각 될 것이고요.

 

  위에 정의한 neural net의 output은 3차원이기 때문에 (예를 들어 [0.1, 0.1, 0.9]) loss를 계산하기 위해서는 label을 one-hot vector로 변환해서 훈련을 시작해야 합니다. 귀찮죠. 그래서 정수로 된 label을 주면 내부적으로 one-hot vector로 변환해서 알아서 loss를 계산해주는 녀석이 SparseCategoricalCrossentropy입니다. 코드로 살펴보겠습니다.

 

import tensorflow as tf

categorical_loss = tf.keras.losses.CategoricalCrossentropy()
y_target_categorical = tf.convert_to_tensor([[0, 0, 1], [0, 1, 0]])
y_predction = tf.convert_to_tensor([[0, 0.1, 0.9], [0.1, 0.8, 0.2]])
categorical_loss(y_target_categorical, y_predction).numpy()

  이미 label이 one-hot vector 형태라면 CategoricalCrossentropy를 사용하면 됩니다.

  * CategoricalCrossentropy와 SparseCategoricalCrossentropy 모두 인자가 (batch_size, num_classes)라고 가정합니다. 이 경우는 batch_size가 2이고, num_classes가 3이고요.

 

  하지만 one-hot vector가 아닌 정수 형태 label을 사용하면 에러가 납니다.

y_target_sparse = tf.convert_to_tensor([2, 1])
categorical_loss(y_target_sparse, y_predction).numpy()
InvalidArgumentError: Incompatible shapes: [2] vs. [2,3] [Op:Mul] name: categorical_crossentropy/mul/

  이럴 때는 간단하게 SparseCategoricalCrossentropy를 사용하면 one-hot vector로 내부적으로 변화해서 잘 처리됩니다.

sparse_categorical_loss = tf.keras.losses.SparseCategoricalCrossentropy()
sparse_categorical_loss(y_target_sparse, y_predction).numpy()

 

  이렇게 또 반복적이고 번거로운 일을 대신해주는 Tensorflow에게 감사하며 포스팅을 마칩니다.