nn.Softmax(dim) 的理解

Posted

tags:

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

参考技术A     使用pytorch框架进行神经网络训练时,涉及到分类问题,就需要使用softmax函数,这里以二分类为例,介绍nn.Softmax()函数中,参数的含义。

1. 新建一个2x2大小的张量,一行理解成一个样本经过前面网络计算后的输出(1x2),则batch_size是2。

                import numpy as np

                import torch

                import torch.nn as nn

                a = np.array([[1.5, 6.7],[6.8, 3.4]])

                b = torch.from_numpy(a)

2. 下面调用nn.Softmax(dim),dim分别为0,1,看看结果是什么样子

                f = nn.Softmax(dim = 0)

                c = f(b)

    结果: tensor([[0.0050, 0.9644], [0.9950, 0.0356]], dtype=torch.float64)

    可以发现,是每一列和为1.

                f = nn.Softmax(dim = 1)

    结果:tensor([[0.0055, 0.9945],  [0.9677, 0.0323]], dtype=torch.float64)

    可以发现是每一行和为1

所以,当nn.Softmax的输入是一个二维张量时,其参数dim = 0,是让列之和为1;dim = 1,是让行之和为1。

若nn.Softmax的输入是三维张量时,dim的取值就变成了0,1,2,那又是代表什么意思呢,看下面的例子。

a = np.array([[[1.5, 6.7, 2.4],

              [6.8, 3.4, 9.3]],

              [[3.1, 6.5, 1.9],

              [8.9, 1.2, 2.5]]])

我们把a换成一个三维数组,大小是2x2x3,可以看成是2个2x3大小的输入。

这时,我们定义Softmax函数的dim为0,则结果是:

tensor([[[0.1680, 0.5498, 0.6225],

        [0.1091, 0.9002, 0.9989]],

        [[0.8320, 0.4502, 0.3775],

        [0.8909, 0.0998, 0.0011]]], dtype=torch.float64)

可以发现,0.1680+0.8320 = 1, 0.5498+0.4502 = 1,即dim = 0,是让两个2x3数据的对应位置和为1.

使dim=1,结果是:

tensor([[[0.0050, 0.9644, 0.0010],

        [0.9950, 0.0356, 0.9990]],

        [[0.0030, 0.9950, 0.3543],

        [0.9970, 0.0050, 0.6457]]], dtype=torch.float64)

可以发现,0.0050+0.9950 = 1,0.9644+0.0356 = 1,即dim = 1,是让张量每个2x3数据自己的列之和为1.

使dim=2,就是让张量每个2x3数据自己的行之和为1.

tf.nn.softmax_cross_entropy_with_logits

函数功能: 计算 logits 与 labels 的 softmax 交叉熵.

函数定义

def softmax_cross_entropy_with_logits(_sentinel=None, # pylint: disable=invalid-name
                                      labels=None,
                                      logits=None,
                                      dim=-1, name=None)                              

参数详解:

  1. # pylint: disable=invalid-name 作用是关闭该行代码中告警消息
  2. _sentinel:该参数为内部使用,实际运用中不会使用。目的是占据函数参数的第一个位置,让我们不能通过位置传递labels 和 logits,而是使用关键字传递参数,避免混淆。原理是:实际使用时_sentinel不用传入该参数,所以我们想要通过位置传递 labels 和 logits 时,实际上参数传递情况为传给了 _sentinel, labels。函数内部检查 logits没有值传进来,就会报错。
  3. labels: 实际标签
  4. logits: 对数几率,需要注意的是这个函数内部自动计算 softmax,然后再计算交叉熵代价函数,也就是说 logits 必须是没有经过 tf.nn.softmax 函数处理的数据,否则导致训练结果有问题。

notice!!! Measures the probability error in discrete classification tasks in which the
classes are mutually exclusive (each entry is in exactly one class). For
example, each CIFAR-10 image is labeled with one and only one label: an image
can be a dog or a truck, but not both.

执行步骤

具体的执行流程大概分为两步:

第一步:
是先对网络最后一层的输出做一个softmax,这一步通常是求取输出属于某一类的概率,对于单样本而言,输出就是一个 num_classes 大小的向量([Y1,Y2,Y3...]其中Y1,Y2,Y3...分别代表了是属于该类的概率)

第二步:
softmax 的输出向量[Y1,Y2,Y3...]和样本的实际标签做一个交叉熵,公式如下:

其中指代实际的标签中第 i 个的值(用mnist数据举例,如果是3,那么标签是[0,0,0,1,0,0,0,0,0,0],除了第4个值为1,其他全为0)
就是softmax的输出向量[Y1,Y2,Y3...]中,第i个元素的值
显而易见,预测越准确,结果的值越小(别忘了前面还有负号),最后求一个平均,得到我们想要的loss

注意!!!这个函数的返回值并不是一个数,而是一个向量,如果要求交叉熵,我们要再做一步tf.reduce_sum操作,就是对向量里面所有元素求和,最后才得到,如果求loss,则要做一步tf.reduce_mean操作,对向量求均值!

tf.nn.sparse_softmax_cross_entropy_with_logits

tf.nn.sparse_softmax_cross_entropy_with_logits(_sentinel=None, labels=None, logits=None, name=None)

这个函数与上一个函数十分类似,唯一的区别在于labels. labels的每一行为真实类别的索引

以上是关于nn.Softmax(dim) 的理解的主要内容,如果未能解决你的问题,请参考以下文章

tf.nn.softmax 分类

tf.nn.softmax_cross_entropy_with_logits

暗淡的 PyTorch softmax

如何在 softmax 分数中添加阈值

TensorFlow 的softmax实例理解

tensorflow log_softmax tf.nn.log(tf.nn.softmax(predict)) tf.nn.softmax_cross_entropy_with_logits