SparseCategoricalCrossentropy

Posted 琥珀彩

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SparseCategoricalCrossentropy相关的知识,希望对你有一定的参考价值。

import tensorflow as tf
import numpy as np
y_true = tf.constant([1, 2])
y_pred = tf.constant([[0.05, 0.95, 0], [0.1, 0.8, 0.1]])
loss = tf.reduce_mean(tf.keras.losses.sparse_categorical_crossentropy(y_true, y_pred))
scce = tf.keras.losses.SparseCategoricalCrossentropy()

print(loss.numpy())
print(scce(y_true, y_pred).numpy())
output
1.1769392
1.1769392

其中有两个基准值1,2说明一共有两类且分别为第一类,第二类,又有两个预测数组[0.05, 0.95, 0], [0.1, 0.8, 0.1]。表明在预测第一个的时候,属于第一类的概率为0.05,属于第二类的概率为0.95,既不属于第一类也不属于第二类的概率为0。同理,在预测第二个的时候,属于第一类的概率为0.1,属于第二类的概率为0.8,既不属于第一类也不属于第二类的概率为0.1。
所以在使用这个函数时,需要如下组织y_true和y_pred:
假如分类时存在三类:其中y_true为:[1,2,1,3]

因为sparse_categorical_crossentropy接受的是离散值,且y_true出现了1,2,3 所以共三类,共四个需要预测。y_pred的组织应该如下:

[0.05, 0.95, 0,0],
[0.1, 0.8, 0.1,0],
[0.1, 0.8, 0.1,0],
[0.1, 0.8, 0.1,0]

意思为,对于第1个预测:属于第一类,第二类,第三类的概率分别为0.05,0.95,0;不属于任何一类的概率为0。
对于第2,3,4个的预测依次类推。
其中这样的组织方式,适用于分类任务,也适用于语义分割任务。因为语义分割任务就是像素点所属类别的预测。
再比如:

y_true = tf.constant([1, 2, 3, 4])
y_pred = tf.constant([
    [0.05, 0.95, 0, 0, 0],
    [0.1, 0.8, 0.1, 0, 0],
    [0.1, 0.8, 0.1, 0, 0],
    [0.1, 0.8, 0.1, 0, 0]
    })

注意,假如y_true:[1, 2, 4, 4],还是看做三类:
y_pred:

[0.05, 0.95, 0,0],
[0.1, 0.8, 0.1,0],
[0.1, 0.8, 0.1,0],
[0.1, 0.8, 0.1,0]

 

 

 

在搭建深度学习模型,构建损失函数经常用到交叉熵函数,同时用到SparseCategoricalCrossentropy。

 

m = tf.keras.metrics.SparseCategoricalCrossentropy()
m.update_state(
  [1, 2],
  [[0.05, 0.9, 0.05], [0.1, 0.8, 0.1]])

# y_true = one_hot(y_true) = [[0, 1, 0], [0, 0, 1]]
# logits = log(y_pred)
# softmax = exp(logits) / sum(exp(logits), axis=-1)
# softmax = [[0.05, 0.95, EPSILON], [0.1, 0.8, 0.1]]

# xent = -sum(y * log(softmax), 1)
# log(softmax) = [[-2.9957, -0.0513, -16.1181], [-2.3026, -0.2231, -2.3026]]
# y_true * log(softmax) = [[0, -0.0513, 0], [0, 0, -2.3026]]

# xent = [0.0513, 2.3026]
# Reduced xent = (0.0513 + 2.3026) / 2

print('Final result: ', m.result().numpy())  # Final result: 1.176

输出结果为Final result: 1.2039728。

loss = 0
j = [[0,1,0],[0,0,1]]
z = [[0.05, 0.9, 0.05], [0.1, 0.8, 0.1]]
z = np.log(z)
for i in range(2):
    print(j[i])
    print(np.log(np.exp(z[i][0])/(np.exp(z[i][0])+np.exp(z[i][1])+np.exp(z[i][2]))))
    
    loss = loss + j[i][0]*np.log(np.exp(z[i][0])/(np.exp(z[i][0])+np.exp(z[i][1])+np.exp(z[i][2])))+\\
            j[i][1]*np.log(np.exp(z[i][1])/(np.exp(z[i][0])+np.exp(z[i][1])+np.exp(z[i][2])))+\\
            j[i][2]*np.log(np.exp(z[i][2])/(np.exp(z[i][0])+np.exp(z[i][1])+np.exp(z[i][2])))
       
    
#     loss = loss+0*np.log(np.exp(i[0])/(np.exp(i[0])+np.exp(i[1])+np.exp(i[2])))/3+\\
#                                               1*np.log(np.exp(i[1])/(np.exp(i[0])+np.exp(i[1])+np.exp(i[2])))/3+\\
#         1*np.log(np.exp(i[2])/(np.exp(i[0])+np.exp(i[1])+np.exp(i[2])))/3
loss/2

对上面的结果取负数,得到与上面相同的结果。

以上是关于SparseCategoricalCrossentropy的主要内容,如果未能解决你的问题,请参考以下文章