gpt4 book ai didi

python-3.x - PyTorch 运行自定义损失函数

转载 作者:行者123 更新时间:2023-12-04 12:44:05 26 4
gpt4 key购买 nike

我正在尝试通过扩展 nn.Module 来使用自定义损失函数,但我无法克服错误

element 0 of variables does not require grad and does not have a grad_fn



注意:我的标签是大小列表:num_samples,但每个批次在整个批次中都具有相同的标签,因此我们通过调用 .diag() 将整个批次的标签缩小为单个标签。

我的代码如下,基于 transfer learning tutorial :
def train_model(model, criterion, optimizer, scheduler, num_epochs=25):
since = time.time()

best_model_wts = copy.deepcopy(model.state_dict())
best_acc = 0.0

for epoch in range(num_epochs):
print('Epoch {}/{}'.format(epoch, num_epochs - 1))
print('-' * 10)

# Each epoch has a training and validation phase
for phase in ['train', 'val']:
if phase == 'train':
scheduler.step()
model.train(True) # Set model to training mode
else:
model.train(False) # Set model to evaluate mode

running_loss = 0.0
running_corrects = 0

# Iterate over data.
for data in dataloaders[phase]:
# get the inputs
inputs, labels = data
inputs = inputs.float()


# wrap them in Variable
if use_gpu:
inputs = Variable(inputs.cuda())
labels = Variable(labels.cuda())
else:
inputs = Variable(inputs)
labels = Variable(labels)

# zero the parameter gradients
optimizer.zero_grad()

# forward
outputs = model(inputs)
#outputs = nn.functional.sigmoid(outputs).round()
_, preds = torch.max(outputs, 1)
label = labels.diag().float()
preds = preds.float()
loss = criterion(preds, label)
# backward + optimize only if in training phase
if phase == 'train':
loss.backward()
optimizer.step()

# statistics
running_loss += loss.data[0] * inputs.size(0)
running_corrects += torch.sum(pred == label.data)

epoch_loss = running_loss / dataset_sizes[phase]
epoch_acc = running_corrects / dataset_sizes[phase]

print('{} Loss: {:.4f} Acc: {:.4f}'.format(
phase, epoch_loss, epoch_acc))

# deep copy the model
if phase == 'val' and epoch_acc > best_acc:
best_acc = epoch_acc
best_model_wts = copy.deepcopy(model.state_dict())

print()

time_elapsed = time.time() - since
print('Training complete in {:.0f}m {:.0f}s'.format(
time_elapsed // 60, time_elapsed % 60))
print('Best val Acc: {:4f}'.format(best_acc))

# load best model weights
model.load_state_dict(best_model_wts)
return model

我的损失函数定义如下:
class CustLoss(nn.Module):
def __init__(self):
super(CustLoss, self).__init__()
def forward(self, outputs, labels):
return cust_loss(outputs, labels)

def cust_loss(pred, targets):
'''preds are arrays of size classes with floats in them'''
'''targets are arrays of all the classes from the batch'''
'''we sum the classes from the batch and find the num correct'''
r = torch.sum(pred == targets)
return r

然后我运行以下命令来运行模型:
model_ft = models.resnet18(pretrained=True)
for param in model_ft.parameters():
param.requires_grad = False

num_ftrs = model_ft.fc.in_features
model_ft.fc = nn.Linear(num_ftrs, 3)

if use_gpu:
model_ft = model_ft.cuda()

criterion = CustLoss()

# Observe that all parameters are being optimized
optimizer_ft = optim.SGD(model_ft.fc.parameters(), lr=0.001, momentum=0.9)

# Decay LR by a factor of 0.1 every 7 epochs
exp_lr_scheduler = lr_scheduler.StepLR(optimizer_ft, step_size=7, gamma=0.1)
model_ft = train_model(model_ft, criterion, optimizer_ft, exp_lr_scheduler,num_epochs=25)

我尝试让它与其他损失函数一起工作但无济于事。当 loss.backward() 时,我总是遇到同样的错误叫做。

据我了解,我不需要 loss.backward 的自定义实现。如果我延长 nn.Module .

最佳答案

您正在子类化 nn.Module定义一个函数,在你的例子中是损失函数。所以,当你计算 loss.backward() ,它尝试将梯度存储在损失本身而不是模型中,并且损失中没有存储梯度的变量。你的损失需要是一个函数而不是一个模块。见 Extending autograd .

你在这里有两个选择——

  • 最简单的就是直接通过cust_loss功能为 criterion train_model 的参数.
  • 您可以扩展 torch.autograd.Function定义自定义损失(如果您愿意,也可以定义向后函数)。

  • 附注- 提到需要实现自定义损失函数的backward。这并非总是如此。仅当您的损失函数在某些时候不可微时才需要它。但是,我认为您不需要这样做。

    关于python-3.x - PyTorch 运行自定义损失函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49821111/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com