损失函数详细复现(pytorch版本)

什么是损失函数

损失函数(Loss Function)是在机器学习和深度学习中用于评估模型预测结果与实际标签之间差异的函数。它衡量了模型的性能,即模型对训练样本的预测与实际标签的偏差程度。目标是通过调整模型参数,使损失函数的值最小化,从而提高模型的准确性和泛化能力。

常见的损失函数

这里的复现主要是与官方的实现进行对比实验。

L1Loss

它叫做平均绝对误差,定义如下所示:

L_{1} = \frac{1}{N}\sum_{N}^{i=1}\left | y_{i}-\hat{y_{i}} \right |

其中,y_{i}表示样本i的真实标签,\hat{y_{i}}表示模型对于样本i的预测标签。将每个样本的绝对误差取平均值,得到L1 Loss。

class L1Loss(nn.Module):
    def __init__(self):
        super(L1Loss, self).__init__()

    def forward(self, input, target):
        loss = torch.mean(torch.abs(input - target))
        return loss

测试代码为以下所示:

if __name__=="__main__":
    criterion1 = nn.L1Loss()
    criterion2 = L1Loss()

    input_data=torch.Tensor([2, 3, 4, 5])
    target_data=torch.Tensor([4, 5, 6, 7])
    loss1 = criterion1(input_data, target_data)
    print(loss1)
    loss2 = criterion2(input_data, target_data)
    print(loss2)

测试输出均为 tensor(2.)

L2Loss

它叫做均方误差,定义如下所示:

L_{2} = \frac{1}{N}\sum_{N}^{i=1}(y_{i}--\hat{y_{i}})^{2}

其中,y_{i}表示样本i的真实标签,\hat{y_{i}}表示模型对于样本i的预测标签。测量预测输出中的每个元素与目标或地面实况中的相应元素之间的平均平方差。

class L2Loss(nn.Module):
    def __init__(self):
        super(L2Loss, self).__init__()

    def forward(self, input, target):
        loss = torch.mean(torch.pow(input - target, 2))
        return loss

测试代码为以下所示: 

if __name__=="__main__":
    criterion1 = nn.MSELoss()
    criterion2 = L2Loss()

    input_data=torch.Tensor([2, 3, 4, 5])
    target_data=torch.Tensor([4, 5, 6, 7])
    loss1 = criterion1(input_data, target_data)
    print(loss1)
    loss2 = criterion2(input_data, target_data)
    print(loss2)

测试输出均为 tensor(4.)

BCELoss

二元交叉熵损失(Binary Cross Entropy Loss),也称为对数损失。

\text{BCELoss} = -\frac{1}{N} \sum_{i=1}^{N} \left( y_i \log(\hat{y}_i) + (1 - y_i) \log(1 - \hat{y}_i) \right)

其中,y_{i}表示样本i的真实标签,\hat{y_{i}}表示模型对于样本i的预测标签。用于测量预测输出中的每个元素与目标或地面实况中的相应元素之间的对数概率差异。

class BCELoss(nn.Module):
    def __init__(self):
        super(BCELoss, self).__init__()

    def forward(self, input, target):
        input = torch.sigmoid(input)
        loss = - (target * torch.log(input) + (1 - target) * torch.log(1 - input))
        return loss.mean()

测试代码为以下所示: 

if __name__=="__main__":
    criterion1 = nn.BCELoss()
    criterion2 = BCELoss()
    input_data = torch.randn((5,))
    print(input_data)
    target_data = torch.randint(0, 2, (5,), dtype=torch.float32)
    print(target_data)
    loss1 = criterion1(torch.sigmoid(input_data), target_data)
    loss2 = criterion2(input_data, target_data)
    print("PyTorch BCELoss:", loss1.item())
    print("MY BCELoss:", loss2.item())

tensor([-2.0343, -1.5186,  1.6389,  0.4658,  0.6823])
tensor([1., 0., 1., 1., 1.])

测试输出均为 0.6857892274856567

当实际标签为1时(y_{i}=1),我们希望模型的预测概率越接近1,因为实际上这个样本是正类别。因此,我们希望\hat{y_{i}}越大,这样log(\hat{y_{i}})的值越小。因此,我们的损失项是-log(\hat{y_{i}})

当实际标签为0时(y_{i}=0),我们希望模型的预测概率越接近0,因为实际上这个样本是负类别。因此,我们希望1-\hat{y_{i}}越大,这样log(1-\hat{y_{i}})的值就越小。因此,我们的损失项是-(1-\hat{y_{i}})log(1-\hat{y_{i}})

我们将上述两种情况的损失项相加,并取平均。最终的BCELoss公式是上述两项的求和。

CrossEntropyLoss

交叉熵损失(CrossEntropyLoss)是在深度学习中常用于多分类问题的一种损失函数。它衡量了模型输出的概率分布与真实标签之间的差异。

\text{CrossEntropyLoss}(x, y) = -\frac{1}{N} \sum_{i=1}^{N} \log\left(\frac{\exp(x_{i, y_i})}{\sum_{j=1}^{C} \exp(x_{i, j})}\right)

其中,y_{i}表示样本i的真实标签,\hat{y_{i}}表示模型对于样本i的预测标签。 

 class CrossEntropyLoss(nn.Module):
    def __init__(self):
        super(CrossEntropyLoss, self).__init__()

    def forward(self, input, target):
        return nn.NLLLoss()(F.log_softmax(input, dim=1), target)

测试代码为以下所示: 

if __name__ == "__main__":
    criterion1 = nn.CrossEntropyLoss()
    criterion2 = CrossEntropyLoss()

    input_data = torch.randn((3, 5))
    target_data = torch.randint(0, 5, (3,))
    loss1 = criterion1(input_data, target_data)
    loss2 = criterion2(input_data, target_data)
    print("PyTorch CrossEntropyLoss:", loss1.item())
    print("Custom CrossEntropyLoss:", loss2.item())

测试输出均为 2.0007288455963135

分子部分exp(x_{i,j})这是模型对第 i 个样本正确类别的原始输出的指数形式。这一部分希望越大越好,因为我们希望模型对正确类别有更高的置信度。

分母部分\sum_{j=1}^{C} \exp(x_{i,j})这是模型对第i个样本所有类别原始输出的指数形式的和。这一部分用于归一化,将原始输出转化为概率分布。通过除以这个和,我们得到每个类别的概率,表示模型对每个类别的相对置信度。

对上述概率分布取对数。这个操作将概率空间映射到实数空间,使得我们可以用数值优化的方法来优化模型。这一部分希望越小越好,因为我们希望模型对真实标签的估计概率越接近于1。

参考文章

L1 loss 是什么_l1loss-CSDN博客

【损失函数】(三) NLLLoss原理 & pytorch代码解析_pytorch nll_loss-CSDN博客

损失函数(lossfunction)的全面介绍(简单易懂版)-CSDN博客

相关推荐

最近更新

  1. TCP协议是安全的吗?

    2024-01-27 02:44:01       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-01-27 02:44:01       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-01-27 02:44:01       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-01-27 02:44:01       18 阅读

热门阅读

  1. 常见的并联谐振应用案例

    2024-01-27 02:44:01       38 阅读
  2. ORA-32771: cannot add file to bigfile tablespace

    2024-01-27 02:44:01       29 阅读
  3. 【每日一题】YACS P11:双质数

    2024-01-27 02:44:01       41 阅读
  4. 【知识---git中一些常用的命令及其选项】

    2024-01-27 02:44:01       27 阅读
  5. Android 写入 csv 乱码,设置UTF-8的流也不行

    2024-01-27 02:44:01       43 阅读