在PyTorch Lightning中使用ddp后端时,对整个验证集进行验证

问题描述

我正在使用PyTorch Lightning训练图像分类模型,并在具有多个GPU的机器上运行,因此我使用推荐的分布式后端来获得最佳性能ddp(DatadistributedParallel)。这自然会拆分数据集,因此每个GPU只会看到一部分数据。

但是,对于验证,我想在整个验证集中而不是仅在一部分上计算诸如准确性之类的指标。我该怎么办?我找到了some hints in the official documentation,但它们没有按预期运行,或者使我感到困惑。发生的情况是validation_epoch_endnum_gpus调用,每次1/num_gpus个验证数据。我想汇总所有结果,并且只运行一次validation_epoch_end

他们在this section中指出,使用dp / ddp2时,您可以添加一个名为如下的附加功能

def validation_step(self,batch,batch_idx):
    loss,x,y,y_hat = self.step(batch)
    return {"val_loss": loss,'y': y,'y_hat': y_hat}

def validation_step_end(self,self,*args,**kwargs):
    # do something here,I'm not sure what,# as it gets called in ddp directly after validation_step with the exact same values
    return args[0]

但是,结果未汇总,validation_epoch_end仍被调用num_gpu次。 ddp无法使用这种行为吗?还有其他方法可以实现这种聚合行为吗?

解决方法

training_epoch_end()validation_epoch_end() 汇总来自特定过程的所有训练/验证批次的数据。他们只是为您在每个训练或验证步骤中返回的内容创建一个列表。

使用 DDP 后端时,每个 GPU 都会运行一个单独的进程。没有简单的方法来访问另一个进程正在处理的数据,但是有一种机制可以在进程之间同步特定的张量。最简单的方法是分块计算度量,然后例如通过取平均值来同步张量。当您使用 self.log() 时,sync_dist=True 调用将 automatically synchronize the value between GPUs。值的同步方式由 reduce_fx 参数决定,默认情况下为 torch.mean

如果您也对按批次平均指标感到满意,则无需覆盖 training_epoch_end()validation_epoch_end()self.log() 将为您进行平均。

还可以在每一步更新一些状态变量,然后定义一个自定义指标,该指标将在每个时期后根据您保存的值进行计算。推荐的方法是创建一个派生自 Metric 类(现已移至 TorchMetrics 项目)的类。使用 add_state() 在构造函数中添加状态变量并覆盖 update()compute() 方法。 API 将负责同步进程之间的状态变量。

TorchMetrics 中已经有一个准确度指标,source code 是如何使用 API 的一个很好的例子。

,

我认为您正在寻找training_step_end / validation_step_end

...因此,当Lightning调用training_step,validation_step,test_step中的任何一个时,您将只对其中之一进行操作。 (...)对于大多数指标而言,这并不重要。但是,如果您想使用所有批处理零件在计算图中添加一些内容(例如softmax),则可以使用training_step_end步骤。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...