본인이 생각하는 마스킹을 고려한 custom loss랑 custom accuracy은 아래 코드와 같음.
def masked_loss(label: tf.Tensor, pred: tf.Tensor) -> float:
mask = label != 0
loss_object = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True, reduction='none')
loss = loss_object(y_true=label, y_pred=pred)
mask = tf.cast(mask, dtype=loss.dtype)
loss *= mask
loss = tf.reduce_sum(input_tensor=loss) / tf.reduce_sum(input_tensor=mask)
return loss
def masked_accuracy(label: tf.Tensor, pred: tf.Tensor) -> float:
pred = tf.argmax(input=pred, axis=2)
label = tf.cast(label, dtype=pred.dtype)
matched = label == pred
mask = label != 0
matched = matched & mask
matched = tf.cast(matched, dtype=tf.float32)
mask = tf.cast(mask, dtype=tf.float32)
return tf.reduce_sum(input_tensor=matched) / tf.reduce_sum(input_tensor=mask)
그리고 현재 본인이 보고있는 책에서는 아래 코드와 같이 소개함.
loss_object = tf.keras.losses.SparseCategoricalCrossentropy(
from_logits=True, reduction='none')
train_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(name='accuracy')
def loss(real, pred):
mask = tf.math.logical_not(tf.math.equal(real, 0))
loss_ = loss_object(real, pred)
mask = tf.cast(mask, dtype=loss_.dtype)
loss_ *= mask
return tf.reduce_mean(loss_)
def accuracy(real, pred):
mask = tf.math.logical_not(tf.math.equal(real, 0))
mask = tf.expand_dims(tf.cast(mask, dtype=pred.dtype), axis=-1)
pred *= mask
acc = train_accuracy(real, pred)
return tf.reduce_mean(acc)
여기서 가장 큰 차이점이라고 하면 책에서는 마스킹 해놓고 마지막을 tf.reduce_mean으로 냅다 때려박는데 이러면 masking 부분까지 포함해서 계산하는터라 잘못되지 않았나 싶음. Tensorflow 공식 Document에서도 첫번째 방식으로 하던데 왜 2번째 방식으로 하는지 모르겠음. 2번째 방식으로 하면 loss나 accuracy가 너무 심하게 뻥튀기 되던데..
그래서 저는 masked_select 한다음 mean 때려 버립니데이 그나저나 텐서플로우? 토나와 ㅡㅡ
보통은 mask sum하지 않나 - dc App