<强>我就废话不多说了,直接上代码吧! 强>
进口火炬 进口torch.nn。功能和F 进口numpy np 从火炬。autograd导入变量 “‘ pytorch实现焦点丢失的两种方式(现在讨论的是基于分割任务) 在计算损失函数的过程中考虑到类别不平衡的问题,假设加上背景类别共有6个类别 “‘ def compute_class_weights(柱状图): classWeights=np。(6,dtype=np.float32) normHist=直方图/np.sum(柱状图) 因为我在范围(6): classWeights[我]=1/(np.log (1.10 + normHist[我])) 返回classWeights def focal_loss_my(输入,目标): “‘ 参数输入:形状(batch_size num_classes, H, W)仅仅经过卷积操作后的输出,并没有经过任何激活函数的作用 :param目标:形状(batch_size H, W) 返回: “‘ n、c, h, w=input.size () 目标=target.long () 输入=V?1、2).transpose (2、3) .contiguous ()。视图(1 c) 目标=target.contiguous () .view (1) number_0=火炬。和(目标==0).item () number_1=火炬。总和(目标==1).item () number_2=火炬。总和(目标==2).item () number_3=火炬。总和(目标==3).item () number_4=火炬。总和(目标==4).item () number_5=火炬。总和(目标==5).item () 频率=火炬。张量((number_0 number_1、number_2 number_3, number_4, number_5), dtype=torch.float32) 频率=frequency.numpy () classWeights=compute_class_weights(频率) “‘ 根据当前给出的地面实况标签计算出每个类别所占据的权重 “‘ #权重=torch.from_numpy (classWeights) .float () .cuda () 重量=torch.from_numpy (classWeights) .float () focal_frequency=F.nll_loss (F。softmax(输入,昏暗的=1),目标,减少='没有') “‘ 上面一篇博文讲过 F.nll_loss (torch.log (F。softmax(输入,昏暗的=1),目标)的函数功能与F.cross_entropy相同 可见F。nll_loss中实现了对于目标的一个炎热的编码编码功能,将其编码成与输入形状相同的张量 然后与前面那一项(即F。nll_loss输入的第一项)进行element-wise生产 相当于取出了日志(p_gt)即当前样本点被分类为正确类别的概率 现在去掉取对数的操作,相当于focal_frequency形状(num_samples) 即取出地面实况类别的概率数值,并取了负号 “‘ focal_frequency +=1.0 #形状(num_samples) 1 - p (gt_classes) focal_frequency=火炬。战俘(focal_frequency, 2) # torch.Size ([75]) focal_frequency=focal_frequency。重复(c, 1) “‘ 进行重复操作后,focal_frequency形状(num_classes, num_samples) “‘ focal_frequency=focal_frequency。置(1,0) 损失=F。nll_loss (focal_frequency * (torch.log (F。softmax(输入,昏暗的=1))),目标,重量=没有 减少=癳lementwise_mean”) 回波损耗 def focal_loss_zhihu(输入,目标): “‘ 参数输入:使用知乎上面大神给出的方案https://zhuanlan.zhihu.com/p/28527749 :param目标: 返回: “‘ n、c, h, w=input.size () 目标=target.long () 输入=输入。置(1、2).transpose (2、3) .contiguous ()。视图(1 c) 目标=target.contiguous () .view (1) N=inputs.size (0) C=inputs.size (1) number_0=火炬。和(目标==0).item () number_1=火炬。总和(目标==1).item () number_2=火炬。总和(目标==2).item () number_3=火炬。总和(目标==3).item () number_4=火炬。总和(目标==4).item () number_5=火炬。总和(目标==5).item () 频率=火炬。张量((number_0 number_1、number_2 number_3, number_4, number_5), dtype=torch.float32) 频率=frequency.numpy () classWeights=compute_class_weights(频率) 重量=torch.from_numpy (classWeights) .float () 重量=重量(target.view(1)] #这行代码非常重要 γ=2 P=F。softmax(输入,昏暗的=1)#形状(num_samples, num_classes) class_mask=inputs.data。新(N、C) .fill_ (0) class_mask=变量(class_mask) id=目标。视图(1,1) class_mask。scatter_ (id。数据,1)#形状(num_samples num_classes]一个炎热的编码 聚合氯化铝=(P * class_mask) .sum (1)。视图(1,1)#形状(num_samples,) log_p=probs.log () 打印(在计算batch_loss, weights.shape、probs.shape log_p.shape) # batch_loss=重量*(火炬。战俘((1 -聚合氯化铝)γ))* log_p batch_loss=-(火炬。战俘((1 -聚合氯化铝)γ))* log_p 打印(batch_loss.shape) 损失=batch_loss.mean () 回波损耗 if __name__==癬_main__”: pred=torch.rand ((2、6、5、5)) y=torch.from_numpy (np.random.randint (0 6 (2、5、5))) loss1=focal_loss_my (pred, y) loss2=focal_loss_zhihu (pred, y) 打印(loss1, loss1) 打印(loss2, loss2) “‘ 在计算batch_loss torch.Size火炬([50])。大小([50,1])火炬。大小([50,1]) 火炬。大小([50,1]) loss1张量(1.3166) loss2张量(1.3166) “‘pytorch实现焦点丢失的两种方式小结