调用Multiclass Accuracy的compute前未调用update导致指标为0
问题描述
使用torchmetrics的MulticlassAccuracy等指标时,出现警告提示compute方法在update方法之前被调用,同时所有准确率类指标输出均为0。
训练代码片段
def _train_one_epoch(self, epoch: int) -> None: self.model.train() train_running_loss = 0.0 training_progress = 0 # len of all batches total_batches = ( len(self.dataset_config.train_data) // self.training_config.batch_size ) for inputs, labels in self.train_loader: # progress bar training_progress += 1 print( f"Training Progress: [-- {training_progress/total_batches*100:.2f}% --] in epoch: {epoch} from {self.training_config.epochs} epochs", end="\r", ) # move the inputs and labels to device inputs = inputs.to(self.training_config.device) labels = labels.to(self.training_config.device) # zero the parameter gradients self.optimizer.zero_grad() # forward pass outputs = self.model(inputs) # calculate the loss loss = self.training_config.criterion(outputs, labels) # backward pass loss.backward() # update the weights self.optimizer.step() # Calculate the metrics train_running_loss += loss.item() * inputs.size(0) preds = torch.argmax(outputs, dim=1) train_epoch_loss = train_running_loss / len(self.dataset_config.train_data) # Metrics on all valid data train_accuracy = self.accuracy.compute() train_precision = self.precision.compute() train_recall = self.recall.compute() train_f1_score = self.f1_score.compute() self.writer.add_scalar("Training/Loss", train_epoch_loss, epoch) self.writer.add_scalar("Training/Accuracy", train_accuracy, epoch) self.writer.add_scalar("Training/Precision", train_precision, epoch) self.writer.add_scalar("Training/Recall", train_recall, epoch) self.writer.add_scalar("Training/F1", train_f1_score, epoch) # Reset the metrics self.accuracy.reset() self.precision.reset() self.recall.reset() self.f1_score.reset()
警告及输出内容
/home/sadegh/miniconda3/envs/ml/lib/python3.11/site-packages/torchmetrics/utilities/prints.py:36: UserWarning: The ``compute`` method of metric MulticlassAccuracy was called before the ``update`` method which may lead to errors, as metric states have not yet been updated. warnings.warn(*args, **kwargs) /home/sadegh/miniconda3/envs/ml/lib/python3.11/site-packages/torchmetrics/utilities/prints.py:36: UserWarning: The ``compute`` method of metric MulticlassPrecision was called before the ``update`` method which may lead to errors, as metric states have not yet been updated. warnings.warn(*args, **kwargs) /home/sadegh/miniconda3/envs/ml/lib/python3.11/site-packages/torchmetrics/utilities/prints.py:36: UserWarning: The ``compute`` method of metric MulticlassRecall was called before the ``update`` method which may lead to errors, as metric states have not yet been updated. warnings.warn(*args, **kwargs) /home/sadegh/miniconda3/envs/ml/lib/python3.11/site-packages/torchmetrics/utilities/prints.py:36: UserWarning: The ``compute`` method of metric MulticlassF1Score was called before the ``update`` method which may lead to errors, as metric states have not yet been updated. warnings.warn(*args, **kwargs) Validation Progress: [-- 9.68% --] in epoch: 8 from 25 epochs Epoch: 8/25 | Valid Loss: 1.9874 | Valid Accuracy: 0.0000 | Valid Precision: 0.0000 | Valid Recall: 0.0000 | Valid F1: 0.0000
查看torchmetrics文档后发现示例中并未调用update方法,请问问题出在哪里?
问题原因及解决办法
核心问题
你没有调用指标的update()方法来累积每个batch的预测结果和真实标签。torchmetrics的指标需要通过update()更新内部状态,之后compute()才能计算出正确的全局指标值。
文档示例没显式调用update(),是因为很多示例采用了自动更新的场景:
- 将指标作为
torch.nn.Module的一部分,通过直接调用指标实例(触发__call__方法)自动执行update - 结合
MetricCollection或PyTorch Lightning等框架时,框架会自动处理指标更新逻辑
而你的代码是手动管理指标实例,必须显式调用update()。
修正代码
在每个batch的循环内,计算出preds之后,添加指标更新操作:
# Calculate the metrics train_running_loss += loss.item() * inputs.size(0) preds = torch.argmax(outputs, dim=1) # 新增:更新各指标的内部状态 self.accuracy.update(preds, labels) self.precision.update(preds, labels) self.recall.update(preds, labels) self.f1_score.update(preds, labels)
修改后,每个batch的预测和标签数据会被传入指标累积计算,后续调用compute()就能得到正确的epoch指标值,警告也会消失。
内容的提问来源于stack exchange,提问作者sadegh-pz
相关产品推荐
相关产品推荐

