pytorch二分类 pytorch分类器

2025-04-07 07:09 - 立有生活网

[损失函数]——交叉熵

输出结果如下:

在了解交叉熵之前我们需要关于熵的一些基本知识,可以参考我的上一篇 博客 [1] 。

pytorch二分类 pytorch分类器pytorch二分类 pytorch分类器


pytorch二分类 pytorch分类器


信息熵的定义为离散随机的出现概率 [2] 。当一个出现的概率更高的时候,我们认为该会传播的更广,因此可以使用信息熵来衡量信息的价值。

当一个信源具有多种不同的结果,记为:U1,U2,...,Un,每个相互,对应的概率记为:P1,P2,...,Pn。信息熵为各个方式概率的期望,公式为:

对于二分类问题,当一种发生的概率为p时,另一种发生的概率就为(1-p),因此,对于二分类问题的信息熵计算公式为:

相对熵(relative entropy),又被称为Kullback-Leibler散度(Kullback-leibler divergence),是两个概率分布间异的一种度量 [3] 。在信息论中,相对熵等于两个概率分布的信息熵的值。

相对熵的计算公式为:

其中 代表的真实概率, 代表的预测概率。例如三分类问题的标签为 ,预测标签为 。

因此该公式的字面上含义就是真实的信息熵与理论拟合的的香农信息量与真实的概率的乘积的的累加。[4]

当p(x)和q(x)相等时相对熵为0,其它情况下大于0。证明如下:

KL散度在 Pytorch 中的使用方法为:

此外,还要注意 log_target 参数,因为在计算的过程中我们往往使用的是log softmax函数而不是softmax函数来避免underflow和overflow问题,因此我们要提前了解target是否经过了log运算。

下面我们用一个例子来看看 torch.nn.KLDivLoss() 是如何使用的:

相对熵可以写成如下形式:

等式的前一项为真实的熵,后一部分为 交叉熵 [4] :

在机器学习中,使用KL散度就可以评价真实标签与预测标签间的异,但由于KL散度的项是个定值,故在优化过程中只关注交叉熵就可以了。一般大多数机器学习算选择交叉熵作为损失函数。

交叉熵在pytorch中可以调用如下函数实现:

其计算方法如下所示 [5] :

设batch size为4,待分类根据交叉熵的计算公式,loss的最终计算等式为:标签有3个,隐藏层的输出为:

经过 softmax 激活函数之后得到预测值:

softmax函数的输出结果每一行相加为1。

设这一个mini batch的标签为

根据交叉熵的公式:

代表真实标签,在真实标签中,除了对应类别其它类别的概率都为0,实际上,交叉熵可以简写为:

所以该mini batch的loss的计算公式为(别忘了除以batch size,我们求得的是mini batch的平均loss):

因此,我们还需要计算一次对数:

计算结果为:

运算结果和pytorch内置的交叉熵函数相同:

除了 torch.nn.CrosEntropyLoss() 函数外还有一个计算交叉熵的函数 torch.nn.BCELoss() 。与前者不同,该函数是用来计算二项分布(0-1分布)的交叉熵,因此输出层只有一个神经元(只能输出0或者1)。其公式为:

在pytorch中的函数为:

用一个实例来看看如何使用该函数:

输出结果为:

它是如何计算的呢,我们接下来一步步分析:

需要经过 sigmoid 函数得到一个输出

输出结果为:

然后我们根据二项分布交叉熵的公式:

得到 loss 的如下计算公式:

和pytorch的内置函数计算结果相同。

另外,需要注意的是, 当使用交叉熵作为损失函数的时候,标签不能为onehot形式,只能是一维的向量 ,例如,当batch size是5时,这一个batch的标签只能时[0,1,4,2,6]这样的形式。

pytorch神经网络跑不起来是数据集的问题吗

在不同的任务中,可能对准确率与召回率有不同的要求。本篇文章要讨论的问题是在模型已经训练完成后,如果在不重新训练模增加 ,类别1所对应的概率会增加,其它类别的概率则会降低。人为提升概率,会导致其预测正样本的概率增加,从而导致召回率的上升,其它类别的情况则相反。型的情况下,调整其预测的准确率与召回率。也就是说,将一个模型发布后,不同的使用者可以使用同一个模型去完整不同的任务。

1.Target 1 is out of bounds.,(1)分类问题中,dataset里数据处理后,label的范围必须是[0,class_num-1],这里的label会作为损失函数的target。(换一种说法,如对分类的结果有3种,cat、dog、bird,那么label也即loss_func的target的范围必须是[0,1,2])。注:nn.NLLoss貌似有一样的问题?(2)检查网络结构,一层的输出有几个

3.使用CrossEntropyLoss函数,我们的模型里面的一层全连接层的输出一般大于1,这时候dataset里的label必须是一个一维的LongTensor类型,不然会在下面进行训练时计算loss的时候报错1D target tensor expected, multi-target not supported;

4.expected scalar type Long but found Float,这个通样是在dataset定义的时候出现的,dataset的label的应该是一个一维tensor(如第3条所说),比如我是对数字分类,label就是1,2,3…等具体的数字,在训练的时候,使用CrossEntropyLoss函数的时候它会将一维的tensor转换成one-hot进行计算损失。

各种熵,条件熵,KL

参考《统计学习方法》李航

通俗理解信息熵 - 忆臻的文章 - 知乎

熵表示一个的信息量。

一般认为,如果一个的随机性很大,那么这个的熵很大。

如果一个比较确定,那么这个的熵很小。

一个【具体】的信息量应该是随着其发生概率而递减的,且不能为负。

对于一个二分类,概率为[0.9999,0.0001],基本就是个随机性很小的,对应它的熵应该很小。

反之,如果这个二分类概率为[0.5,0.5],比如抛硬,正反概率不多,基本很难确定,那么它的熵很大。

设x是一个取有限个值的离散随机变量,其概率分布是:

则随机变量x的熵定义为: ,若 则定义0log0=0。

在这里,一个分布的熵可以看作是 具体信息量的期望 。(即对各个的信息量依照概率加权)。

注意:得到的熵与x无关,只与概率分布有关。

所以我们可以得到二分类熵的函数图:

H(Y|X) : 是已知随机变量X的前提下,随机变量Y的不确定性。

即,已知X的取值情况,则先求x确定下的信息量,H(Y|X= ),再对信息量求一个期望。

信息增益:

知道随机变量X,使随机变量Y的信息,不确定性减少的程度。

g(D,A) = H(D) - H(D|A)

信息增益比:

参考花书《深度学习》第三章

如果我们对同一个随机变量x,有两个单独的概率分布,P(x)和Q(x),我们可以使用KL散度,来 衡量这两个分布的异 。

p在前,表示以p为基准,去考虑p和q相多少

信息量的值:

表示分布异,再×概结果为:率得到期望。

性在使用过程中, reduction 一般设置为 batchmean 这样才符合数学公式而不是 mean ,在以后的版本中 mean 会被替换掉。质:

KL 散度有很多有用的性质,最重要的是它是 非负 的。 KL 散度为 0 当且仅当P 和 Q 在离散型变量的情况下是相同的分布(此时P(x)/Q(x)=1) ,或者在连续型变量的情况下是 ‘‘几乎处处’’ 相同的。因为 KL 散度是非负的并且衡量的是两个分布之间的异,它经常被用作分布之间的某种距离。然而,它并不是真的距离因为它不是对称的:对于某些 P 和 Q,

pytorch对应损失函数:

示例

常用的损失函数。不具有对称性。H(P , Q)≠H(Q , P) 且非负。

二分类问题的交叉熵损失函数的本质是设数据服从以模型输出为参数的伯努利分布的极大似然估计。(为什么交叉熵(cross-entropy)可以用于计算代价? - Chris的回答 - 知乎 )

实际计算:

可以直接 认为是这样的一个概率和,

如果是多分类,设真实标签[0,1,2,1,1,2,1]

那就是

因为在实际运算中,目标label已确定,对应概率值就是1

PyTorch神经网络层拆解

前半部分就是 的熵,后半部分就是我们的交叉熵:

本文将拆解常见的PyTorch神经网络层,从开发者的角度来看,这些神经网络层都是一个一个的函数,完成对数据的处理。

:CLASS torch.nn.Flatten( start_dim=1 , end_dim=- 1 ) ,将的输入一维化,常用在从卷积层到全连接层的过渡。需要注意的是,Flatten()的默认值start_dim=1,即默认数据数据的格式是[N,C,H,W]第0维度为Batch Size,不参与Flatten。后面的CHW全部展平为一维。

Linear类有两个属性:

第三 ,CLASS torch.nn.Conv2d (in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros', dev=None, dtype=None),卷积层,常用于提取图像特征,+RELU+MaxPooling已经成为一种常见的特征提取作了。

需要注意的是:要求数据输入格式为:[N, Cin, Hin, Wout],Cin是输入数据Tensor的通道数量,输出为[N, Cout, Hout, Wout],Cout为本层的卷积个数。Hout和Wout计算公式如下所示:

范例torch.nn.KLDivLoss() 会传入两个参数 (input, target) , input 是模型的预测输出, target 是样本的观测标签。程序:

总结:

pytorch分类神经网络如何实现五折交叉验证

把输入的数据先进行sigmod,然后再计算loss,应用时,通常还有个backward()

1、首先将所有pytorch分类神经网络数据集分成5份,不重复地每次取其中一份做测试集。

2、其次用其余四份做训练集训练模3、将5次的MSE取平均得到的MS进行,即可实现五折交叉验证。型,之后计算该模型在测试集上MSE。

【BCELoss】pytorch中的BCELoss理解

首先输入是:

BCELoss:Binary Cross Entropy Loss,二值交叉熵损失,适用于0/1二分类。

定义:

计算公式 是 “ -ylog(y^hat) - (1-y)log(1-y^hat) ”,其中y为gt,y_hat为预测值。这样,当gt为0的时候,公式前半部分为0,y^hat 需要尽可能为0才能使后半部分数值更小;当gt为1时,后半部分为0,y^hat 需要尽可能为1才能使前半部分的值更小,这样就达到了让y^hat尽量靠近gt的预期效果。

这要求输出必须在0-1之间,所以为了让网络的输出确保在0-1之间,一般都会加一个Sigmoid。更具体一点来说,使用BCELoss的话只需要网络输出一个即可,不像CE Loss(Cross Entropy Loss)那样,往往是有n_class个类就需要网络最终输出n_class个。

分类任务中

CE因为需要用在多分类上,所以计算公式就变成了sum(-ylog(y^hat))。这个函数实际上只是在对相应gt=1的那个的值做约束,希望这一点的输出能尽量为1;而其他原本gt为0的因为y=0,在计算到sum中的时候无论其相应输出是多少都没有关系。

那这是不是意味着CE的公式还有漏洞呢?话虽这么说,但其实是因为我们忘记了CE之前还有Softmax这个函数,这个函数会让输入的n_class个中大的更大,小的更小,并且可以确保最终所有的输出的总和为1,这样一来只要对应gt=1的那个输出足够靠近1,其他的自然输出就会趋近于0了。

分割任务中

BCE和CE的另一个区别是,BCE只需要输出一个通道,而CE需要输出n_class个通道。

BCE虽然总是用来学习0/1分布,即二分类问题,但不是0/1两个数,只要在0~1之间的数也都能学习。原因从BCE的公式聊起:

实例:

输出:

Pytorch-交叉熵

pytorch中有计算交叉熵损失的接口,即 F.cross_entropy() ,不过该接口包含了Softmax函数、log函数、交叉熵损失函数。也就是说 F.cross_entropy() = F.softmax() + torch.log() + F.nnl_loss() 。即使如此,也要使用 F.cross_entropy() ,不仅是因为它简单,更因为它能保证数值稳定。

一条信息的信息量大小和它的不确定性有很大的关系 。一句话如果需要很多外部信息才能确定,我们就称这句话的信息量比较大。比如你听到“云南西双版纳下雪了”,那你需要去看天气预报、问当地人等等查证(因为云南西双版纳从没下过雪)。相反,如果和你说“人一天要吃三顿饭”,那这条信息的信息量就很小,因为这条信息的确定性很高。

那我们就能将 的信息量定义如下(其中 表示 发生的概率):

信息量是对于单个来说的 ,但是实际情况一件事有很多种发生的可能,比如掷有可能出现6种情况,明天的天气可能晴、多云或者下雨等等。 熵是表示随机变量不确定的度量,是对所有可能发生的产生的信息量的期望 。公式如下:

的曲线如下:

结合熵的公式(2)以及 曲线,当这些所有可能发生的概率比较小(接近0)或者比较大(接近1)时,熵的值会比较小;如果发生的概率既远离0也远离1时,熵的值就会比较大。

例如,如下三组比较:

1)概率均等,[0.0, 0.0, 0.0, 0.0],熵为2;

2)概率比较靠近0或者1,[0.1, 0.1, 0.1, 0.7],熵为1.3568;

3)概率极其靠近0或者1,[0.001, 0.001, 0.001, 0.999],熵为0.0313.

熵的一种比较特殊的情况就是掷硬 ,只有正、反两种情况,该种情况(二项分布或者0-1分布)熵的计算可以简化如下:

其中, 表示正面概率。

相对熵又称KL散度,用于衡量对于同一个随机变量 的两个分布 和 之间的异 。在机器学习中, 常用于描述样本的真实分布 ,例如[1,0,0,0]表示样本属于类,而 则常常用于表示预测的分布 ,例如[0.7,0.1,0.1,0.1]。显然使用q(x)来描述样本不如 准确, 需要不断地学习来拟合准确的分布 。

KL散度的公式如下:

KL散度的值越小表示两个分布越接近。

我们将KL散度的公式进行变形,得到:

机器学习中,我们常常使用KL散度来评估predict和label之间的别,但是由于KL散度的前半部分是一个常量,所以我们常常将后半部分的交叉熵作为损失函数,其实二者是一样的。

交叉熵代价函数(Cross-entropy cost function)是用来衡量人工神经网络(ANN)的预测值与实际值的一种方式。与二次代价函数相比,它能更有效地促进ANN的训练。在介绍交叉熵代价函数之前,本文先简要介绍二次代价函数,以及其存在的不足。

ANN的设计目的之一是为了使机器可以像人一样学习知识。人在学习分析新事物时,当发现自己犯的错误越大时,改正的力度就越大。比如投篮:当运动员发现自己的投篮方向离正确方向越远,那么他调整的投篮角度就应该越大,篮球就更容易投进篮筐。同理, 我们希望:ANN在训练时,如果预测值与实际值的误越大,那么在反向传播训练的过程中,各种参数调整的幅度就要更大,从而使训练更快收敛。 然而,如果使用二次代价函数训练ANN,看到的实际效果是,如果误越大,参数调整的幅度可能更小,训练更缓慢。

在实验1中,随机初始化参数,使得次输出值为0.82(该样本对应的实际值为0);经过300次迭代训练后,输出值由0.82降到0.09,逼近实际值。而在实验2中,次输出值为0.98,同样经过300迭代训练,输出值只降到了0.20。

从两次实验的代价曲线中可以看出: 实验1的代价随着训练次数增加而快速降低,但实验2的代价在一开始下降得非常缓慢;直观上看,初始的误越大,收敛得越缓慢。

其实,误大导致训练缓慢的原因在于使用了二次代价函数。二次代价函数的公式如下:

其中, 表示代价, 表示样本, 表示实际值, 表示输出值, 表示样本的总数。为简单起见,同样一个样本为例进行说明,此时二次代价函数为:

目前训练ANN最有效的算法是反向传播算法 。简而言之,训练ANN就是通过反向传播代价,以减少代价为导向,调整参数。参数主要有:神经元之间的连接权重 ,以及每个神经元本身的偏置 。调参的方式是采用梯度下降算法(Gradient descent),沿着梯度方向调整参数大小。 和 的梯度推导如下:

其中, 表示神经元的输入, 表示激活函数。从以上公式可以看出, 和 的梯度跟激活函数的梯度成正比,激活函数的梯度越大, 和 的大小调整得越快,训练收敛得就越快。而神经网络常用的激活函数为sigmoid函数,该函数的曲线如下所示:

如图所示, 实验2的初始输出值(0.98)对应的梯度明显小于实验1的输出值(0.82),因此实验2的参数梯度下降得比实验1慢。这就是初始的代价(误)越大,导致训练越慢的原因。 与我们的期望不符,即:不能像人一样,错误越大,改正的幅度越大,从而学习得越快。

可能有人会第二 , CLASS torch.nn.Linear( in_features , out_features , bias=True , dev=None , dtype=None ) ,Linear又叫全连接层,TensorFlow里面叫Dense,主要用于分类。说,那就选择一个梯度不变化或变化不明显的激活函数不就解决问题了吗?那样虽然简单粗暴地解决了这个问题,但可能会引起其他更多更麻烦的问题。而且,类似sigmoid这样的函数(比如tanh函数)有很多优点,非常适合用来做激活函数,具体请自行google之。

换个思路,我们不换激活函数,而是换掉二次代价函数,改用交叉熵代价函数:

其中, 表示样本, 表示样本的总数。那么,重新计算参数 的梯度:

因此, 的梯度公式中原来的 被消掉了;另外,该梯度公式中的 表示输出值与实际值之间的误。所以,当误越大,梯度就越大,参数 调整得越快,训练速度也就越快。 实际情况证明,交叉熵代价函数带来的训练效果往往比二次代价函数要好。

在实际分类任务中,要先将输出层的输出值经过Softmax函数,再经过log函数,才用交叉熵损失函数计算损失。

机器学习的过程就是希望在训练数据熵 模型学到的分布 和 真实的分布 越近越好,我们知道KL散度可以表示两个分布之间的不同。

但我们没有真实数据的分布,那么只能退而求其次,希望模型学到的分布和训练数据的分布 ,也就是把训练数据当做模型和真实数据之间的人 。设训练数据是从总体中同步分布采样(Independent and identically distributed sampled)而来,那么我们可以利用最小化训练数据的经验误来降低模型的泛化误。简单说:

由此非常理想化的看法是如果 模型(左) 能够学到 训练数据(中) 的分布,那么应该近似的学到了 真实数据(右) 的分布: 近似于 近似于

简单的交叉熵,你真的懂了吗?

交叉熵损失函数

如何动态调整准确率与召回率?

对于准确率与召回率的概念,虽然有很多文章介绍了,但是很多人还是不容易形成直觉的理解。这里不谈公式,结合一个通俗的例子,帮助大家理解。

例子 :有100个人,1人患有癌症。我们对其进行预测2.Using a target size (torch.Size([32])) that is different to the input size (torch.Size([32, 1])) is deprecated. Please ensure they he the same size.,这个问题我在二分类问题中遇到的,损失函数的target是一维的,但是model的输出也即损失函数的input是二维的。,然后再计算每种预测的准确率与召回率。

准确率与召回率是相对于 正 样本来说的,也就是要先定义什么是正。我们这里将“有癌症”定义为正,那么没有癌症就是负。

他们还有另一对名字,更直观也更容易理解:

在二分类任务中,模型输出一般为0到1之间的一个数值,记为 ,如果大于0.5,我们预测为正,否则为负。这里的0.5代表一个阈值,记为 ,则分类标准如下:

要调整准确率与召回率,直接调整s就行了。增大s,准确率上升,召回率下降;减少s,准确率下降,召回率上升。

如何理解?以一个神经元的二类分类训练为例,进行两次实验(ANN常用的激活函数为sigmoid函数,该实验也采用该函数):输入一个相同的样本数据x=1.0(该样本对应的实际分类y=0);两次实验各自随机初始化参数,从而在各自的次前向传播后得到不同的输出值,形成不同的代价(误):

模型的输出 可以代表信心(也就是模型预测样本为正的确信程度)。阈值 增加,则表示需要更大的信心才会预测为正,这时准确率必然增加;同时,阈值的增加导致所预测正样本的减少,找出正样本的可能性就会降低,从而导致召回率的下降。

在多分类任务中,模型会输出一个Category分布,比如3分类,一个可能的输出是[0.1, 0.2, 0.7]。在深度学习模型中,我们一般使用一个softmax函数来生成中的分布。记前一层的输出为 , 最终的输出为 , 则:

要调整类别1所对应的准确率召回率,我们直接调整 就行了(增加/减少一个值)。增加 ,类别1的的召回率增加,准确率下降;同时,类别2、类别3的召回率下降,准确率增加。

如何理解?

在NLP中,分词、词性、NER都被转化为序列标注任务进行处理。序列标注任务也就是序列分类任务。学会了分类任务准确率召回率调整方法,调整序列标注任务也就不难了。以NER任务为例:

现在主流的序列标注模型是BI-LSTM-CRF、BERT-CRF等,都是先使用一个神经网络计算每个字每个类别的分数,然后再通过CRF层进行调整。我们可以通过调整进入CRF之前的分数,从而达到调整准确率与召回率的目的。(BI-LSTM-CRF和CRF的PyTorch通用实现可以参考 开源库bi-lstm-crf )

在上面的表格种,每一列对应一个字的多分类的分数,这些分数的范围没有经过归一化,范围是整个 ,但是调整的方法还是一样的,直接修改这些分数就行了。

比如通过增加"O"标签对应的分数,"O"标签对应的最终概率就会提升,跟实体相关的标签(B-LOC, I-LOC, ...)的概率则会下降,这样NER的召回率就会下降,准确率则会上升。

通过实验法,拿一个带标注的数据集作为测试集,使用不同的调整数值,跑完整个测试集上,并计算准确率与召回率。这样就会得到2根曲线,一条对应准确率、一条对回率,横坐标对应不同的调整数值。然后根据需要选择对应的调整数值即可。

建筑资料员是干什么的 建筑资料员是干嘛的

小爱今天给分享建筑资料员是干什么的的知识,其中也会对建筑资料员是干嘛的进行解释,希望能解决你的问题,请看下面的文章阅读吧! 建筑资料员是干什么的 建筑资料员是干嘛的 建筑资料员···

一年级数学阅读教案 一年级数学阅读教案人教

小学一年级数学教案 作为一名专为他人授业解惑的教师,可能需要进行教案编写工作,编写教案助于积累教学经验,不断提高教学质量。写教案需要注意哪些格式呢?以下是我收集整理的小学一年···

a3的纸是多大的纸 a3纸的尺寸多少厘米

关于a3的纸是多大的纸,a3纸的尺寸多少厘米这个很多人还不知道,今天小乐来为大家解答以上的问题,现在让我们一起来看看吧! a3的纸是多大的纸 a3纸的尺寸多少厘米 a3的纸是多大的纸 a3纸的尺···