Logo
Section 1 / 6

反事实解释

了解反事实解释,它能够生成与原始图像相似但预测结果不同的新图像。

导入

反事实解释

了解反事实解释,它能够生成与原始图像相似但预测结果不同的新图像。

...
反事实解释
...
数字4的反事实解释

X' = \argmin_{X'} \lambda \cdot (f(X') - y')^2 + d(X, X')

1import torch 2import torch.nn as nn 3import torchvision 4import torchvision.transforms as T 5from torchvision import datasets 6from PIL import Image 7import matplotlib.pyplot as plt 8import sklearn.linear_model as lm 9import numpy as np 10 11NUM_ITERATIONS = 1000 # 采样次数 12LAMBDA = 10 13 14class Network(nn.Module): # 全连接神经网络 15 def __init__(self): 16 super(Network, self).__init__() 17 self.fc1 = nn.Linear(784, 512) 18 self.relu = nn.ReLU() # ReLU激活函数 19 self.fc2 = nn.Linear(512, 256) 20 self.fc3 = nn.Linear(256, 128,) 21 self.fc4 = nn.Linear(128, 64) 22 self.fc5 = nn.Linear(64, 10) # 输出长度为10的向量 23 def forward(self, x): 24 x = self.relu(self.fc1(x)) 25 x = self.relu(self.fc2(x)) 26 x = self.relu(self.fc3(x)) 27 x = self.relu(self.fc4(x)) 28 x = self.relu(self.fc5(x)) 29 return x 30 31# 加载MNIST测试数据集 32test_data = datasets.MNIST(root = './', train = False, transform = T.ToTensor(), download=True) 33image = test_data.data[4].float() # 从测试集中选取一个输入样本 34pil_image = T.functional.to_pil_image(image*255) 35pil_image.resize((224, 224)).save("./output/image.png") 36 37model = Network() # 加载神经网络模型 38ckpt = torch.load("./mnist_fc.pth", map_location="cpu") # 加载模型权重 39model.load_state_dict(ckpt) 40model.eval() 41 42logits = model(image.view(-1).unsqueeze(0))[0] # 前向传播 43prediction = torch.argmax(logits) # 模型预测结果 44print("原始图像的模型预测结果 : ", prediction.item()) 45target = torch.tensor(np.eye(1, 10, prediction.item())) 46 47cf = image.clone() 48cf.requires_grad = True 49 50for i in range(NUM_ITERATIONS): 51 logits = model(cf.view(-1).unsqueeze(0))[0] # 扰动输入的前向传播 52 prediction = torch.argmax(logits) 53 regularization = torch.sum(torch.abs(cf - image)) 54 top2_predictions = torch.topk(logits, 2) 55 loss = nn.functional.relu(top2_predictions[0] - top2_predictions[1]) 56 57 objective = torch.mean(LAMBDA*loss + regularization) 58 grad = torch.autograd.grad(objective, [cf])[0] 59 60 cf = cf - 0.01*grad 61 cf = torch.clip(cf, 0., 1.0) 62 63print("反事实样本的模型预测结果 : ", prediction.item()) 64cf = torch.nn.functional.interpolate(cf[None, None, :, :], (224,224), mode='bilinear') 65torchvision.utils.save_image(cf.detach(), "./output/saliency.png", normalize=True)

类别激活图

基于扰动的解释