变量名解释

logits:未经过normalize(未经过激活函数处理)的原始预测值,例如一个mlp将特征映射到num_target_class维的输出tensor就是logits。 probs:probabilities的简写,例如logits经过sigmoid函数,就变成了分布在0-1之间的概率值probs。

Binary Cross-Entropy Loss

Binary Cross-Entropy Loss,简称为BCE loss,即二元交叉熵损失。

二元交叉熵损失是一种用于二分类问题的损失函数。它衡量的是模型预测的概率分布与真实标签的概率分布之间的差异。在二分类问题中,每个样本的标签只有两种可能的状态,通常表示为 0(负类)和 1(正类)。

其公式为:

L

B

C

E

=

1

N

i

=

1

N

[

y

i

log

(

p

i

)

+

(

1

y

i

)

log

(

1

p

i

)

]

L_{BCE}=-\frac{1}{N} \sum_{i=1}^N\left[y_i \log \left(p_i\right)+\left(1-y_i\right) \log \left(1-p_i\right)\right]

LBCE​=−N1​i=1∑N​[yi​log(pi​)+(1−yi​)log(1−pi​)]

其中:

N

N

N是数据集的样本数量。

y

i

y_i

yi​是第

i

{i}

i个样本的真实标签,取值为 0 或 1,即第

i

{i}

i个样本要么属于类别 0(负类),要么属于类别 1(正类)。

p

i

p_i

pi​是第

i

{i}

i个样本属于类别 1(正类)的预测概率

log

\log

log是是自然对数。

当真实标签

y

i

=

1

y_i=1

yi​=1 时,损失函数的第一部分

y

i

log

(

p

i

)

y_i \log \left(p_i\right)

yi​log(pi​) 起作用,第二部分为 0 。此时, 如果预测概率

p

i

p_i

pi​ 接近 1 (接近真实标签

y

i

=

1

y_i=1

yi​=1), 那么

log

(

p

i

)

\log \left(p_i\right)

log(pi​) 接近 0 , 损失较小;如果

p

i

p_i

pi​ 接近 0 (即模型预测错误),那么

log

(

p

i

)

\log \left(p_i\right)

log(pi​) 会变得成绝对值很大的负数,导致取反后loss很大。

当真实标签

y

i

=

0

y_i=0

yi​=0 时,损失函数的第二部分

(

1

y

i

)

log

(

1

p

i

)

\left(1-y_i\right) \log \left(1-p_i\right)

(1−yi​)log(1−pi​)起作用,第一部分为 0。此时,预测概率

p

i

p_i

pi​越接近于 0,整体loss越小。

Pytorch手动实现

import torch

import torch.nn.functional as F

def manual_binary_cross_entropy_with_logits(logits, targets):

# 使用 Sigmoid 函数将 logits 转换为概率

probs = torch.sigmoid(logits)

# 计算二元交叉熵损失

loss = - torch.mean(targets * torch.log(probs) + (1 - targets) * torch.log(1 - probs))

return loss

# logits和targets可以是任意shape的tensor,只要两者shape相同即可

logits = torch.tensor([0.2, -0.4, 1.2, 0.8])

targets = torch.tensor([0., 1., 1., 0.])

assert logits.shape == targets.shape

# 使用 PyTorch 的 F.binary_cross_entropy_with_logits 函数计算损失

loss_pytorch = F.binary_cross_entropy_with_logits(logits, targets)

# 使用手动实现的函数计算损失

loss_manual = manual_binary_cross_entropy_with_logits(logits, targets)

print(f'Loss (PyTorch): {loss_pytorch.item()}')

print(f'Loss (Manual): {loss_manual.item()}')

F.binary_cross_entropy 与 F.binary_cross_entropy_with_logits的区别

F.binary_cross_entropy的输入是probs

F.binary_cross_entropy_with_logits的输入是logits

   

Dice Loss

Dice Loss 来自文章《V-Net: Fully Convolutional Neural Networks for Volumetric Medical Image Segmentation》,它能够有效地处理图像分割任务中正负样本不平衡问题。例如,当一张图片中真实分割区域占比很小,即gt_label里的正样本像素很少。这时候如果用BCE Loss,图片里的每个像素都要去进行二分类,而绝大部分的像素都是负样本,所以会存在正负样本不平衡的问题。

介绍Dice Loss前,需要先了解Dice系数。

Dice系数是一种用于评估两个集合的相似性的度量函数,取值范围在0到1之间,取值越大表示越相似。定义如下:

 dice coefficient 

=

2

×

X

Y

X

+

Y

\text { dice coefficient }=\frac{2 \times|X \cap Y|}{|X|+|Y|}

 dice coefficient =∣X∣+∣Y∣2×∣X∩Y∣​

其中

X

X

X 和

Y

Y

Y 分别是两个样本集合,

X

Y

X \cap Y

X∩Y 表示它们交集的大小,

X

|X|

∣X∣ 和

Y

|Y|

∣Y∣分别表示

X

X

X 和

Y

Y

Y中的样本个数。由于分子乘上了 2,Dice 系数的值在 0 到 1 之间,值越大表示相似度越高。

而对于Dice Loss,我们的训练目的是让两个样本越来越相似,所以当

X

X

X 和

Y

Y

Y越相似,loss值应该越小,而Dice系数的值在 0 到 1 之间,我们可以直接用1减去Dice系数来作为Dice Loss,这样就能达成两个样本越相似loss值越小的目的:

L

d

i

c

e

=

1

 dice coefficient 

L_{dice}= 1 - \text { dice coefficient }

Ldice​=1− dice coefficient 

在图像分割任务中,Dice 系数计算预测分割区域和真实分割区域之间的重叠度。上述公式中的

X

X

X 和

Y

Y

Y则分别代表预测分割区域和真实分割区域。

I

=

1

N

p

i

y

i

U

=

1

N

(

p

i

+

y

i

)

=

1

N

p

i

+

1

N

y

i

\begin{gathered} I=\sum_1^N p_i y_i \\ U=\sum_1^N\left(p_i+y_i\right)=\sum_1^N p_i+\sum_1^N y_i \end{gathered}

I=1∑N​pi​yi​U=1∑N​(pi​+yi​)=1∑N​pi​+1∑N​yi​​

其中:

N

N

N是一张图片里的像素数量。

y

i

y_i

yi​是第

i

{i}

i个像素的真实标签,取值为 0 或 1,即第

i

{i}

i个像素要么属于类别 0(非分割区域),要么属于类别 1(分割区域)。

p

i

p_i

pi​是第

i

{i}

i个像素属于类别 1(分割区域)的预测概率。

I

I

I是图像的分割区域中,每个像素的预测概率之和。

I

I

I代表上述公式中的

X

Y

|X \cap Y|

∣X∩Y∣。

U

U

U是图像每个像素的真实分割概率之和(即真实分割区域的像素总数) + 每个像素的预测分割概率之和。

U

U

U代表上述公式中的

X

+

Y

|X|+|Y|

∣X∣+∣Y∣。

Dice Loss 为 Dice 系数的补数,即 1 减去 Dice 系数。在实际应用中,为了避免除以零的情况,通常会在分子和分母中添加一个小的平滑项

ϵ

\epsilon

ϵ。

L

dice 

=

1

2

I

+

ε

U

+

ε

L_{\text {dice }}=1-\frac{2 I+\varepsilon}{U+\varepsilon}

Ldice ​=1−U+ε2I+ε​

在许多实现中,将预测值 logits 和目标 targets 在计算Dice Loss的过程中除以一个缩放因子(如 1000 或 10000),通常是为了数值稳定性。当处理大型图像或大量数据时,像素点的总数可能非常大,这意味着求和操作可能产生非常大的值。这可能导致计算过程中出现数值不稳定性,尤其是在梯度下降和反向传播过程中。通过引入一个缩放因子,可以将这些值缩小到一个更合理的范围内,从而减少数值不稳定性的风险。

Pytorch手动实现

import torch

import torch.nn.functional as F

def dice_loss(

logits: torch.Tensor, # shape为[bs, h, w]

targets: torch.Tensor, # shape为[bs, h, w]

scale=1000,

eps=1e-6,

):

probs = logits.sigmoid()

# 只对h,w这两维求和,保留bs这一维,这样每个sample都可以得到一个dice loss

numerator = 2 * (probs / scale * targets).sum(dim=(-2, -1))

denominator = (probs / scale).sum(dim=(-2, -1)) + (targets / scale).sum(dim=(-2, -1))

loss = 1 - (numerator + eps) / (denominator + eps)

return loss

# 随机生成shape为(4, 480, 640)的预测值 logits 和目标 targets

# targets要么是 0(非分割区域),要么是 1(分割区域)

logits = torch.randn(4, 480, 640)

targets = torch.randint(0, 2, (4, 480, 640))

loss = dice_loss(logits, targets) # shape为[bs, ]

print(f"Dics Loss: {loss}")

GIOU Loss

Focal Loss

Cross-Entropy Loss

KLDivLoss

好文链接

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。