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에게 감사하며 포스팅을 마칩니다.
'Deep Learning' 카테고리의 다른 글
Docker Image에서 개발 중인 코드를 사용하기 (0) | 2020.06.02 |
---|---|
Pre-trained Word Vector를 Tensorflow에서 사용하기 (0) | 2020.05.20 |
대용량 훈련 데이터 처리 - Generator로 TF Dataset 만들기 (3) | 2020.05.07 |
Word Vector 훈련 데이터를 키우면 얼마나 도움이 될까? (0) | 2020.05.01 |
Tensorflow의 Embedding Layer vs fastText (0) | 2020.04.30 |