目录标题
- 一、分类任务损失函数
- 二、回归任务损失函数
- 三、综合测试
一、分类任务损失函数
1)二分类任务损失函数
二分类任务常用二元交叉熵损失函数(Binary Cross-Entropy Loss)。
L = − 1 n ∑ i = 1 n ( y i log y ^ i + ( 1 − y i ) log ( 1 − y ^ i ) ) L = -\frac{1}{n}\sum_{i=1}^{n} \left( y_i \log \hat{y}_i + (1 - y_i)\log(1 - \hat{y}_i) \right)L=−n1i=1∑n(yilogy^i+(1−yi)log(1−y^i))
其中:
y i y_iyi为真实值(通常为 0 或 1)
y ^ i \hat{y}_iy^i为预测值(表示样本i ii为 1 的概率)
在 PyTorch 中可使用torch.nn.BCELoss实现:
importtorchimporttorch.nnasnn# 真实值target=torch.tensor([[1],[0],[0]],dtype=torch.float32)# 预测值input=torch.randn((3,1))prediction=torch.sigmoid(input)# 实例化损失函数loss=nn.BCELoss()print(loss(prediction,target))2)多分类任务损失函数
多分类任务常用多类交叉熵损失函数(Categorical Cross-Entropy Loss)。它是对每个类别的预测概率与真实标签之间差异的加权平均。
L = − 1 n ∑ i = 1 n ∑ c = 1 C y i , c log y ^ i , c L = -\frac{1}{n}\sum_{i=1}^{n}\sum_{c=1}^{C} y_{i,c} \log \hat{y}_{i,c}L=−n1i=1∑nc=1∑Cyi,clogy^i,c
其中:
C CC是类别数
y i , c y_{i,c}yi,c为真实值(表示y i y_iyi是否为类别c cc,通常为 0 或 1)
y ^ i , c \hat{y}_{i,c}y^i,c为预测值(表示样本i ii为类别c cc的概率)
在 PyTorch 中可使用torch.nn.CrossEntropyLoss实现:
注意:调用torch.nn.CrossEntropyLoss相当于调用了torch.nn.LogSoftmax之后再调用torch.nn.NLLLoss。即使用CrossEntropyLoss时上一层的输出不需要Softmax激活函数,因为该损失函数内会自动处理。
importtorchimporttorch.nnasnn# 1.目标值为顺序编码的标签input=torch.randn(6,8)print(input)# 目标值,6个数据的类别标签(0-7)# IndexError: Target 9 is out of bounds.# target = torch.tensor([1,0,2,7,5,9])target=torch.tensor([1,0,2,7,5,3])#定义损失函数loss=nn.CrossEntropyLoss()print(loss(input,target))二、回归任务损失函数
1)MAE
平均绝对误差(Mean Absolute Error,MAE),也称 L1 Loss:
L = 1 n ∑ i = 1 n ∣ y i − y ^ i ∣ L = \frac{1}{n}\sum_{i=1}^{n}|y_i - \hat{y}_i|L=n1i=1∑n∣yi−y^i∣
L1 Loss 对异常值鲁棒,但在 0 点处不可导
importtorchimporttorch.nnasnn# 1.定义数据input=torch.randn(3,5)target=torch.randn(3,5)#MSE L1 Lossmse_loss1=nn.L1Loss()print(mse_loss1(input,target))2)MSE
均方误差(Mean Squared Error,MSE),也称 L2 Loss:
L2 Loss 对异常值敏感,遇到异常值时易发生梯度爆炸。
importtorchimporttorch.nnasnn# 1.定义数据input=torch.randn(3,5)target=torch.randn(3,5)#MSE L2 Lossmse_loss=nn.MSELoss()print(mse_loss(input,target))3)Smooth L1
平滑 L1:
S m o o t h L 1 = { 1 2 ( y i − y ^ i ) 2 , ∣ y i − y ^ i ∣ < 1 ∣ y i − y ^ i ∣ − 1 2 , ∣ y i − y ^ i ∣ ≥ 1 Smooth\ L1 = \begin{cases} \frac{1}{2}(y_i - \hat{y}_i)^2, & |y_i - \hat{y}_i| < 1 \\ |y_i - \hat{y}_i| - \frac{1}{2}, & |y_i - \hat{y}_i| \ge 1 \end{cases}SmoothL1={21(yi−y^i)2,∣yi−y^i∣−21,∣yi−y^i∣<1∣yi−y^i∣≥1
当误差较小时(( ∣ y i − y ^ i ∣ < 1 (|y_i - \hat{y}_i| < 1(∣yi−y^i∣<1))使用 L2 Loss,使得损失函数平滑可导。当误差较大时(( ∣ y i − y ^ i ∣ ≥ 1 (|y_i - \hat{y}_i| \ge 1(∣yi−y^i∣≥1))使用 L1 Loss 降低异常值的影响。
importtorchimporttorch.nnasnn# 1.定义数据input=torch.randn(3,5)target=torch.randn(3,5)#Smooth L1smooth_l1_loss=nn.SmoothL1Loss()print(smooth_l1_loss(input,target))三、综合测试
importtorchfromtorchimportnn,optim# 定义模型classModel(nn.Module):# 初始化def__init__(self):super().__init__()# 只定义一个全连接层self.linear=nn.Linear(in_features=5,out_features=3)# 权重初始化(这里自定义权重,是为了观看权重变化)self.linear.weight.data=torch.tensor([[0.1,0.2,0.3],[0.4,0.5,0.6],[0.7,0.8,0.9],[1.0,1.1,1.2],[1.3,1.4,1.5]]).T self.linear.bias.data=torch.tensor([1.0,2.0,3.0])# 前向传播defforward(self,x):x=self.linear(x)returnx# 主流程# 1. 定义数据# 输入数据 2x5X=torch.tensor(data=[[1,2,3,4,5],[6,7,8,9,10]],dtype=torch.float)# 目标值 2x3target=torch.tensor(data=[[0,0,0],[0,0,0]],dtype=torch.float)# 2. 创建模型model=Model()# 3. 前向传播,预测输出output=model(X)# 4. 定义损失函数,计算损失loss=nn.MSELoss()loss_value=loss(output,target)# 5. 反向传播,计算梯度loss_value.backward()# 6. 定义优化器optimizer=optim.SGD(model.parameters(),lr=0.1)# 7. 更新参数optimizer.step()optimizer.zero_grad()#打印模型参数 (看看经过一步迭代后参数变化)forparamNameinmodel.state_dict():print(paramName)print(model.state_dict()[paramName])''' 打印结果和原始参数差别很大 linear.weight tensor([[-6.7833, -8.0333, -9.2833, -10.5333, -11.7833], [-7.7667, -9.2667, -10.7667, -12.2667, -13.7667], [-8.7500, -10.5000, -12.2500, -14.0000, -15.7500]]) linear.bias tensor([-0.5500, 0.2000, 0.9500]) '''