在深度学习中, 损失反映模型最后预测结果与实际真值之间的差距, 可以用来分析训练过程的好坏、 模型是否收敛等, 例如均方损失、交叉熵损失等。 在PyTorch中, 损失函数可以看做是网络的某一层而放到模型定义中, 但在实际使用时更偏向于作为功能函数而放到前向传播过程中。
PyTorch在torch.nn及torch.nn.functional中都提供了各种损失函数,通常来讲, 由于损失函数不含有可学习的参数, 因此这两者在功能上基本没有区别。
perception.py
1 import torch 2 from torch import nn 3 4 # 首先建立一个全连接的子module, 继承nn.Module 5 class Linear(nn.Module): 6 7 def __init__(self, in_dim, out_dim): 8 super(Linear, self).__init__() # 调用nn.Module的构造函数 9 10 # 使用nn.Parameter来构造需要学习的参数 11 self.w = nn.Parameter(torch.randn(in_dim, out_dim)) 12 self.b = nn.Parameter(torch.randn(out_dim)) 13 14 def forward(self, x): 15 x = x.matmul(self.w) # 使用Tensor.matmul实现矩阵相乘 16 y = x +self.b.expand_as(x) # 使用Tensor.expand_as()来保证矩阵 17 18 # 形状一致 19 return y 20 21 # 构建感知机类, 继承nn.Module, 并调用了Linear的子module 22 class Perception(nn.Module): 23 def __init__(self, in_dim, hid_dim, out_dim): 24 super(Perception, self).__init__() 25 self.layer1 = Linear(in_dim, hid_dim) 26 self.layer2 = Linear(hid_dim, out_dim) 27 28 def forward(self, x): 29 x = self.layer1(x) 30 y = torch.sigmoid(x) 31 32 y = self.layer2(y) 33 y = torch.sigmoid(y) 34 35 return y
test.py
1 import torch 2 from perception import Perception 3 4 from torch import nn 5 import torch.nn.functional as F 6 7 # 实例化一个网络, 并赋值全连接中的维数, 最终输出二维代表了二分类 8 p = Perception(2, 3, 2) 9 # 可以看到perception中包含上述定义的layer1与layer2 10 11 # named_parameters()可以返回学习参数的迭代器, 分别为参数名与参数值 12 for name, parameter in p.named_parameters(): 13 print(name, parameter) 14 15 16 # 随机生成数据, 注意这里的4代表了样本数为4, 每个样本有两维 17 data = torch.randn(4, 2) 18 print(data, data.size()) 19 20 # 将输入数据传入p, p()相当于调用perception中的forward()函数 21 output = p(data) 22 print(output) 23 24 # 设置标签, 由于是二分类, 一共有4个样本, 因此标签维度为1*4, 每个数为0或1两个类别 25 label = torch.Tensor([0, 1, 1, 0]).long() 26 # 实例化nn中的交叉熵损失类 27 criterion = nn.CrossEntropyLoss() 28 # 实例化nn中的交叉熵损失类 29 loss_nn = criterion(output, label) 30 print(loss_nn) 31 32 # 由于F.cross_entropy是一个函数, 因此可以直接调用, 不需要实例化, 两者求得的损失值相同 33 loss_functional = F.cross_entropy(output, label) 34 print(loss_functional)