【发布时间】:2021-12-03 22:32:05
【问题描述】:
我写了一个简短的 sn-p 来训练一个分类模型,并学习其优化算法的学习率。在我的示例中,我尝试在内部优化循环中更新网络的权重,并使用外部优化循环(元优化)来学习权重更新的学习率。我收到了错误:
RuntimeError:梯度计算所需的变量之一已被就地操作修改:[torch.FloatTensor [3, 10]],即 AsStridedBackward0 的输出 0,版本为 12;而是预期的版本 2。提示:使用 torch.autograd.set_detect_anomaly(True) 启用异常检测以查找未能计算其梯度的操作。
我的代码 sn-p 如下(注意:我使用的是_stateless,nn 的实验性功能 API。您需要使用每晚构建的 pytorch 运行。)
import torch
from torch import nn, optim
from torch.utils.data import Dataset, DataLoader
from torch.nn.utils import _stateless
class MyDataset(Dataset):
def __init__(self, N):
self.N = N
self.x = torch.rand(self.N, 10)
self.y = torch.randint(0, 3, (self.N,))
def __len__(self):
return self.N
def __getitem__(self, idx):
return self.x[idx], self.y[idx]
class MyModel(nn.Module):
def __init__(self):
super(MyModel, self).__init__()
self.fc1 = nn.Linear(10, 10)
self.fc2 = nn.Linear(10, 3)
self.relu = nn.ReLU()
self.alpha = nn.Parameter(torch.randn(1))
self.beta = nn.Parameter(torch.randn(1))
def forward(self, x):
y = self.relu(self.fc1(x))
return self.fc2(y)
epochs = 20
N = 100
dataset = DataLoader(dataset=MyDataset(N), batch_size=10)
model = MyModel()
loss_func = nn.CrossEntropyLoss()
optim = optim.Adam([model.alpha], lr=1e-3)
params = dict(model.named_parameters())
for i in range(epochs):
model.train()
train_loss = 0
for batch_idx, (x, y) in enumerate(dataset):
logits = _stateless.functional_call(model, params, x) # predict
loss_inner = loss_func(logits, y) # loss
optim.zero_grad() # reset grad
loss_inner.backward(create_graph=True, inputs=params.values()) # compute grad
train_loss += loss_inner.item() # store loss
for k, p in params.items():
if k is not 'alpha' and k is not 'beta':
p.update = - model.alpha * p.grad
params[k] = p + p.update # update weight
print('Train Epoch: {}\tLoss: {:.6f}'.format(i, train_loss / N))
logits = _stateless.functional_call(model, params, x) # predict
loss_meta = loss_func(logits, y)
loss_meta.backward()
loss_meta.step()
从错误消息中,我了解到问题来自网络第二层权重的权重更新,这表明我的内部循环优化存在错误。任何建议将不胜感激。
【问题讨论】:
标签: pytorch