PyTorch训练DistilBERT五分类器时遇'torch.device'不可调用错误
这个TypeError: 'torch.device' object is not callable错误,核心是你把一个torch.device对象当成函数来调用了。单批次测试没问题,说明问题出在训练循环的上下文或者全局变量的复用/覆盖上,下面是几个重点排查方向:
检查device变量的调用方式
你肯定定义过类似device = torch.device("cuda" if torch.cuda.is_available() else "cpu")的代码,但大概率在训练循环里某个地方误写成了device(),比如把模型或数据移到设备时,写了model.to(device()),正确的写法是model.to(device)。单批次测试时你可能没犯这个错,或者测试代码和训练循环的代码有细微差别。排查是否有变量覆盖device
训练循环里可能有其他变量不小心占用了device这个名字,比如某个函数的参数叫device,或者循环内部把device重新赋值成了别的对象。举个例子:# 错误示例: def train_step(device): # 这里的device参数直接覆盖了全局的torch.device对象 ... # 或者循环里: for batch in train_loader: device = batch.get('device') # 如果batch里有个叫device的字段,直接把原来的device覆盖了 inputs = inputs.to(device()) # 这里自然会报错对比单批次测试和训练循环的作用域差异
单批次测试可能是在全局作用域跑的,而训练循环可能封装在函数里,导致device变量的作用域变了——比如函数内部没正确引用全局的device,反而创建了一个同名的错误对象。检查优化器相关的设备操作
有些新手会给优化器做移设备操作,比如误写optimizer.to(device()),实际上优化器不需要手动移设备,它会自动跟着模型参数的设备走,就算要操作,也应该用device而不是device()。
最快的排查方法是全局搜索代码里的device(),把所有这种写法改成device;然后检查所有命名为device的变量,看有没有被意外覆盖的情况。如果还是找不到,把训练循环里涉及设备的代码和单批次测试的代码逐行对比,差异点就是问题所在。
内容的提问来源于stack exchange,提问作者Yaovi

