Pytorch中易混淆的损失函数与激活函数【softmax, log_softmax, NLLLoss, CrossEntropy】

  • Post author:
  • Post category:其他




定义


  • softmax

    :将一个数值序列映射到概率空间(每个元素分布并且所有和为1)

  • log_softmax

    :在softmax的基础上取对数

  • NLLLoss

    :对log_softmax与one-hot进行计算

  • CrossEntropy

    :衡量两个概率分布的差别(交叉熵)


在分类问题中,CrossEntropy等价于log_softmax 结合 nll_loss。



激活函数



softmax

import torch
import torch.nn.functional as F
'''
torch.nn.functional 涉及了所有 torch.nn 需要 类 和 方法 ,torch.nn 构建的模块通常就是调用 torch.nn.functional 里的方法实现的.
'''
torch.manual_seed(0)
output = torch.randn(2, 3)
print(output)
#tensor([[ 1.5410, -0.2934, -2.1788],
#        [ 0.5684, -1.0845, -1.3986]])
print(F.softmax(output, dim=1))
# 这里dim的意思是计算Softmax的维度,这里设置dim=1,可以看到每一行的加和为1。0是对列 1 是对行
#tensor([[0.8446, 0.1349, 0.0205],
#       [0.7511, 0.1438, 0.1051]])



T-softmax

T-softmax的目的是平滑分布,不让分布太过于极端。比如可以看下面的实例哈。

import numpy as np

def softmax(x):
    x_exp = np.exp(x)
    return x_exp / np.sum(x_exp)

output = np.array([0.1, 1.6, 3.6])
print(softmax(output))
#[0.02590865 0.11611453 0.85797681]

使用带温度系数的softmax函数:

def softmax_t(x, t):
    x_exp = np.exp(x / t)
    return x_exp / np.sum(x_exp)

output = np.array([0.1, 1.6, 3.6])
print(softmax_t(output, 5))
#[0.22916797 0.3093444  0.46148762]

设置为5可以看到分布在【0,1】的数更加平滑了。



log_softmax

这个很好理解,其实就是对

softmax

处理之后的结果执行一次对数运算。可以理解为

log(softmax(output))

print(F.log_softmax(output, dim=1))
print(torch.log(F.softmax(output, dim=1)))
# 输出结果是一致的

tensor([[-0.1689, -2.0033, -3.8886], [-0.2862, -1.9392, -2.2532]]) tensor([[-0.1689, -2.0033, -3.8886], [-0.2862, -1.9392, -2.2532]])



损失函数



NLLLoss

该函数的全称是

negative log likelihood loss

. 若



x

i

=

[

q

1

,

q

2

,

.

.

.

,

q

N

]

x_i=[q_1, q_2, …, q_N]







x










i




















=








[



q










1


















,





q










2


















,







,





q










N


















]





为神经网络对第i个样本的输出值,



y

i

y_i







y










i





















为真实标签。则:





f

(

x

i

,

y

i

)

=

q

y

i

f(x_i,y_i)=-q_{y_i}






f


(



x










i


















,





y










i


















)




=












q












y










i








































其中输入:

log_softmax(output), target

print(F.nll_loss(torch.tensor([[-1.2, -2, -3]]), torch.tensor([0])))
#结果是tensor(1.2000) 就是取第0个index值的负数


通常我们结合 log_softmax 和 nll_loss一起用



CrossEntropy交叉熵


在分类问题中,CrossEntropy等价于log_softmax 结合 nll_loss




N

N






N





分类问题,对于一个特定的样本,已知其真实标签,

CrossEntropy

的计算公式为:





c

r

o

s

s

_

e

n

t

r

o

p

y

=

k

=

1

N

(

p

k

log

q

k

)

cross\_entropy=-\sum_{k=1}^{N}\left(p_{k} * \log q_{k}\right)






cross


_


e


n


t


ro


p


y




=






















k


=


1



















N





















(



p











k


























lo

g






q











k



















)






其中p表示真实值,在这个公式中是one-hot形式;q是经过

softmax

计算后的结果,



q

k

q_k







q










k





















为神经网络认为该样本为第



k

k






k





类的概率。

仔细观察可以知道,因为p的元素不是0就是1,而且又是乘法,所以很自然地我们如果知道1所对应的index,那么就不用做其他无意义的运算了。所以在pytorch代码中target不是以one-hot形式表示的,而是直接用scalar表示。若该样本的真实标签为



y

y






y





,则交叉熵的公式可变形为:





c

r

o

s

s

_

e

n

t

r

o

p

y

=

k

=

1

N

(

p

k

log

q

k

)

=

l

o

g

q

y

cross\_entropy=-\sum_{k=1}^{N}\left(p_{k} * \log q_{k}\right)=-log \, q_{y}






cross


_


e


n


t


ro


p


y




=






















k


=


1



















N





















(



p











k


























lo

g






q











k



















)





=











l


o


g





q











y






















output = torch.tensor([[1.2, 2, 3]])
target = torch.tensor([0])

log_sm_output = F.log_softmax(output, dim=1)
nll_loss_of_log_sm_output = F.nll_loss(log_sm_output, target)
print(nll_loss_of_log_sm_output)
output = torch.tensor([[1.2, 2, 3]])
target = torch.tensor([0])

ce_loss = F.cross_entropy(output, target)
print(ce_loss)

F.cross_entropy 《==》 F.log_softmax(output, dim=1)+F.nll_loss(log_sm_output, target)

这两者是等价的。



版权声明:本文为qq_43456497原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。