batch_data = batches[t]
# 获取批量数据的预测结果
_,pred_traj,y_traj,pred_intent,_,_ = get_prediction_on_batch(batch_data, model, device)
# None的作用主要是在使用None的位置新增一个维度
traj_preds.append(pred_traj[0].detach()[None])
# 当我们再训练网络的时候可能希望保持一部分的网络参数不变,只对其中一部分的参数进行调整;
# 或者只训练部分分支网络,并不让其梯度对主网络的梯度造成影响,这时候我们就需要使用detach()函数来切断一些分支的反向传播
# 返回一个新的tensor,从当前计算图中分离下来的,但是仍指向原变量的存放位置, 不同之处只是requires_grad为false,得到的这个tensor永远不需要计算其梯度,不具有grad。
# 即使之后重新将它的requires_grad置为true,它也不会具有梯度grad
# 这样我们就会继续使用这个新的tensor进行计算,后面当我们进行反向传播时,到该调用detach()的tensor就会停止,不能再继续向前进行传播
# 使用detach返回的tensor和原始的tensor共同一个内存,即一个修改另一个也会跟着改变。
intent_preds.append(pred_intent[0].detach()[None])
temp_pred_list += [pred_traj]
temp_label_list += [y_traj]
temp_data_list += [batch_data]
if len(temp_pred_list) > adapt_step:
# maintains a buffer of length adapt_step containing the past adapt_step measurements for supervised adaptation
temp_pred_list = temp_pred_list[1:]
temp_label_list = temp_label_list[1:]
temp_data_list = temp_data_list[1:]
if t < adapt_step - 1:
continue
# temp_label_list1 = temp_label_list[0].detach()
# temp_pred_list1 = temp_pred_list[0].detach()
Y = temp_label_list[0]
Y_hat = temp_pred_list[0]
# detach()将数据的处理设备从其他设备(如.cuda()拿到cpu上),不会改变变量类型,转换后仍然是Tensor变量。
full_loss = (Y - Y_hat).detach().pow(2).mean().cpu().numpy().round(6) # 整体的损失值
cost_list.append(full_loss)
# torch.contiguous()方法首先拷贝了一份张量在内存中的地址,然后将地址按照形状改变后的张量的语义进行排列。
# 如果想要断开这两个变量之间的依赖(x本身是contiguous的),就要使用contiguous()针对x进行变化,感觉上就是我们认为的深拷贝。
# 当调用contiguous()时,会强制拷贝一份tensor,让它的布局和从头创建的一模一样,但是两个tensor完全没有联系。
Y_tau = Y[:, :adapt_step].contiguous().view((-1, 1))
# touch.view()方法对张量改变“形状”其实并没有改变张量在内存中真正的形状,可以理解为:
# view方法没有拷贝新的张量,没有开辟新内存,与原张量共享内存;
# view方法只是重新定义了访问张量的规则,使得取出的张量按照我们希望的形状展现。
Y_hat_tau = Y_hat[:, :adapt_step].contiguous().view((-1, 1)) # 部分数据的损失值
err = (Y_tau - Y_hat_tau).detach()
curr_cost = err.pow(2).mean().cpu().numpy()
update_epoch = 1
# IPython.embed()
# κt = 1, If jt < ξ1
# 2, If ξ1 ≤ jt < ξ2
# 0, If jt ≥ ξ2
if multiepoch_thresh[0] <= 0 <= multiepoch_thresh[1]:
if curr_cost < multiepoch_thresh[0]:
update_epoch = 1
elif curr_cost < multiepoch_thresh[1]:
update_epoch = 2
else:
update_epoch = 0
cnt[update_epoch] += 1
for cycle in range(update_epoch):
def mekf_closure(index=0):
# mekf闭包 在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。
# optimizer.zero_grad()清除了优化器中所有的x的x.grad,
# 在每次loss.backward()之前,不要忘记使用,否则之前的梯度将会累积,这通常不是我们所期望的
optimizer.zero_grad()
# optimizer.state 参数的缓存,需要用到什么参数就缓存到这个地方
dim_out = optimizer.optimizer.state['dim_out'] if 'Lookahead' in optim_name else optimizer.state['dim_out']
retain = index < dim_out - 1
Y_hat_tau[index].backward(retain_graph=retain) # 反向传播
return err
def lbfgs_closure():
optimizer.zero_grad()
temp_data = temp_data_list[0]
_, temp_pred_traj, temp_y_traj, _, _, _ = get_prediction_on_batch(temp_data, model, device)
y_tau = temp_y_traj[:, :adapt_step].contiguous().view((-1, 1))
y_hat_tau = temp_pred_traj[:, :adapt_step].contiguous().view((-1, 1))
loss = (y_tau - y_hat_tau).pow(2).mean()
loss.backward()
return loss
if 'MEKF' in optim_name:
# step()函数的作用是执行一次优化步骤,通过梯度下降法来更新参数的值。
# 因为梯度下降是基于梯度的,所以在执行optimizer.step()函数前应先执行loss.backward()函数来计算梯度
optimizer.step(mekf_closure) # 将函数作为参数传入
elif 'LBFGS' in optim_name:
optimizer.step(lbfgs_closure)
else:
torch.autograd.set_detect_anomaly(True)
loss = (Y_tau - Y_hat_tau).pow(2).mean()
loss.backward()
optimizer.step()
在运行else部分代码时,出现以下错误:
RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation: [torch.FloatTensor [64, 100]], which is output 0 of AsStridedBackward0, is at version 2; expected version 1 instead.
网上找了很多方法都无法解决,希望各位能给予解决办法,谢谢