我正在制作一个试图解决潮流问题的 GNN。为此,我一直在考虑使用名为“physical_loss”的自定义损失函数。 问题是,当使用这个损失函数时,调用 loss.backwards() 会导致错误
发生异常:RuntimeError 梯度计算所需的变量之一已通过就地操作进行了修改:[torch.FloatTensor []],它是 AsStridedBackward0 的输出 0,版本为 2832;预期版本为 2831。提示:上面的回溯显示了未能计算其梯度的操作。有问题的变量在此处或稍后在任何地方发生了更改。祝你好运! 文件“...\GNN_OPF\src rain.py”,第 60 行,train_batch loss.backward() 文件“...\GNN_OPF\src rain.py”,第 33 行,train_model epoch_loss += train_batch(data=batch, model=gnn, optimizationr=optimizer, criteria=criterion) 文件“...\GNN_OPF\src\main.py”,第 48 行,在 main 中 模型,损失,val_losses = train_model(参数,训练,val,测试) 文件“...\GNN_OPF\src\main.py”,第 58 行,位于
主要的() RuntimeError:梯度计算所需的变量之一已被就地操作修改:[torch.FloatTensor []],它是AsStridedBackward0的输出0,版本为2832;预期版本为 2831。提示:上面的回溯显示了未能计算其梯度的操作。有问题的变量在此处或稍后在任何地方发生了更改。祝你好运!
当使用Physics_crit = True时,错误出现在训练批处理函数中:
def train_batch(data, model, optimizer, criterion, physics_crit=True, device='cpu'):
model.to(device)
th.autograd.set_detect_anomaly(True)
optimizer.zero_grad()
out = model(data)
if physics_crit:
loss = physics_loss(data, out)
else:
loss = criterion(out, data.y)
loss.backward() #Error pops up when this line is called
我认为这个错误是由物理损失函数引起的:
def physics_loss(network, output, log_loss=True):
active_imbalance = output[:,0] # th.zeros(output_r.shape[0])
reactive_imbalance = output[:,1]#th.zeros(output_r.shape[0])
resist_line_total = th.multiply(network.edge_attr[:, 0], network.edge_attr[:, -1])
react_line_total = th.multiply(network.edge_attr[:, 1], network.edge_attr[:, -1])
denom = th.add(th.multiply(resist_line_total, resist_line_total),th.multiply(react_line_total, react_line_total))
conductances = th.div(resist_line_total , denom)
susceptances = th.multiply(th.div(react_line_total, denom),-1.0)
for i, x in enumerate(th.transpose(network.edge_index, 0, 1)):
angle_diff = th.sub(output[x[0],3] , output[x[1],3])
active_imbalance[x[0]] =th.sub(active_imbalance[x[0]],th.multiply(th.multiply(th.abs_(output[x[0], 2]) , th.abs_(output[x[1], 2])), th.add(th.multiply(conductances[i], th.cos(angle_diff)) , th.multiply(susceptances[i], th.sin(angle_diff)))))
reactive_imbalance[x[0]] = th.sub(reactive_imbalance[x[0]],th.multiply( th.multiply(th.abs_(output[x[0], 2]), th.abs_(output[x[1], 2])), th.sub(th.multiply(conductances[i], th.sin(angle_diff)) , th.multiply(susceptances[i], th.cos(angle_diff)))))
if log_loss:
tot_loss = th.log(th.add(1.0 , th.sum(th.add(th.multiply(active_imbalance, active_imbalance), th.multiply(reactive_imbalance, reactive_imbalance)))))
else:
tot_loss = th.sum(np.abs(active_imbalance) + np.abs(reactive_imbalance))
return tot_loss
我已经努力为每个操作使用所有火炬函数,但是在我的调试尝试中,我有理由相信是主动和被动不平衡计算导致了错误,就像我使用 Tensor 的代码的先前版本一样.detach() 在这些操作中并且它没有导致错误(因为它没有用于反向传播)。
我尝试仅对所有内容使用火炬操作(在以前的版本中,当使用内置操作时,例如:+,*,/。我得到了相同的错误,但具有不同的“版本”)并且我做了一些测试,在不同的位置分离渐变点以便尝试找出错误原因。
许多 pytorch 操作都有“就地”版本。就地操作由操作名称上额外的
_
表示。例如,.abs
进行复制,.abs_
就位。您的代码使用 th.abs_
可能会导致该错误。