Hello SYT
损失函数模块:
损失函数的构建分为选择损失函数,在循环中得到损失值并反向传播三步
loss_function = nn.CrossEntropyLoss() # 选择损失函数
#训练之后,获得outputs
loss = loss_function(outputs, labels) # 得到损失值
loss.backward() # 反向传播
损失函数的选择:
pytorch中有如下18种损失函数
- nn.CrossEntropyLoss
- nn.NLLLoss
- nn.BCELoss
- nn.BCEWithLogitsLoss
- nn.L1Loss
- nn.MSELoss
- nn.SmoothL1Loss
- nn.PoissonNLLLoss
- nn.KLDivLoss
- nn.MarginRankingLoss
- nn.MultiLabelMarginLoss
- nn.SoftMarginLoss
- nn.MultiLabelSoftMarginLoss
- nn.MultiMarginLoss
- nn.TripletMarginLoss
- nn.HingeEmbeddingLoss
- nn.CosineEmbeddingLoss
- nn.CTCLoss
下面进行详细的介绍:
1、nn.CrossEntropyLoss
nn.CrossEntropyLoss(weight=None, size_average=None,ignore_index=-100,reduce=None,reduction=‘mean’)
功能:交叉熵损失函数,利用nn.LogSoftmax()与nn.NLLLoss(),进行交叉熵计算
参数:
weight: 想让模型更关注哪一类,可将其权重值设大一些,如将第0类权重设为1.2,则其loss就会放大1.2倍
weight参数为torch.float形式的tensor变量
注:是有多少个类别就有多少个权重,而不是和输入数据量挂钩
ignore_index: 忽略哪一个类别,不计算其损失函数
reduction: 取值 none/sum/mean
none:逐个元素计算,有多少类别返回多少loss
sum:对所有loss进行求和,返回标量
mean:对所有loss加权平均,返回标量,求平均的分母为各损失值所占权重之和
注:参数size_average和reduce可忽略,之前使用这两个参数来实现none/sum/mean三个状态,现在可以不使用size_average和reduce这两个参数
pytorch中的数据运算形式:
不加权重形式推导
红框中,先对结果进行softmax处理,将结果化为0~1的概率形式
篮筐中,再对结果取交叉熵,
注释:LogSoftmax已经完成了softmax和取log的功能,NLLLoss只是对其取了负号
原始交叉熵公式:
与理论中的交叉熵公式对比,缺少了P(xi)这一项,这一项为1,因为xi已经被取出,为必然事件
2、nn.NLLLoss
nn.NLLLoss(weight=None, size_average=None,ignore_index=-100,reduce=None,reduction=‘mean’)
功能:实现负对数似然函数中的负号功能,仅取负号
pytorch中的数据运算形式:
蓝框中为权重
3、nn.BCELoss
nn.BCELoss(weight=None, size_average=None,reduce=None,reduction=‘mean’)
功能:二分类交叉熵
注意事项:输入值取值在[0,1],即最后一层激活函数可能需要为softmax
只不过是交叉熵的特殊表达形式
#准备数据
inputs = torch.tensor([[1,2],[2,2],[3,4],[4,5]],dtype=torch.float)
target = torch.tensor([[1,0],[1,0],[0,1],[0,1]],dtype=torch.float)
#get简单些简单的运算结果
outputs = torch.sigmoid(inputs) # 这里仅经过一个sigmoid函数,使数据符合[0,1]的硬性条件
weight = torch.tensor([1,1],dtype=torch.float)#设置损失函数中的权重值,两个类别都设为1,相当于没设
#一、选择损失函数
# reduction取值的三种形式
loss_f_none = nn.BCELoss(weight=weights,reduction='none')
loss_f_sum = nn.BCELoss(weight=weights,reduction='sum')
loss_f_mean = nn.BCELoss(weight=weights,reduction='mean')
#二、得到损失值
loss_none = loss_f_none(outputs, target)
loss_sum = loss_f_sum(outputs, target)
loss_mean = loss_f_mean(outputs, target)
#三、反向传播(此处单纯反向传播没有意义)
loss_none.backward()
loss_sum.backward()
loss_mean.backward()
#输出查看
print('\nweights:',weights)
print('BCE Loss:\n',loss_none,'\n',loss_sum,'\n',loss_mean)
4、nn.BCEWithLogitsLoss
nn.BCEWithLogitsLoss(weight=None,size_average=None,reduce=None,reduction=‘mean’,pos_weight=none)
功能:结合Sigmoid与二分类交叉熵(3)
为了满足特殊要求:网络最后一层不希望是sigmoid但计算loss时有需要为[0,1]取值的输入
注意事项:网络最后不用再加Sigmoid
特殊参数:
pos_weight:用于均衡正负样本,例如正样本有300个,负样本有100个,则可以将参数设为1/3,等价于正负样本相同
红框:即sigmoid函数
pos_w = torch.tensor([1],dtype=torch.float)
los_f_BCEWithLog = nn.BCEWithLogitsLoss(weight=weights,reduction='none',pos_weight=pos_w)
los_BCEWithLog = los_f_BCEWithLog(outputs,targets)
回归中常用的两个损失函数5、6
5、nn.L1Loss
nn.L1Loss(size_average=None,reduce=None,reduction=‘mean’)
功能:计算inputs与target只差的绝对值
6、nn.MSELoss
nn.MSELoss(size_average=None,reduce=None,reduction=‘mean’)
功能:计算inputs与target之差的平方
7、nn.SmoothL1Loss
nn.SmoothL1Loss(size_average=None,reduce=None,reduction=‘mean’)
功能:平滑的L1Loss
在x-y取值为[-1,1]的区间,采用平方的形式来平滑曲线
8. nn.PoissonNLLLoss
nn.PoissonNLLLoss(log_input=True,full=False,size_average=None,esp=1e-08,reduce=None,reduction=‘mean’)
功能:泊松分布的负对数似然函数
主要参数:
log_input:输入是否为对数形式,决定计算公式
full:计算所有loss,默认为False
esp:修正项,避免log(input)为nan
log_input = True
即输入已经为对数的时候
log_input = False
即输入不是对数的时候
引入了eps修正值,esp是一个10^-8的数,不会对结果产生影响,仅为了避免log为nan
9. nn.KLDivLoss
nn.KLDivLoss(size_average=None,reduce=None,reducton=‘mean’)
功能:计算KLD(divergence),KL散度,相对熵(衡量两个分布的相似性)
重要参数:reduction=none/sum/mean/batchmean
batchmean:batchsize维度求平均值
注意:输入数据,需要提前经过一个nn.logsoftmax()
P为标签,Q为输出值。对比两个篮框可以看到,需要将原始输出化为概率形式,并取log,即需要将输出经过一个nn.logsoftmax()
10. nn.MarginRankingLoss
nn.MarginRankingLoss(margain=0.0,size_average=None,reduce=None,reduction=‘mean’)
功能:用于计算两个向量之间的相似度,用于排序任务
说明:该方法计算两组数据之间的差异,若两组数据长度都为n,则返回一个n*n的loss矩阵
主要参数:
margin:边界,x1与x2之间的差异值
reduction:none/sum/mean
y取值:
y=1时,希望x1比x2大,当x1>x2时,不产生loss
y=-1时,希望x2比x1大,当x2>x1时,不产生loss
x1 = torch.tensor([[1],[2],[3]],dtype=torch.float)
y = torch.tensor([[2],[2],[2]],dtype=torch.float)
target = torch.tensor([1,1,-1],dtype=torch.float)
loss_f = nn.MarginRankingLoss(margin=0,reduction='none')
loss = loss_f(x1,y,target)
print(loss)
11. nn.MultiLabelMarginLoss
nn.MultiLabelMarginLoss(margin=0.0,size_average=None,reduce=None,reduction=‘mean’)
功能:多标签边界损失函数
12. nn.SoftMarginLoss
nn.SoftMarginLoss(size_average=None,reduce=None,reduction=‘mean’)
功能:计算二分类的logistic损失
13. nn.MultiLabelSoftMarginLoss
nn.MultiLabelSoftMarginLoss(weight=None,size_average=None,reduce=None,reduction=‘mean’)
功能:SoftMarginLoss多标签版本
主要参数:
weight:各类别的loss设置权值
reduction :计算模式,可为none/sum/mean
14. nn.MultiMarginLoss
nn.MultiMarginLoss(p=1,margin=1.0,weight=None,size_average=None,reduce=None,reduction=‘mean’)
功能:计算多分类的折页损失
主要参数:
p :可选1或2
weight:各类别的loss设置权值
margin :边界值
reduction :none/sum/mean
15. nn.TripletMarginLoss
nn.TripletMarginLoss(margin=1.0,p=2.0,eps=1e-06,swap=False,size_average=None,reduction=‘mean’)
功能:计算三元组损失,人脸验证中常用
主要参数:
p :范数的阶,默认为2
margin :边界值
reduction :none/sum/mean
16. nn.HingeEmbeddingLoss
nn.HingeEmbeddingLoss(margin=1.0,size_average=None,reduce=None,reduction=‘mean’)
功能:计算两个输入的相似性,常用于非线性embedding和半监督学习
特别注意:输入x应为两个输入之差的绝对值
主要参数:
margin :边界值
reduction :none/sum/mean
17. nn.CosineEmbeddingLoss
nn.CosineEmbeddingLoss(margin=0.0, size_average=None,reduce=None,reduction=‘mean’)
功能:采用余弦相似度计算两个输入的相似性
主要参数:
margin :可取值[-1, 1] , 推荐为[0, 0.5]
reduction :none/sum/mean
18. nn.CTCLoss
nn.CTCLoss(blank=0, reduction=‘mean’, zero_infinity=False)
功能:计算CTC(Connectionist Temporal Classification)损失,解决时序类数据的分类
主要参数:
blank :blank label
zero_infinity :无穷大的值或梯度置0
reduction :none/sum/mean