深度学习25:PyTorch:损失函数
目录标题一、分类任务损失函数二、回归任务损失函数三、综合测试一、分类任务损失函数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_{i1}^{n} \left( y_i \log \hat{y}_i (1 - y_i)\log(1 - \hat{y}_i) \right)L−n1i1∑n(yilogy^i(1−yi)log(1−y^i))其中y i y_iyi为真实值通常为 0 或 1y ^ i \hat{y}_iy^i为预测值表示样本i ii为 1 的概率在 PyTorch 中可使用torch.nn.BCELoss实现importtorchimporttorch.nnasnn# 真实值targettorch.tensor([[1],[0],[0]],dtypetorch.float32)# 预测值inputtorch.randn((3,1))predictiontorch.sigmoid(input)# 实例化损失函数lossnn.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_{i1}^{n}\sum_{c1}^{C} y_{i,c} \log \hat{y}_{i,c}L−n1i1∑nc1∑Cyi,clogy^i,c其中C CC是类别数y i , c y_{i,c}yi,c为真实值表示y i y_iyi是否为类别c cc通常为 0 或 1y ^ 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.目标值为顺序编码的标签inputtorch.randn(6,8)print(input)# 目标值,6个数据的类别标签(0-7)# IndexError: Target 9 is out of bounds.# target torch.tensor([1,0,2,7,5,9])targettorch.tensor([1,0,2,7,5,3])#定义损失函数lossnn.CrossEntropyLoss()print(loss(input,target))二、回归任务损失函数1MAE平均绝对误差Mean Absolute ErrorMAE也称 L1 LossL 1 n ∑ i 1 n ∣ y i − y ^ i ∣ L \frac{1}{n}\sum_{i1}^{n}|y_i - \hat{y}_i|Ln1i1∑n∣yi−y^i∣L1 Loss 对异常值鲁棒但在 0 点处不可导importtorchimporttorch.nnasnn# 1.定义数据inputtorch.randn(3,5)targettorch.randn(3,5)#MSE L1 Lossmse_loss1nn.L1Loss()print(mse_loss1(input,target))2MSE均方误差Mean Squared ErrorMSE也称 L2 LossL2 Loss 对异常值敏感遇到异常值时易发生梯度爆炸。importtorchimporttorch.nnasnn# 1.定义数据inputtorch.randn(3,5)targettorch.randn(3,5)#MSE L2 Lossmse_lossnn.MSELoss()print(mse_loss(input,target))3Smooth L1平滑 L1S 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.定义数据inputtorch.randn(3,5)targettorch.randn(3,5)#Smooth L1smooth_l1_lossnn.SmoothL1Loss()print(smooth_l1_loss(input,target))三、综合测试importtorchfromtorchimportnn,optim# 定义模型classModel(nn.Module):# 初始化def__init__(self):super().__init__()# 只定义一个全连接层self.linearnn.Linear(in_features5,out_features3)# 权重初始化(这里自定义权重,是为了观看权重变化)self.linear.weight.datatorch.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.datatorch.tensor([1.0,2.0,3.0])# 前向传播defforward(self,x):xself.linear(x)returnx# 主流程# 1. 定义数据# 输入数据 2x5Xtorch.tensor(data[[1,2,3,4,5],[6,7,8,9,10]],dtypetorch.float)# 目标值 2x3targettorch.tensor(data[[0,0,0],[0,0,0]],dtypetorch.float)# 2. 创建模型modelModel()# 3. 前向传播预测输出outputmodel(X)# 4. 定义损失函数计算损失lossnn.MSELoss()loss_valueloss(output,target)# 5. 反向传播计算梯度loss_value.backward()# 6. 定义优化器optimizeroptim.SGD(model.parameters(),lr0.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])