Pytorch:为什么在 nn.modules.loss 和 nn.functional 模块中都实现了损失函数?
Pytorch: Why loss functions are implemented both in nn.modules.loss and nn.functional module?
Pytorch 中的许多损失函数都在 nn.modules.loss 和 nn.functional 中实现。
例如下面两行return结果相同
import torch.nn as nn
import torch.functional as F
nn.L1Loss()(x,y)
F.l1_loss(x,y)
为什么有两个实现?
- 其他参数损失函数的一致性
- 损失函数的实例化带来了一些好处
- 否则
我将其视为部分应用情况 - 能够 "bundle" 许多具有损失函数对象的配置变量很有用。在大多数情况下,您的损失函数 必须 将 prediction
和 ground_truth
作为其参数。这使得损失函数的基本 API 相当统一。但是,它们在细节上有所不同。例如,并非每个损失函数都有一个 reduction
参数。 BCEWithLogitsLoss
has weight
and pos_weight
parameters; PoissonNLLLoss
有 log_input
、eps
。写一个像
这样的函数很方便
def one_epoch(model, dataset, loss_fn, optimizer):
for x, y in dataset:
model.zero_grad()
y_pred = model(x)
loss = loss_fn(y_pred, y)
loss.backward()
optimizer.step()
与实例化 BCEWithLogitsLoss
和 PoissonNLLLoss
一样适用。但由于需要簿记,它不能与它们的功能对应物一起工作。您必须先创建
loss_fn_packed = functools.partial(F.binary_cross_entropy_with_logits, weight=my_weight, reduction='sum')
只有这样你才能将它与上面定义的 one_epoch
一起使用。但是这个包装已经提供了面向对象的损失API,以及一些花里胡哨的东西(因为损失子类nn.Module
,你可以使用前向和后向钩子,在cpu之间移动东西和 gpu 等)。
没有文档有BCEWithLogistsLoss的代码:
class BCEWithLogitsLoss(_Loss):
def __init__(self, weight: Optional[Tensor] = None, size_average=None, reduce=None, reduction: str = 'mean',
pos_weight: Optional[Tensor] = None) -> None:
super(BCEWithLogitsLoss, self).__init__(size_average, reduce, reduction)
self.register_buffer('weight', weight)
self.register_buffer('pos_weight', pos_weight)
def forward(self, input: Tensor, target: Tensor) -> Tensor:
return F.binary_cross_entropy_with_logits(input, target,
self.weight,
pos_weight=self.pos_weight,
reduction=self.reduction)
如果不考虑参数传递,class和函数实现完全一样。但是,使用 class 实现可以使您的代码更加简洁和可读,例如
使用函数
loss_func=binary_cross_entropy_with_logits
def train(model, dataloader, loss_fn, optimizer, weight, size_average, reduce, reduction, pos_weight):
for x, y in dataloader:
model.zero_grad()
y_pred = model(x)
loss = loss_fn(y_pred, y, weight, size_average, reduce, reduction, pos_weight)
loss.backward()
optimizer.step()
使用class
loss_func = BCEWithLogitsLoss(weight, size_average, reduce, reduction, pos_weight)
def train(model, dataloader, loss_fn, optimizer):
for x, y in dataloader:
model.zero_grad()
y_pred = model(x)
loss = loss_fn(y_pred, y)
loss.backward()
optimizer.step()
如果您有多个参数或不同的损失函数,class 实现更好。
Pytorch 中的许多损失函数都在 nn.modules.loss 和 nn.functional 中实现。
例如下面两行return结果相同
import torch.nn as nn
import torch.functional as F
nn.L1Loss()(x,y)
F.l1_loss(x,y)
为什么有两个实现?
- 其他参数损失函数的一致性
- 损失函数的实例化带来了一些好处
- 否则
我将其视为部分应用情况 - 能够 "bundle" 许多具有损失函数对象的配置变量很有用。在大多数情况下,您的损失函数 必须 将 prediction
和 ground_truth
作为其参数。这使得损失函数的基本 API 相当统一。但是,它们在细节上有所不同。例如,并非每个损失函数都有一个 reduction
参数。 BCEWithLogitsLoss
has weight
and pos_weight
parameters; PoissonNLLLoss
有 log_input
、eps
。写一个像
def one_epoch(model, dataset, loss_fn, optimizer):
for x, y in dataset:
model.zero_grad()
y_pred = model(x)
loss = loss_fn(y_pred, y)
loss.backward()
optimizer.step()
与实例化 BCEWithLogitsLoss
和 PoissonNLLLoss
一样适用。但由于需要簿记,它不能与它们的功能对应物一起工作。您必须先创建
loss_fn_packed = functools.partial(F.binary_cross_entropy_with_logits, weight=my_weight, reduction='sum')
只有这样你才能将它与上面定义的 one_epoch
一起使用。但是这个包装已经提供了面向对象的损失API,以及一些花里胡哨的东西(因为损失子类nn.Module
,你可以使用前向和后向钩子,在cpu之间移动东西和 gpu 等)。
没有文档有BCEWithLogistsLoss的代码:
class BCEWithLogitsLoss(_Loss):
def __init__(self, weight: Optional[Tensor] = None, size_average=None, reduce=None, reduction: str = 'mean',
pos_weight: Optional[Tensor] = None) -> None:
super(BCEWithLogitsLoss, self).__init__(size_average, reduce, reduction)
self.register_buffer('weight', weight)
self.register_buffer('pos_weight', pos_weight)
def forward(self, input: Tensor, target: Tensor) -> Tensor:
return F.binary_cross_entropy_with_logits(input, target,
self.weight,
pos_weight=self.pos_weight,
reduction=self.reduction)
如果不考虑参数传递,class和函数实现完全一样。但是,使用 class 实现可以使您的代码更加简洁和可读,例如
使用函数
loss_func=binary_cross_entropy_with_logits
def train(model, dataloader, loss_fn, optimizer, weight, size_average, reduce, reduction, pos_weight):
for x, y in dataloader:
model.zero_grad()
y_pred = model(x)
loss = loss_fn(y_pred, y, weight, size_average, reduce, reduction, pos_weight)
loss.backward()
optimizer.step()
使用class
loss_func = BCEWithLogitsLoss(weight, size_average, reduce, reduction, pos_weight)
def train(model, dataloader, loss_fn, optimizer):
for x, y in dataloader:
model.zero_grad()
y_pred = model(x)
loss = loss_fn(y_pred, y)
loss.backward()
optimizer.step()
如果您有多个参数或不同的损失函数,class 实现更好。