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)=–x∑XP(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(j∑nexj)
其中,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 参数可以指定应用于输出结果的计算方式,例如求均值、求和等。