一、常见损失函数的用法

本文详细介绍了多分类交叉熵、均方差、二分类交叉熵等损失函数在深度学习中的应用,展示了如何在PyTorch中实现这些损失函数,并通过实例演示了如何在MNIST数据集上训练网络,强调了损失函数在模型训练中的关键作用。

前言

定义损失函数的常用方法,其中包括多分类交叉熵、均方差、二分类交叉熵的用法。其作用包括:1.衡量模型输出值和标签值的差异;2.评估模型的预测值与真实值不一致程度;3.神经网络中优化的目标函数,损失函数越小,预测值越接近真实值,模型健壮性也越好。


一、L1-loss(MAE)、L2- loss(MSE)、smooth L1- loss、交叉熵损失函数是什么?

在这里插入图片描述

在这里插入图片描述

二、使用步骤

1.损失函数方法

代码如下(示例):

#定义损失函数,更新梯度----
loss_fn = torch.nn.CrossEntropyLoss()#多分类交叉熵不需要用激活幂函数输出
# loss_fn=torch.nn.MSELoss()#均方差
# loss_fn=torch.nn.BCELoss()#二分类交叉熵
# loss_fn=torch.nn.BCEWithLogitsLoss()#自动引入激活函数

2.代码操作

代码如下(示例):

import torch
from torchvision import datasets,transforms
from torch.utils.data import DataLoader#类时加载数据的核心,返回可迭代的数据
import os
import matplotlib.pyplot as plt


class Net(torch.nn.Module):
    def __init__(self):
        super().__init__()#继承
        self.fc1 = torch.nn.Sequential(
            torch.nn.Linear(784,256),
            torch.nn.BatchNorm1d(256),
            torch.nn.ReLU())
        #nn.Sequential 将网络层和激活函数结合起来,输出激活后的网络节点。
        #nn.Linear(in_features,out_features,bias = True )对传入数据应用线性变换
        #784,每个输入样本的大小----即为28*28,图像的像素值w*h
        # 256 每个输出样本的大小-----784通过Linear函数
        #BatchNorm1d(256),#自适应标准化-正态分布--输入值落在非线性函数敏感的区域,避免梯度消失问题产生
        #nn.ReLU() 激活函数 relu
        self.fc2 = torch.nn.Sequential(
            torch.nn.Linear(256,128),
            torch.nn.BatchNorm1d(128),
            torch.nn.ReLU())
        self.fc3 = torch.nn.Linear(128,10)
    def forward(self,x):#forward函数里面实现在前向传播运算
        # print(x.shape)
        #N,C,H,W(batchsize,channels,x,y)-->N,V
        #x.size(0)==batchsize,转换后有几行
        #最后通过x.view(x.size(0), -1)将tensor的结构转换为了(batchsize, channels*x*y),
        # 即将(channels,x,y)拉直,然后就可以和fc层连接了
        #-1指在不告诉函数有多少列的情况下,根据原tensor数据和batchsize自动分配列数。
        x = torch.reshape(x,[x.size(0),-1])#变换形状,换成2维,reshape=view
        # print(x.shape)
        y=self.fc1(x)#N,256
        y=self.fc2(y)#N,128     #y=w*sqrt(x2+bias)
        # y=self.fc3(y)#N,10
        self.y=self.fc3(y)
        y=torch.softmax(self.y,1)
        return y


if __name__ == '__main__':
    save_params = r"./save_params/parmas.pth"#保存参数
    save_net = r"./save_params/net.pth"#保存网络
    transf = transforms.Compose([transforms.ToTensor(),
             transforms.Normalize(mean=[0.5,],std=[0.5,])])
    #transforms.Compose 将transforms列表里面的transform操作进行遍历。
    #transforms.ToTensor() 灰度范围从0-255变换到0-1之间
    #transforms.Normalize把0-1变换到(-1,1),(image-mean)/std
    train_data = datasets.MNIST("./data",train=True,transform=transf,download=True)#读取训练数据
    test_data = datasets.MNIST("./data",train=False,transform=transf,download=False)#读取测试数据

    # 100涨图片,True 是否打乱,随机,给出不同的特征才能学习
    trin_loader = DataLoader(train_data,100,True)#加载数据
    test_loader = DataLoader(test_data,100,True)
    # DataLoader()
    # 利用多进程来加速batchdata的处理
    # 直观的网络输入数据结构,便于使用和扩展
    print(train_data.data.shape)
    print(train_data.targets.shape)
    print(test_data.data.shape)
    print(test_data.targets.shape)
    print(test_data.classes)

    if torch.cuda.is_available():
        device = torch.device("cuda")
    else:
        device = torch.device("cpu")

    net=Net().to(device)#网络加载器开始读取数据时的tensor变量copy一份到device所指定的cuda上去
    if os.path.exists(save_params):
        net.load_state_dict(torch.load(save_params))#只加载参数
        print("参数加载成功")
    else:
        print("No params!")
    # net = torch.load(save_net).to(device)#加载参数和网络
    # loss_fn = torch.nn.CrossEntropyLoss()#多分类交叉熵,定义损失函数,更新梯度----
    # loss_fn=torch.nn.MSELoss()#均方差
    # loss_fn=torch.nn.BCELoss()#二分类交叉熵
    loss_fn=torch.nn.BCEWithLogitsLoss()#二分类交叉熵,对输入值自动做sigmoid
    # optim = torch.optim.SGD(net.parameters(),lr=1e-3)#比较稳定
    optim = torch.optim.Adam(net.parameters(),lr=1e-3)#创建优化器
    #torch.optim.Adam  优化器
    # (net.parameters(), 待优化参数的iterable或者是定义了参数组的dict
    # lr=1e-3) 学习率或步长因子

    #测试,实时画图分析
    a = []
    b = []
    # plt.ion()
    net.train()
    for epoch in range(1):
        for i ,(x,y) in enumerate(trin_loader):
            x = x.to(device)
            y = y.to(device)
            y_ = torch.zeros(len(y), max(y) + 1).to(device)
            y_[torch.arange(len(y)), y] = 1
            out = net(x)#前向输出
            # loss = loss_fn(out,y)#求损失
            loss = loss_fn(net.y,y_)
            optim.zero_grad()#清空当前梯度
            loss.backward()#计算当前梯度
            optim.step()#沿着当前梯度更新一步
            # a.append(i)
            # b.append(loss.item())
            # plt.clf()
            # plt.plot(a,b)
            # plt.pause(0.1)
            if i%50==0:
                print("loss",loss.item())
    plt.ioff()
    plt.show()


    # 测试
    eval_loss=0
    eval_acc=0
    net.eval()
    for i,(x,y) in enumerate(test_loader):
        x = x.to(device)#x传给网络
        y = y.to(device)
        y_ = torch.zeros(len(y), max(y) + 1).to(device)
        y_[torch.arange(len(y)), y] = 1
        out = net(x)
        # loss = loss_fn(out, y)
        loss = loss_fn(out,y_)
        eval_loss += loss.item() * y.size(0)
        eval_acc += (y == torch.argmax(out, 1)).cpu().sum().item()
    avg_loss = eval_loss / len(test_data)
    avg_acc = eval_acc / len(test_data)
    print(avg_loss)
    print(avg_acc)

    if not os.path.exists("./save_params"):
        os.mkdir("./save_params")
    torch.save(net.state_dict(),"./save_params/parmas.pth")#只保存参数
    torch.save(net,"./save_params/net.pth")

总结

提示:这里对文章进行总结:

loss_fn = torch.nn.CrossEntropyLoss()#多分类交叉熵,输出不需要加激活函数。
loss_fn=torch.nn.MSELoss()#均方差、输出需要加激活函数。
loss_fn=torch.nn.BCELoss()#二分类交叉熵、输出需要加激活函数。
loss_fn=torch.nn.BCEWithLogitsLoss()#二分类交叉熵,对输入值自动做sigmoid
### 常见损失函数介绍及应用 #### 1. 均方误差 (Mean Squared Error, MSE) 均方误差是最常用的回归问题中的损失函数。该方法通过计算预测值与真实值之间差异平方的平均数来衡量模型的好坏。 \[ \text{MSE} = \frac{1}{n}\sum_{i=1}^{n}(y_i-\hat y_i)^2 \] 这种损失函数适用于连续数值型目标变量的情况,在线性回归等问题中有广泛应用[^1]。 #### 2. 交叉熵损失 (Cross Entropy Loss) 对于分类任务来说,二元或多元逻辑斯蒂回归常采用交叉熵作为评价标准: - **二类交叉熵** 当面对的是两个类别时, \[ L(y,\hat y)=-\left[y\log(\hat y)+(1-y)\log(1-\hat y)\right] \] 这里 \(y\) 表示样本的真实标签(0 或者 1),而 \(\hat y\) 则代表对应的概率估计值。 - **多类交叉熵** 如果涉及多个互斥类别,则可以使用softmax层配合下面这个公式: \[ C = -\frac{1}{n}\sum_x{\sum_j {y_j \ln a^L_j}} \] 其中\(a^L_j\)表示第j个神经元输出激活后的结果;\(y_j\)为one-hot编码形式下的期望输出向量。 #### 3. 铰链损失 (Hinge Loss) 主要用于支持向量机(SVM),特别是针对最大间隔分类器而言非常有效果的个度量方式: \[ l(y)=max(0,1−t⋅y) \] 这里的\(t∈{-1,+1}\), 而\(y=f(x)=w·x+b\) 是由权重参数决定的支持超平面位置得分【注意此处不是指Sigmoid/Swish等激活函数】. 铰链损失有助于构建具有较大边界的决策边界,并且能够很好地处理不可分的数据集情况. #### 4. BPR 损失函数 BPR(Bayesian Personalized Ranking)损失函数专为解决推荐系统的个性化排名问题设计而成。此算法旨在最大化正反馈项相对于负反馈项的概率优势,从而实现更精准的商品/内容推送服务[^2]: \[ \ell(u,i,j)=(\sigma(\hat{x}_{ui}-\hat{x}_{uj})-1)^2 \] 在这个表达式里:\(\hat{x}_{ui},\hat{x}_{uj}\)分别对应用户u对物品i和j的兴趣程度评分; σ()则是sigmoid函数用来压缩实数值到区间[0,1]内以便于解释成可能性大小. 选择恰当类型的损失函数不仅影响着机器学习项目的成败与否,同时也决定了后续调参工作的难易程度。因此理解不同种类之间的区别并掌握它们各自适用范围显得尤为重要. ```python import numpy as np def mse_loss(true_values, predicted_values): """Calculate Mean Squared Error between true and predicted values.""" return ((true_values - predicted_values)**2).mean() def binary_crossentropy_loss(true_labels, pred_probs): """Compute Binary Crossentropy loss given actual labels and prediction probabilities""" epsilon = 1e-7 # To prevent log(0) clipped_pred_probs = np.clip(pred_probs, epsilon, 1.-epsilon) losses = -(true_labels * np.log(clipped_pred_probs) + (1-true_labels)*np.log(1-clipped_pred_probs)) return losses.mean() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值