1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
| class NeuralNet(nn.Module): def __init__(self, input_size, hidden_size, num_classes): super(NeuralNet, self).__init__() self.fc1 = nn.Linear(input_size, hidden_size) self.relu = nn.ReLU() self.fc2 = nn.Linear(hidden_size, num_classes)
def forward(self, x): out = self.fc1(x) out = self.relu(out) out = self.fc2(out) return out
def pre_grad(self,x): out = self.fc1(x) out = self.relu(out) out = self.fc2(out) return out
model = NeuralNet(input_size, hidden_size, num_classes).to(device)
criterion = nn.CrossEntropyLoss() optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
for epoch in range(num_epochs): for i, (images, labels) in enumerate(train_loader): images = images.reshape(-1, 28*28).to(device) images.requires_grad = True labels = labels.to(device)
outputs = model(images) loss = criterion(outputs, labels)
optimizer.zero_grad() loss.backward() print(np.shape(images.grad),images.grad[0][:5]) optimizer.step()
model.zero_grad() out = model.pre_grad(images) out.backward(torch.ones_like(out)) print(np.shape(images.grad),images.grad[0][:5]) images.grad = None
''' # 如果想要得到原始的Jacobian矩阵,需要利用one-hot向量多次backward,再把结果拼起来; 例如 x = torch.randn(2, requires_grad=True) y = x * 2 J = torch.zeros(x.shape[0],x.shape[0]) # 初始化空Jacobian矩阵 (2*2) y.backward(torch.FloatTensor([[1,0]]),retain_graph=True) # 第一行 J[:,0] = x.grad x.grad = None y.backward(torch.FloatTensor([[0,1]]),retain_graph=True) # 第二行 J[:,1] = x.grad
print(J)
# 对于这个nn,Jacobian矩阵也可以通过修改计算图pre_grad,遍历神经元再拼起来得到 ''' img = images[0].view(1,-1) img.requires_grad = True model.zero_grad() out = model.pre_grad(img) out.backward(torch.ones_like(out)) print(np.shape(img.grad),img.grad[:,:5]) img.grad = None
|