PyTorch的SoftMax交叉熵损失和梯度用法
在PyTorch中可以方便的验证SoftMax交叉熵损失和对输入梯度的计算
关于softmax_cross_entropy求导的过程,可以参考HERE
示例:
#-*-coding:utf-8-*- importtorch importtorch.autogradasautograd fromtorch.autogradimportVariable importtorch.nn.functionalasF importtorch.nnasnn importnumpyasnp #对data求梯度,用于反向传播 data=Variable(torch.FloatTensor([[1.0,2.0,3.0],[1.0,2.0,3.0],[1.0,2.0,3.0]]),requires_grad=True) #多分类标签one-hot格式 label=Variable(torch.zeros((3,3))) label[0,2]=1 label[1,1]=1 label[2,0]=1 print(label) #forbatchloss=mean(-sum(Pj*logSj)) #forone:loss=-sum(Pj*logSj) loss=torch.mean(-torch.sum(label*torch.log(F.softmax(data,dim=1)),dim=1)) loss.backward() print(loss,data.grad)
输出:
tensor([[0.,0.,1.], [0.,1.,0.], [1.,0.,0.]]) #loss:损失和input'sgrad:输入的梯度 tensor(1.4076)tensor([[0.0300,0.0816,-0.1116], [0.0300,-0.2518,0.2217], [-0.3033,0.0816,0.2217]])
注意:
对于单输入的loss和grad
data=Variable(torch.FloatTensor([[1.0,2.0,3.0]]),requires_grad=True) label=Variable(torch.zeros((1,3))) #分别令不同索引位置label为1 label[0,0]=1 #label[0,1]=1 #label[0,2]=1 print(label) #forbatchloss=mean(-sum(Pj*logSj)) #forone:loss=-sum(Pj*logSj) loss=torch.mean(-torch.sum(label*torch.log(F.softmax(data,dim=1)),dim=1)) loss.backward() print(loss,data.grad)
其输出:
#第一组: lable:tensor([[1.,0.,0.]]) loss:tensor(2.4076) grad:tensor([[-0.9100,0.2447,0.6652]]) #第二组: lable:tensor([[0.,1.,0.]]) loss:tensor(1.4076) grad:tensor([[0.0900,-0.7553,0.6652]]) #第三组: lable:tensor([[0.,0.,1.]]) loss:tensor(0.4076) grad:tensor([[0.0900,0.2447,-0.3348]]) """ 解释: 对于输入数据tensor([[1.,2.,3.]])softmax之后的结果如下 tensor([[0.0900,0.2447,0.6652]]) 交叉熵求解梯度推导公式可知s[0,0]-1,s[0,1]-1,s[0,2]-1是上面三组label对应的输入数据梯度 """
pytorch提供的softmax,和log_softmax关系
#官方提供的softmax实现 In[2]:importtorch ...:importtorch.autogradasautograd ...:fromtorch.autogradimportVariable ...:importtorch.nn.functionalasF ...:importtorch.nnasnn ...:importnumpyasnp In[3]:data=Variable(torch.FloatTensor([[1.0,2.0,3.0]]),requires_grad=True) In[4]:data Out[4]:tensor([[1.,2.,3.]]) In[5]:e=torch.exp(data) In[6]:e Out[6]:tensor([[2.7183,7.3891,20.0855]]) In[7]:s=torch.sum(e,dim=1) In[8]:s Out[8]:tensor([30.1929]) In[9]:softmax=e/s In[10]:softmax Out[10]:tensor([[0.0900,0.2447,0.6652]]) In[11]:#等同于pytorch提供的softmax In[12]:org_softmax=F.softmax(data,dim=1) In[13]:org_softmax Out[13]:tensor([[0.0900,0.2447,0.6652]]) In[14]:org_softmax==softmax#计算结果相同 Out[14]:tensor([[1,1,1]],dtype=torch.uint8) #与log_softmax关系 #log_softmax=log(softmax) In[15]:_log_softmax=torch.log(org_softmax) In[16]:_log_softmax Out[16]:tensor([[-2.4076,-1.4076,-0.4076]]) In[17]:log_softmax=F.log_softmax(data,dim=1) In[18]:log_softmax Out[18]:tensor([[-2.4076,-1.4076,-0.4076]])
官方提供的softmax交叉熵求解结果
#-*-coding:utf-8-*- importtorch importtorch.autogradasautograd fromtorch.autogradimportVariable importtorch.nn.functionalasF importtorch.nnasnn importnumpyasnp data=Variable(torch.FloatTensor([[1.0,2.0,3.0],[1.0,2.0,3.0],[1.0,2.0,3.0]]),requires_grad=True) log_softmax=F.log_softmax(data,dim=1) label=Variable(torch.zeros((3,3))) label[0,2]=1 label[1,1]=1 label[2,0]=1 print("lable:",label) #交叉熵的计算方式之一 loss_fn=torch.nn.NLLLoss()#reduce=Trueloss.sum/batch&grad/batch #NLLLoss输入是log_softmax,target是非one-hot格式的label loss=loss_fn(log_softmax,torch.argmax(label,dim=1)) loss.backward() print("loss:",loss,"\ngrad:",data.grad) """ #交叉熵计算方式二 loss_fn=torch.nn.CrossEntropyLoss()#thetargetlabelisNOTanone-hotted #CrossEntropyLoss适用于分类问题的损失函数 #input:没有softmax过的nn.output,target是非one-hot格式label loss=loss_fn(data,torch.argmax(label,dim=1)) loss.backward() print("loss:",loss,"\ngrad:",data.grad) """ """
输出
lable:tensor([[0.,0.,1.], [0.,1.,0.], [1.,0.,0.]]) loss:tensor(1.4076) grad:tensor([[0.0300,0.0816,-0.1116], [0.0300,-0.2518,0.2217], [-0.3033,0.0816,0.2217]])
通过和示例的输出对比,发现两者是一样的
以上这篇PyTorch的SoftMax交叉熵损失和梯度用法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。