MindSpore:损失函数nn.SoftmaxCrossEntropyWithLogits 解析

1. 关于Softmax

机器学习中有一个经典的方法:逻辑回归(Logistic Regression)。它属于一种有监督学习(Supervised Learning)方法。 逻辑回归输出的范围为0-1的值,表示概率,并依据概率的大小将样本归类,其中包括二分类问题与多分类问题。二分类逻辑回归模型输出一个值,该值用于表示样本属于其中一类的概率,多分类逻辑回归模型的输出结果为所有类别的概率分布。
在多分类深度神经网络中,在输出层加上Softmax,使得输出结果为0~1的向量,合为1,表示一种概率分布。此时概率最大的项作为分类预测的类别。Softmax便是沿用了逻辑回归的方法。

详细内容可参考:二分类逻辑回归与多分类逻辑回归的公式推导

2. 交叉熵

交叉熵(Cross Entropy) 本质上是用来衡量两个概率分布的相似性:

“… the cross entropy is the average number of bits needed to encode data coming from a source with distribution p when we use model q …”

— Page 57, Machine Learning: A Probabilistic Perspective, 2012.

交叉熵可以用来评估两个概率事件P和Q的相似性计算,公式如下

H(P,Q) = – \sum_x^X P(x) * log(Q(x))H(P,Q)=xXP(x)log(Q(x))

3. 分类任务损失函数

分类任务的损失函数,就是计算输出结果的预测分类与给定标签的误差,该误差越小越好。简单来说,对于二分类任务,如果给定的标签是1,则模型的输出值越接近1越好;若标签为0,则模型输出值越接近于0越好。换句话说,若标签为1,则最大化概率P(y_i =1)P(yi=1)。

交叉熵(Cross Entropy)可以衡量两个概率分布之间的距离的,Softmax能把一切转换成概率分布。那么自然二者一起使用可以用于分类任务的损失函数。 根据交叉熵的定义,由于一个样本只有一个标签,即给定标签只存在一个P(x)=1P(x)=1,其他值为0,不难得出交叉熵损失函数计算公式:

loss(x, c) = -log(\frac{e^{x_c}}{\sum_j^ne^{x_j}}) = -x_c + log({\sum_j^ne^{x_j}})loss(x,c)=log(jnexjexc)=xc+log(jnexj)

其中,n表示分类标签的个数,x为长度n的向量,表示预测每个标签的概率值,c是真实标签对应的编号位置,取值范围[0,n-1]。

4. nn.SoftmaxCrossEntropyWithLogits的使用

SoftmaxCrossEntropyWithLogits接口就是分类任务的交叉熵损失函数实现,接口参数说明见官方文档

下面介绍如何使用SoftmaxCrossEntropyWithLogits。

  • sparse=Fasle,表示输入参数labels与输入参数shape相同,给出了每个label对应的值。

    from mindspore import Tensor, nn
    import numpy as np
    import mindspore
    x = Tensor(np.array([[1, 2, 3]]),mindspore.float32)
    y1 = Tensor(np.array([[0, 1, 0]]), mindspore.float32)
    loss_false = nn.SoftmaxCrossEntropyWithLogits(sparse=False)
    
    print("x shape:", x.shape)
    print("y1 shape:", y1.shape)
    out1 = loss_false(x, y1)
    
    print("sparse false:", out1)
    
    def softmax_cross_entropy(x, c):
        exps = np.exp(x)
        return -x[c] + np.log(np.sum(exps))
    
    x = np.array([1,2,3])
    c = 1
    out3 = softmax_cross_entropy(x, c)
    print("numpy:", out3)
    

    输出结果如下

    x shape: (1, 3)
    y1 shape: (1, 3)
    sparse false: [1.4076059]
    numpy: 1.4076059644443801
    
  • sparse=true时,输入y是一维,表示真标签对应的位置

    from mindspore import Tensor, nn
    import numpy as np
    import mindspore
    
    x = Tensor(np.array([[1, 2, 3]]),mindspore.float32)
    y2 = Tensor(np.array([1]), mindspore.int32) # 编号1标签为真
    loss_true = nn.SoftmaxCrossEntropyWithLogits(sparse=True)
    print("x shape:", x.shape)
    print("y2 shape:", y2.shape)
    out2 = loss_true(x, y2)
    print("sparse true:", out2)
    

    输出结果:

    x shape: (1, 3)
    y2 shape: (1,)
    sparse true: [1.4076059]
    

总结
1、由于数据批处理的原因,接口参数logits只支持二维输入,第一维度表示的是batch size;

2、sparse 参数取不同的值,对输入labels的shape和type有不同的要求;

3、reduction 参数可以指定应用于输出结果的计算方式,例如求均值、求和等。

posted @ 2022-08-11 17:00  Skytier  阅读(201)  评论(0编辑  收藏  举报