皮皮网

【源码有版权嘛】【jquery源码素材】【无为麻将源码】torchsoftmax源码

2024-11-20 20:26:39 来源:Android 源码. 编译时间

1.nn.Softmax(dim) 的理解
2.pytorch算子的源码cuda实现——expand,where,softmax
3.基于pytorch的二分类、多分类、源码多标签等问题总结
4.请问用gumbel-softmax的源码时候,怎么让softmax输出的概率分布
5.一文看懂如何实现softmax分类器(内附完全代码)
6.DisenKGAT论文代码精读

torchsoftmax源码

nn.Softmax(dim) 的理解

           使用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., 0.], [0., 0.]], dtype=torch.float)

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

                        f = nn.Softmax(dim = 1)

            结果:tensor([[0., 0.],  [0., 0.]], dtype=torch.float)

            可以发现是每一行和为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., 0., 0.],

                [0., 0., 0.]],

                [[0., 0., 0.],

                [0., 0., 0.]]], dtype=torch.float)

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

        使dim=1,结果是:

        tensor([[[0., 0., 0.],

                [0., 0., 0.]],

                [[0., 0., 0.],

                [0., 0., 0.]]], dtype=torch.float)

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

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

pytorch算子的cuda实现——expand,where,softmax

       算子的简单介绍

       orch.Tensor.expand() 是 PyTorch 中 Tensor 类的一个方法,用于扩展张量的源码维度。输入:input 是源码要扩展的张量,size 是源码源码有版权嘛一个元组,指定了要扩展的源码每个维度的大小。输出:返回一个新的源码张量,形状是源码 input 张量的形状扩展后的形状。例如,源码x 的源码形状假设为(2,1,5,1),x.expand(2,源码4,5,6) 表示希望将 x 扩展为(2,4,5,6)形状的数组,注意 expand 只能在原始形状扩张,源码并且是源码原始维度的长度为1的地方。

       torch.where() 是源码 PyTorch 中的一个函数,用于根据给定的条件从两个张量中选择元素。输入:condition, inputx, inputy。注意 condition, inputx, inputy 不要求形状保持一致。例如,condition=[2,1,1,1],inputx=[1,3,4,1],inputy=[1,2,4,2],这都符合要求,此时输出的形状应该是[2,3,4,2],换句话说,where 应该支持广播运算。

       一维情况的 expand 和 where

       对于一维向量来说,使用 expand 和 where 实现非常简单。对于 expand,我们可以写出伪代码。对于 where,我们也可以写出伪代码。

       高维数组的 expand

       对于高维数组而言,expand 需要考虑在哪个维度扩张。假设输入向量 input 的形状为 [公式],其中至少存在一个 [公式](这是因为 expand 只能在某个维度的长度为1的地方扩张)。假设经过 expand 输出以后 output 的形状为 [公式]。由于计算机存储高维数组仍然需要将数组拉平,弄成一维数组存储,因此我们需要获得高维数组拉平后的长度以及全局索引。例如,input[inputIdx]: inputIdx =[公式]。output[outputIdx]: outputIdx =[公式]。由此我们就可以直接获得 expand 的公式。假设 [公式],即扩张的维度 dim=1,此时对于 output 的任意一个元素,假设索引为 [公式],那么这个元素对应的取值就应该是 input 中索引为 [公式] 的元素。

       高维数组的 where 编程

       有了 expand 的经验之后,where 的jquery源码素材实现就相对容易理解了。在编写 expand 算子的过程中,核心内容是根据 outputIdx 反推得到 inputIdx。同样地,我们可以根据 outputIdx 计算出 inputxIdx, inputyIdx, conditionIdx,然后直接计算即可。

       一维向量的 softmax 介绍

       softmax 的实现相对复杂。这里本人暂时只能实现一维向量的 softmax。假设输入是 x,输出是 y,其中 [公式]。在处理过程中,为了避免指数变化导致溢出,首先需要计算出向量 x 的最大值 [公式],然后做一次变换 [公式],将变换以后的数组记录为 [公式],从而得到 [公式]。

       softmax 的实现可以分解为三步:

       遍历向量 x,计算得到 M,也就是一个 max 规约操作。

       更新向量 x,其中 [公式],计算 [公式],也就是一个 sum 规约。

       得到向量 y,其中 [公式]。

       向量的 sum 规约

       softmax 涉及到两次规约,这里我们先介绍使用的规约策略。我们先用 sum 规约介绍,其实 max 规约几乎如出一辙。

       交叉配对规约:reduce=0

       向量长度是 size(假设 size 是 2 的幂次方),交叉配对的原理是不断将奇数位置的元素加到偶数位置,最终将所有元素的和存放在起始位置。

       以代码举例说明,这里重点说明第 行的代码。定义了一个数组 tmp,其中 __shared__ 关键字表示这个数组放在共享内存中,以及 tmp 数组面对当前线程块中的所有线程都是共享的。对于每个线程块来说,tmp 存储的是该线程块每个线程对应的数据。__syncthreads() 在 GPU 端做一个同步,确保所有线程的数据都赋值到了 tmp。重点来看 行以后的代码。

       以图为例,blockDim=(8,1,1), gridDim=(4,1,1),一共有 个线程,blockDim.x=8。考虑第 行这个循环。当 strip=1 时,threadIdx.x%2 == 0,则 threadIdx.x 有 0,无为麻将源码2,4,6 满足条件。当 threadIdx.x=0 时, 行代码就是 tmp[0] += tmp[1],类似地,成功将数据从 8 个位置转移到了 4 个位置,然后继续修改 strip=2,4,最后将所有元素的和转移到 tmp[0] 即可。最后将 tmp[0] 的数据放到 result[blockIdx.x] 中,也就是说 result 的每个元素存储的都是对应某个线程块内所有元素的和。最终结果全在 result 数组中,那么我们就可以推断出 result 的长度应该是 ceil(num_rows / BLOCK_DIM),其中 ceil 表示向上取整,num_rows 是向量的长度。

       交叉配对规约的特点是规约过程类似于一个二叉树,每次都把奇数位置的元素添加到偶数位置,架构很简单,但具体每一次规约的数据访问却是跳跃的。

       交错配对规约:reduce=1

       分析后面的规约代码,当 strip=4 时,threadIdx.x < 4,就有 threadIdx.x=0,1,2,3 满足条件。当 threadIdx.x=0 时,就有 tmp[0] += tmp[4],tmp[1] += tmp[5],tmp[2] += tmp[6],tmp[3] += tmp[7]。这种做法的好处是每次规约数组的访问都是连续的,可以减少访存开销。后面的数值实验也证明这种并行策略确实加速效果更好。

       shuffle warp:reduce=2

       这种做法的原理比较复杂,这里本人解释的不一定准确。首先声明了一个长度为 的共享内存数组 tmp,这个 实际上是线程的 warp,GPU 线程的设计是每 个线程为一组,称为一个线程簇 warp,我们的一维线程块的 BLOCK_DIM 每隔 个线程做一个切分。

       现在我们进一步考虑线程块内部的线程,对于某个线程块里面的某一个 warp 而言,这里面的 data 其实是线程私有变量,但是 data += __shfl_down_sync(0xffffffff, data, ) 的意思表示不同线程之间的 data 其实可以通过某种特殊方式相互读取累加的。该 warp 有 个线程,第一次累加的原则是,第 0 个线程和第 个线程相加,...,第 个线程和第 个线程数据相加,这样就把 warp 内 个线程的数据全部累加到了前 个线程。后面几句代码也是类似的,最后把该 warp 的jira 源码安装 个线程数据累加到第一个线程。所以当 threadIdx.x%==0 时,表示 threadIdx.x 这个线程存储了该 warp 中 个线程数据的累加和。所以 tmp[threadIdx.x/] 位置存储的就是每一个 warp 所有线程数据的和。

       现在需要把 tmp 这 个数据类似原则累加,因此借助于 threadIdx.x 可以直接读取 tmp 的数据,但是 threadIdx.x 的范围太大,我们不要借助那么多所以需要做一个判断以免访问 tmp 越界。最后将 tmp 的数据做完规约以后得到的 data 就保存了当前线程块的所有线程数据的累加和。而我们线程块的总数是 gridDim.x,blockIdx.x 的范围就是 0 到 gridDim.x-1,所以 result 的长度还是 gridDim.x,每个元素保存了对应线程块所有数据的累加和。

       对于某个 warp,为什么第一次规约是以 为距离累加呢?实际上,从线程的角度来看,比如我们考虑最前面的 个线程,也就是 block 中第一个 warp,0 号线程一直到 号线程做累加的时候读取的数据正好是相邻的 个元素,累加的时候读取的是后面 个元素。不管怎么累加,不同线程之间读取的数据总数相邻,这样就保证了数据的局部性,所以访问时间进一步缩短。

       把这些并行策略封装在 pre_dot 以后,后面仍然是写一个 cuda_dot 函数将 result 的结果传回 CPU 的 host_z,然后再串行求 host_z 的元素和。特别注意的是此时调用需要使用 pre_dot<<>>(cuda_x, cuda_y, cuda_z, result),share_size 表示申请的共享内存大小,这里我一般使用 BLOCK_DIM×sizeof(double)。

       向量的 max 规约

       前面两种规约方式对于 max 来说是一样的,稍微有一点区别的是 reduce=2 这种抽牌规约策略。有兴趣的同学可以查看一下 __shfl_down_sync 函数的用法就知道这个是怎么回事了。

       初级 softmax

       有了上面的 sum 和 max 规约策略,我们可以给一个初级的 softmax 算法,步骤如下:

       1:先对数组 input 做一个 max 规约,此时会得到一个 result 数组,这个数组的长度是 ceil(N/BLOCK_DIM),其中 N 是数组的长度,BLOCK_DIM 是线程块的大小。观察向量的 max 规约可以发现这个规约其实只是对向量做了切割,切割成了 ceil(N/BLOCK_DIM),每一份长度是 BLOCK_DIM。而这个向量 result 的长度正好是 ceil(N/BLOCK_DIM),其中 result 的每个元素存储的是对应的那份长度为 BLOCK_DIM 的数据的 max,但是这个不是全局 max,因此我们需要把向量 result 从 GPU 搬运到 CPU,然后通过一个串行 for 循环来遍历 result,由此来获得全局 max,假设是 M。

       2:然后我们做一个更新向量 x,网上祭拜源码其中 [公式],计算 [公式],此时这个做 sum 规约,仍然是把向量切割成了 ceil(N/BLOCK_DIM),每一份长度是 BLOCK_DIM,并且每份长度为 BLOCK_DIM 的数据的 sum 被存储到了 result 的对应位置(result 可以多次利用,不需要重新定义新的数组)。然后还是需要把向量 result 从 GPU 搬运到 CPU,然后通过一个串行 for 循环来遍历 result,由此来获得全局 sum,假设是 S。

       3:得到向量 y,其中 [公式]。这个过程比较无聊,不赘述。

       综合上面信息,我们发现这个初级的 softmax 的数据来来回回从 CPU 和 GPU 移动了好几次,效率不太高。

       高级 softmax

       我们回顾一下上面的步骤 1 和 2,我们发现生成的 result 需要从 GPU 移动到 CPU,然后还要串行遍历 result 计算全局结果,但我们可以类似在 GPU 端规约 result,依次来减少数据移动,增大速度。经过本人测试,这个想法完全可行,可以称之为二次规约:

       观察上面这段代码,本人定义了一个 girdmax 函数来实现 result 的规约,这个过程和 reduce=1 的规约策略一模一样,经过这样规约以后,全局的 max 将会被存储到 result[0],也就是 result 向量的开头元素。

       类似地,我们继续这么做,这个 gridsum 会将 result 的所有元素都加载到 index=0,也就是开头位置,这样就得到了我们的高级 softmax。

       高维数组的 softmax 目前还没调节好代码,有兴趣的同学可以自己试一试,完整代码参考本人博客。

       本人在下一篇博客给出了一个 softmax 算子融合的介绍,有兴趣可以参考。

基于pytorch的二分类、多分类、多标签等问题总结

       基本照搬 Honda:基于pytorch的二分类、多分类、多标签等问题总结;其中加了一些自己看的时候的思考。

       1. Sigmoid函数和Softmax函数

       1.1 Sigmoid

       Sigmoid函数常用于多标签分类问题,即存在多个正确答案的情况,如胸部X光检查、住院等。在构建分类器时,使用Sigmoid函数处理各个原始输出值,以解决存在多个正确答案的问题。

       1.2 Softmax

       Softmax函数适用于多类别分类问题,即只有一个正确答案的情况,如手写数字、鸢尾花等。在构建分类器时,使用Softmax函数处理各个原始输出值,以解决只有唯一正确答案的问题。

       2. Pytorch中的nn.sigmoid和nn.softmax

       2.1 nn.Softmax

       Softmax函数的表达式为:[公式]

       nn.Softmax可以用于激活函数或多分类,其中分类模型如下:

       2.2 nn.LogSoftmax

       相对于nn.Softmax,nn.LogSoftmax对输出进行了log操作,公式如下:[公式]

       2.3 nn.CrossEntropyLoss

       nn.CrossEntropyLoss用于计算交叉熵,适用于二分类和多分类任务。

       2.4 torch.nn.Sigmoid 和 BCELoss()

       Sigmoid公式为:[公式]

       BCELoss()用于二分类,计算方式如下:[公式]

       对于多标签分类,将Sigmoid和BCELoss整合,即BCEWithLogitsLoss()。

       3. 二分类中的nn.sigmoid和nn.softmax

       3.1 区别

       Sigmoid函数和Softmax函数在二分类问题上是等价的。Sigmoid函数将数值压缩到(0,1)之间,得到的结果可以理解为分类成目标类别的概率。Softmax函数本身针对多项分布,当类别数是2时,它退化为二项分布。

       3.2 使用场景

       在二分类问题时,二者可以互换使用。对于多类别分类任务,通常使用Softmax。对于多标签分类任务,通常使用Sigmoid。

       4. 小思考

       在二分类问题中,使用softmax和sigmoid的结果是相同的。对于多类别分类,sigmoid可以用于多分类,但使用softmax更为合理。在多标签分类中,将问题拆解成多个二分类问题,使用sigmoid进行分类。

请问用gumbel-softmax的时候,怎么让softmax输出的概率分布

       在探讨使用gumbel-softmax时如何让softmax输出概率分布,可以参考pytorch中torch.nn.functional.gumbel_softmax的实现。

       具体操作中,当参数hard设置为True时,返回的结果是one-hot向量。其中,y_soft表示采样得到的概率分布,y_hard是基于此概率分布计算得出的one-hot向量。这里的detach()方法实际上将一个张量从计算图中移除,使其成为常量,以确保在反向传播时不会计算它的梯度。

       综上所述,gumbel-softmax通过构造一个数值上等同于one-hot向量的张量,但在反向传播过程中梯度沿y_soft返回,实现了一种在概率分布与one-hot向量间平滑过渡的方式。这种方式在处理离散概率分布时具有优势,能够提供更好的灵活性和稳定性。

一文看懂如何实现softmax分类器(内附完全代码)

       首先导入需要的包。

       设置小批量数目为,转换类型并生成迭代器,与线性回归的读取数据方法相似。

       初始化模型参数:每个图像有个特征值,网络输出为个类别,因此存在*个权重参数和个偏差参数。

       实现softmax运算,将其转换为非负数,每行元素之和为1。

       回顾tensor的按维度操作,定义softmax运算公式。

       将权重和偏差参数与输入数据相乘,得到输出结果。

       定义损失函数,使用torch.gather函数提取真实标签对应的预测概率。

       根据交叉熵函数公式计算损失值。

       计算分类准确率,从预测概率中找出最大概率对应的索引,与真实标签比较,计算准确率。

       优化算法选择小批量随机梯度下降。

       训练模型,调节迭代周期数和学习率获得分类更准确的模型。

       预测模型效果,训练五次后,损失值从0.减少到0.,准确率从0.提升到0.。

       完整程序包含以上步骤,实现softmax分类器。

DisenKGAT论文代码精读

       公式1:互信息

       解释:该公式定义了随机变量x和z之间的互信息。

       公式2:初始组件嵌入

       公式解释:- h^0_{ u,k}:实体u在第k个潜在空间中的初始嵌入。- σ:激活函数(例如ReLU或Sigmoid)。- W_k:用于第k个潜在空间的投影矩阵。- x_u:实体u的特征向量。

       对应代码文件:model.py文件:DisenLayer.py详细讲解总结

       公式3和4:组件级别交互

       公式解释:- m(v, k, r):从邻居v聚合的消息。- φ:组合操作符,可以是减法、乘法、交叉交互或循环相关。- h_{ v,k}:邻居v在第k个组件中的嵌入。- h_r:关系r的嵌入。- θ_r:关系r的投影矩阵。- W_r:关系r的投影矩阵。- diag(w_r):将向量w_r变成对角矩阵。

       对应代码文件:DisenLayer.py详细讲解总结

       如果您对某个具体部分有更详细的疑问或需要进一步的解释,请告诉我!

       公式5:注意力得分

       公式解释:- α_k(u, v, r):组件k中邻居v对于实体u的注意力得分,考虑关系r。- softmax:Softmax函数,用于归一化注意力得分。- (e^k_{ u,r})^T:实体u在关系r的第k个组件中的嵌入的转置。- e^k_{ v,r}:邻居v在关系r的第k个组件中的嵌入。

       对应代码文件:DisenLayer.py详细讲解总结

       公式6:组件聚合

       公式解释:- h^{ l+1}{ u,k}:实体u在第k个组件中的第l+1层嵌入。- σ:激活函数。- ∑:求和符号,用于聚合邻居信息。- N(u):实体u的邻居集合。- α_k(u, v, r):组件k中邻居v对于实体u的注意力得分。- φ:组合操作符。- h^l{ v,k}:邻居v在第k个组件中的第l层嵌入。- h^l_r:关系r的第l层嵌入。- θ_r:关系r的投影矩阵。

       对应代码文件:DisenLayer.py详细讲解

       ReLU激活函数,对应公式中的点积部分 (e^k_{ u,r})^T · e^k_{ v,r}。-alpha = softmax(alpha, edge_index_i, num_nodes=self.p.num_ent):对alpha进行softmax归一化,对应公式中的softmax。

       总结公式7:关系表示更新

       公式解释:- h^{ l+1}r:关系r的第l+1层嵌入。- W^l{ rel}:第l层的线性变换矩阵。- h^l_r:关系r的第l层嵌入。

       对应代码文件:DisenLayer.py详细讲解总结

       公式8:互信息正则化

       对应代码文件:model.py文件:model.py详细讲解

       .Tanh())

       总结公式9:KL散度

       公式解释:- L(h_{ u,i}, h_{ u,j}):KL散度损失。- D_KL:KL散度。- p(h_{ u,i} | h_{ u,j}):真实条件概率分布。- q_θ (h_{ u,i} | h_{ u,j}):变分条件概率分布,参数为θ。

       对应代码文件:model.py详细讲解总结

       公式:组件级别预测

       公式解释:- ψ_k(u, r, v):候选三元组(u, r, v)在第k个组件中的评分。- f:评分函数。- vec:向量化操作,将矩阵展平为向量。- h^L_{ u,k}:实体u在第k个组件中的第L层嵌入。- h^L_r:关系r的第L层嵌入。- star:卷积操作。- ω:卷积核。- W:线性变换矩阵。- h^L_{ v,k}:实体v在第k个组件中的第L层嵌入。

       对应代码文件:model.py详细讲解

       对应关系:-comb_emb:组合后的实体和关系嵌入,对应公式中的 f(h^L_{ u,k}; h^L_r)。- stack_inp:经过卷积操作的输入,对应公式中的 h^L_r star ω。- x:经过激活函数和线性变换后的嵌入,对应公式中的 f(vec(f(h^L_{ u,k}; h^L_r star ω)))W。

       if self.p.score_order == 'before': x = torch.einsum('bk,bkn->bn', [attention, x]) pred = torch.sigmoid(x) elif self.p.score_order == 'after': x = torch.sigmoid(x) pred = torch.einsum('bk,bkn->bn', [attention, x]) pred = torch.clamp(pred, min=0., max=1.0) return pred, corr

       总结公式:注意力评分

       公式解释:- β_k(u, r):组件k在给定关系r中的重要性。- softmax:Softmax函数,用于归一化注意力得分。- (h^L_{ u,k} circ θ_r)^T:实体u在关系r的第k个组件中的嵌入与关系权重的元素级乘积的转置。- h^L_r:关系r的第L层嵌入。

       对应代码文件:model.py详细讲解

       x = x.view(-1, self.p.num_factors, self.p.gcn_dim)

       总结

       如果您对某个具体部分有更详细的疑问或需要进一步的解释,请告诉我!

       公式:最终预测评分

       公式解释:

       对应代码文件:model.py详细讲解

       f(h^L_{ u,k}; h^L_r star ω))W)。

       if self.p.score_order == 'before': x = torch.einsum('bk,bkn->bn', [attention, x]) pred = torch.sigmoid(x) elif self.p.score_order == 'after': x = torch.sigmoid(x) pred = torch.einsum('bk,bkn->bn', [attention, x]) pred = torch.clamp(pred, min=0., max=1.0) return pred, corr

       总结公式:总体目标

       公式解释:- L:总损失函数。- B:批量大小。- N:知识图谱中的实体数量。- ∑_{ (u, r) ∈ batch}:对批次中的所有三元组(u, r)求和。- ∑_i:对所有候选实体i求和。- t_i:标签,表示三元组(u, r, v_i)是否为有效三元组。- log(ψ_{ final}(u, r, v_i)):最终预测评分的对数值。- λ:互信息正则化损失的权重。- L_mi:互信息正则化损失。

       对应代码文件:run.py详细讲解总结

       如果您对某个具体部分有更详细的疑问或需要进一步的解释,请告诉我!

NLP修炼系列之分类loss二分类、多分类与多标签分类loss损失函数

       本文将探讨二分类、多分类与多标签分类的区别与损失函数,详细分析softmax、log_softmax、CrossEntropyLoss 和 NLLLoss 四个函数的应用与对比,以深入理解它们之间的差异和用法。

       首先,我们需要了解基本概念:

       二分类:任务有两个类别,每个样本属于其中的一个,如新闻分为体育与非体育。

       多分类:任务有多个类别,每个样本属于一个类别,如新闻分类为体育、财经、其他。

       多标签分类:任务有多个类别,每个样本可以属于多个类别,如新闻可能同时属于体育、财经、教育。

       接下来,分析二分类任务:

       输出层仅有一个单元,使用sigmoid损失函数和二分类交叉熵损失。

       torch中提供两种二分类损失函数:BCELoss 和 BCEWithLogitsLoss。

       二者区别在于BCEWithLogitsLoss直接对最后的logits进行处理,不再需要sigmoid缩放。

       使用sigmoid+BCELoss或softmax+交叉熵实现。

       也可直接使用CrossEntropyLoss。

       多分类任务的处理方式:

       输出层单元数为类别数量,使用softmax损失函数和多分类交叉熵损失。

       标签转换为one-hot向量,表示每个类别的独热编码。

       实现代码包括softmax+nll_loss或直接使用CrossEntropyLoss。

       多标签分类任务:

       视为多个二分类任务,每个标签为独立的二分类问题。

       使用sigmoid+BCELoss进行实现,对每个标签进行单独评分。

       标签以one-hot编码形式表示,如[0,0,0,1,0,1,0,0,1]。

       实现代码包括sigmoid+BCELoss或直接使用BCEWithLogitsLoss。

       总结损失函数:

       激活函数将输出缩放到[0,1]。

       求对数操作计算输出的对数。

       累加求和计算损失。

       softmax、log_softmax、CrossEntropyLoss 和 NLLLoss 的对比:

       softmax/sigmoid:对应激活函数操作。

       log_softmax:完成激活函数与对数计算。

       nll_loss:对应损失计算的最后一步。

       CrossEntropyLoss:整合所有步骤。

       多分类交叉熵损失实现方法:

       三步实现:softmax+log+nll_loss。

       两步实现:log_softmax+nll_loss。

       一步实现:crossEntropyLoss。

       总结全文,本文详细介绍了二分类、多分类与多标签分类的区别,以及损失函数softmax、log_softmax、CrossEntropyLoss 和 NLLLoss 的对比,帮助读者理解这些函数在不同分类任务中的应用与区别。

pytorch多分类任务输出层使用softmax,该选择什么损失函数

       多分类任务中,通常在全连接层输出数据为batch_size*n_classes。此结构适配torch.nn.CrossEntropyLoss(),该函数内整合了softmax、log和NLLloss,故全连接层输出结果可直接接入此函数,实现交叉熵损失计算。函数中reduction参数有三种选择:'none'表示返回每个样本的交叉熵损失,'sum'表示返回每个样本损失的总和,'mean'表示返回平均交叉熵损失。

       若全连接层输出结果上先应用了torch.softmax(),则不宜再直接使用torch.nn.CrossEntropyLoss()。此时,需在应用softmax后,进行log操作并取对应位置结果计算损失。具体公式为:loss = torch.log(torch.softmax(results_fc, dim=1))[torch.arange(len(target), target].sum()。

       其中,results_fc为全连接层输出结果,target为真实标签。torch.softmax函数亦可用F.softmax替代。