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

本文介绍了损失函数在机器学习和深度学习中的作用,重点讲解了L1Loss、均方误差(L2Loss)、二元交叉熵(BCELoss)和交叉熵损失(CrossEntropyLoss)的概念、计算方式以及在PyTorch中的应用实例。这些损失函数用于评估模型预测与实际标签的差距,通过最小化损失优化模型性能。
摘要由CSDN通过智能技术生成

什么是损失函数

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

常见的损失函数

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

L1Loss

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

eq?L_%7B1%7D%20%3D%20%5Cfrac%7B1%7D%7BN%7D%5Csum_%7BN%7D%5E%7Bi%3D1%7D%5Cleft%20%7C%20y_%7Bi%7D-%5Chat%7By_%7Bi%7D%7D%20%5Cright%20%7C

其中,eq?y_%7Bi%7D表示样本i的真实标签,eq?%5Chat%7By_%7Bi%7D%7D表示模型对于样本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

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

eq?L_%7B2%7D%20%3D%20%5Cfrac%7B1%7D%7BN%7D%5Csum_%7BN%7D%5E%7Bi%3D1%7D%28y_%7Bi%7D--%5Chat%7By_%7Bi%7D%7D%29%5E%7B2%7D

其中,eq?y_%7Bi%7D表示样本i的真实标签,eq?%5Chat%7By_%7Bi%7D%7D表示模型对于样本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),也称为对数损失。

eq?%5Ctext%7BBCELoss%7D%20%3D%20-%5Cfrac%7B1%7D%7BN%7D%20%5Csum_%7Bi%3D1%7D%5E%7BN%7D%20%5Cleft%28%20y_i%20%5Clog%28%5Chat%7By%7D_i%29%20+%20%281%20-%20y_i%29%20%5Clog%281%20-%20%5Chat%7By%7D_i%29%20%5Cright%29

其中,eq?y_%7Bi%7D表示样本i的真实标签,eq?%5Chat%7By_%7Bi%7D%7D表示模型对于样本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时(eq?y_%7Bi%7D%3D1),我们希望模型的预测概率越接近1,因为实际上这个样本是正类别。因此,我们希望eq?%5Chat%7By_%7Bi%7D%7D越大,这样eq?log%28%5Chat%7By_%7Bi%7D%7D%29的值越小。因此,我们的损失项是eq?-log%28%5Chat%7By_%7Bi%7D%7D%29

当实际标签为0时(eq?y_%7Bi%7D%3D0),我们希望模型的预测概率越接近0,因为实际上这个样本是负类别。因此,我们希望eq?1-%5Chat%7By_%7Bi%7D%7D越大,这样eq?log%281-%5Chat%7By_%7Bi%7D%7D%29的值就越小。因此,我们的损失项是eq?-%281-%5Chat%7By_%7Bi%7D%7D%29log%281-%5Chat%7By_%7Bi%7D%7D%29

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

CrossEntropyLoss

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

eq?%5Ctext%7BCrossEntropyLoss%7D%28x%2C%20y%29%20%3D%20-%5Cfrac%7B1%7D%7BN%7D%20%5Csum_%7Bi%3D1%7D%5E%7BN%7D%20%5Clog%5Cleft%28%5Cfrac%7B%5Cexp%28x_%7Bi%2C%20y_i%7D%29%7D%7B%5Csum_%7Bj%3D1%7D%5E%7BC%7D%20%5Cexp%28x_%7Bi%2C%20j%7D%29%7D%5Cright%29

其中,eq?y_%7Bi%7D表示样本i的真实标签,eq?%5Chat%7By_%7Bi%7D%7D表示模型对于样本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

分子部分eq?exp%28x_%7Bi%2Cj%7D%29这是模型对第 i 个样本正确类别的原始输出的指数形式。这一部分希望越大越好,因为我们希望模型对正确类别有更高的置信度。

分母部分eq?%5Csum_%7Bj%3D1%7D%5E%7BC%7D%20%5Cexp%28x_%7Bi%2Cj%7D%29这是模型对第i个样本所有类别原始输出的指数形式的和。这一部分用于归一化,将原始输出转化为概率分布。通过除以这个和,我们得到每个类别的概率,表示模型对每个类别的相对置信度。

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

参考文章

L1 loss 是什么_l1loss-CSDN博客

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

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

 

  • 27
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 好的,以下是使用PyTorch复现PointNet++的步骤: 1. 安装PyTorch和其他必要的库,如numpy、scipy、h5py等。 2. 下载PointNet++的代码和数据集。可以从官方GitHub仓库下载代码,数据集可以从官方网站下载。 3. 将数据集转换为PyTorch可以处理的格式。可以使用h5py库读取数据集,然后将数据转换为PyTorch张量。 4. 编写模型代码。PointNet++的模型代码可以在PointNet++的GitHub仓库找到。将代码转换为PyTorch版本并进行必要的修改。 5. 训练模型。使用PyTorch的优化器和损失函数训练模型。可以使用PyTorch的DataLoader加载数据集,并使用PyTorch的GPU加速训练过程。 6. 测试模型。使用测试集测试模型的性能。可以使用PyTorch的评估函数计算模型的准确率和其他指标。 7. 调整模型。根据测试结果调整模型的参数和架构,以提高模型的性能。 以上是使用PyTorch复现PointNet++的基本步骤。需要注意的是,这只是一个大致的指导,具体的实现过程可能会因为数据集和模型的不同而有所不同。 ### 回答2: PointNet 是一种用于点云数据的深度学习模型,其对点云进行全局池化(global pooling)以及局部特征学习(local feature learning)的方法使得其在各种场景取得了非常好的结果。本文将介绍如何使用 PyTorch 复现 PointNet 模型。 首先,我们需要准备数据。PointNet 接收的输入是点云,我们可以通过采样或者转换方法将 mesh 数据转换为点云数据。在转换为点云后,我们可以将点云转换为 numpy array,并使用 PyTorch 的 DataLoader 进行数据预处理。在这里我们使用 ModelNet40 数据集进行实验。 接下来,我们需要定义 PointNet 模型的结构。PointNet 包括两个编码器和一个分类器。编码器用于从点云提取特征信息,分类器用于将提取的特征映射到具体的分类标签。这里我们定义一个函数 PointNetCls,将编码器和分类器都封装在这个函数。 ```python import torch.nn as nn import torch.nn.functional as F import torch.optim as optim class PointNetCls(nn.Module): def __init__(self, k=40): super(PointNetCls, self).__init__() self.k = k self.conv1 = nn.Conv1d(3, 64, 1) self.conv2 = nn.Conv1d(64, 128, 1) self.conv3 = nn.Conv1d(128, 1024, 1) self.fc1 = nn.Linear(1024, 512) self.fc2 = nn.Linear(512, 256) self.fc3 = nn.Linear(256, k) def forward(self, x): batchsize = x.size()[0] x = F.relu(self.conv1(x)) x = F.relu(self.conv2(x)) x = F.relu(self.conv3(x)) x = torch.max(x, 2, keepdim=True)[0] x = x.view(-1, 1024) x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) x = self.fc3(x) return F.log_softmax(x, dim=1) ``` 具体来讲,我们先使用三个卷积层提取特征信息,然后使用 max pooling 进行池化,最后通过三个全连接层将提取的特征映射到具体的分类标签。特别的,我们将最后一层的输出使用 softmax 函数来进行分类。 训练过程如下: ```python device = torch.device("cuda" if torch.cuda.is_available() else "cpu") model = PointNetCls().to(device) optimizer = optim.Adam(model.parameters(), lr=0.001) for epoch in range(300): model.train() for batch_id, (data, label) in enumerate(train_loader): optimizer.zero_grad() data, label = data.to(device), label.to(device) pred = model(data) loss = F.nll_loss(pred, label) loss.backward() optimizer.step() print(f'Epoch {epoch}: Training Loss: {loss.item()}') model.eval() correct = 0 for data, label in test_loader: data, label = data.to(device), label.to(device) pred = model(data) pred = pred.data.max(1)[1] correct += pred.eq(label.data).cpu().sum() accuracy = correct.item() / float(len(test_loader.dataset)) print(f'Epoch {epoch}: Testing Accuracy: {accuracy}') ``` 可以看到,在训练阶段我们使用 Adam 优化器来优化模型,并使用负对数似然对数函数作为损失函数。在测试阶段我们将模型设置为评价模式,并使用预测结果和真实标签的比对结果计算准确率。 通过以上步骤,我们已经完成了一个 PointNet 的 PyTorch 实现。当然,为了提高准确率我们还可以对模型结构进行优化,如引入 dropout、batch normalization 等结构,或者将模型拓展到 PointNet++ 等更加优秀的架构。 ### 回答3: PointNet是一种针对点云数据进行分类和分割的深度学习模型,其在处理三维几何数据方面具有很好的效果,也被广泛应用于许多领域。为了复现PointNet模型,我们可以使用Pytorch框架进行实现。下面是针对PointNet复现详细步骤: 一、准备数据 首先需要准备点云数据集,我们可以使用ShapeNet数据集的某些部分进行测试。我们需要将点云数据转化为numpy数组形式,并将其划分为训练集和验证集。 二、数据预处理 在进行训练工作之前,我们需要将点云数据进行预处理,包括点云的标准化和噪声过滤等操作。处理后的数据可以使用dataloader以batch的形式进行加载。 三、搭建模型 我们可以按照PointNet的论文模型结构进行搭建。线性变换、最大池化和ReLU激活层的堆叠是构成模型的主要部分。我们需要使用Pytorch定义模型的方法实现PointNet模型。 四、训练模型 我们可以使用Pytorch自带的优化器,如Adam优化器来训练PointNet模型。在每个epoch结束后,我们可以计算模型在验证集上的精度和准确度,以评估模型性能。 五、测试模型 完成模型训练后,我们可以使用Pytorch模型预测方法对新的未见数据进行分类和分割预测。 这些就是复现PointNet模型详细步骤。此外,还需要注意一些细节问题,例如使用GPU加速训练、采用KNN算法处理最近邻等。借助Pytorch框架,我们可以轻松地实现PointNet模型,从而应用到更多的实际场景
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏天是冰红茶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值