모든 설치가 끝나면 한글 폰트를 바르게 출력하기 위해 [런타임] -> **[런타임 다시시작]**을 클릭한 다음, 아래 셀부터 코드를 실행해 주십시오.
# 라이브러리 임포트%matplotlib inlineimport numpy as npimport matplotlib.pyplot as plt# from IPython.display import display# 폰트 관련 용도import matplotlib.font_manager as fm# Colab, Linux# 나눔 고딕 폰트의 경로 명시path = '/usr/share/fonts/truetype/nanum/NanumGothic.ttf'font_name = fm.FontProperties(fname=path, size=10).get_name()# Window# font_name = "NanumBarunGothic"# Mac# font_name = "AppleGothic"
# 기본 폰트 설정plt.rcParams['font.family'] = font_name # window font# 기본 폰트 사이즈 변경plt.rcParams['font.size'] = 14# 기본 그래프 사이즈 변경plt.rcParams['figure.figsize'] = (6,6)# 기본 그리드 표시# 필요에 따라 설정할 때는, plt.grid()plt.rcParams['axes.grid'] = Trueplt.rcParams["grid.linestyle"] = ":"# 마이너스 기호 정상 출력plt.rcParams['axes.unicode_minus'] = False# 넘파이 부동소수점 자릿수 표시np.set_printoptions(suppress=True, precision=4)
Import modules
import osimport numpy as npimport matplotlib.pyplot as pltimport torchfrom torch import nn, optimimport torch.nn.functional as Ffrom torchvision import datasets, transformsfrom torch.utils.data import DataLoaderimport ipdb
np.random.seed(123)torch.manual_seed(123)
<torch._C.Generator at 0x26338c6f8f0>
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")print(f"device = {device}")
device = cuda
Define model architecture
class ConvNet(nn.Module): def __init__(self): super(ConvNet, self).__init__() self.cn1 = nn.Conv2d(1, 16, 3, 1) self.cn2 = nn.Conv2d(16, 32, 3, 1) self.dp1 = nn.Dropout2d(0.10) self.dp2 = nn.Dropout2d(0.25) self.fc1 = nn.Linear(4608, 64) # 4608 is basically 12 X 12 X 32 self.fc2 = nn.Linear(64, 10) def forward(self, x): x = self.cn1(x) x = F.relu(x) x = self.cn2(x) x = F.relu(x) x = F.max_pool2d(x, 2) x = self.dp1(x) x = torch.flatten(x, 1) x = self.fc1(x) x = F.relu(x) x = self.dp2(x) x = self.fc2(x) op = F.log_softmax(x, dim=1) return op
Define training and inference routines
def train(model, device, train_dataloader, optim, epoch): model.train() for b_i, (X, y) in enumerate(train_dataloader): X, y = X.to(device), y.to(device) pred_prob = model(X) loss = F.nll_loss(pred_prob, y) # nll is the negative likelihood loss optim.zero_grad() loss.backward() optim.step() if b_i % 100 == 0: print('epoch: {} [{}/{} ({:.0f}%)]\t training loss: {:.6f}'.format( epoch, b_i * len(X), len(train_dataloader.dataset), 100. * b_i / len(train_dataloader), loss.item()))
def test(model, device, test_dataloader): model.eval() loss = 0 success = 0 with torch.no_grad(): for X, y in test_dataloader: X, y = X.to(device), y.to(device) pred_prob = model(X) loss += F.nll_loss(pred_prob, y).item() # loss summed across the batch pred = pred_prob.argmax(dim=1) # us argmax to get the most likely prediction # ipdb.set_trace() # success += pred.eq(y.view_as(pred)).sum().item() success += (pred == y).float().mean() loss /= len(test_dataloader) success /= len(test_dataloader) print('\nTest dataset: Overall Loss: {:.4f}, Overall Accuracy: {:.3f}%'.format( loss, 100. * success))
Create data loaders
# The mean and standard deviation values are calculated as the mean of all pixel values of all images in the training datasetpath = os.path.join(os.getcwd(), "data")train_dataloader = torch.utils.data.DataLoader( datasets.MNIST(path, train=True, download=True, transform=transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.1302,), (0.3069,))])), # train_X.mean()/256. and train_X.std()/256. batch_size=32, shuffle=True)test_dataloader = torch.utils.data.DataLoader( datasets.MNIST(path, train=False, transform=transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.1302,), (0.3069,)) ])), batch_size=500, shuffle=True)
idx = np.random.randint(0, len(sample_targets))sample_data = sample_data.to(device)print(f"Model prediction is : {model(sample_data).data.max(1)[1][idx]}")print(f"Ground truth is : {sample_targets[idx]}")
for i in range(len(model_children_list)): if type(model_children_list[i]) == nn.Conv2d: model_parameters.append(model_children_list[i].weight) convolutional_layers.append(model_children_list[i])# len(model_parameters) # 2# len(model_parameters[0]) # 16# len(model_parameters[1]) # 32
idx = np.random.randint(0, per_layer_results[0].shape[0]) # (0, 500)plt.figure(figsize=(5, 4))layer_visualisation = per_layer_results[0][idx, ...] # torch.Size([16, 26, 26])layer_visualisation = layer_visualisation.dataprint(layer_visualisation.size())print(type(layer_visualisation))for i, flt in enumerate(layer_visualisation): plt.subplot(4, 4, i + 1) plt.imshow(flt.cpu().detach(), cmap='gray') plt.axis("off")plt.show()
torch.Size([16, 26, 26])
<class 'torch.Tensor'>
idx = np.random.randint(0, per_layer_results[1].shape[0]) # (0, 500)plt.figure(figsize=(5, 8))layer_visualisation = per_layer_results[1][idx, :, :, :]layer_visualisation = layer_visualisation.dataprint(layer_visualisation.size())for i, flt in enumerate(layer_visualisation): plt.subplot(8, 4, i + 1) plt.imshow(flt.cpu().detach(), cmap='gray') plt.axis("off")plt.show()
torch.Size([32, 24, 24])
Captum
import modules
from captum.attr import IntegratedGradientsfrom captum.attr import Saliencyfrom captum.attr import DeepLiftfrom captum.attr import visualization as viz
sample_data = sample_data.to(device)print(f"Model prediction is : {model(sample_data).data.max(1)[1][0]}")print(f"Ground truth is : {sample_targets[0]}")
orig_image = np.tile(np.transpose((sample_data[0].cpu().detach().numpy() / 2) + 0.5, (1, 2, 0)), (1,1,3))print(orig_image.shape)# tmp = np.transpose((sample_data[0].cpu().detach().numpy() / 2) + 0.5, (1, 2, 0))# orig_image = np.concatenate([tmp, np.zeros(tmp.shape), np.zeros(tmp.shape)], axis=2)_ = viz.visualize_image_attr(None, orig_image, cmap='gray', method="original_image", title="Original Image") # a function that visualizes attribution maps over an image.
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers). Got range [0.28787878..1.9106851].
(28, 28, 3)
c:\Users\user\anaconda3\envs\torchgpu_py3.12\Lib\site-packages\torch\nn\functional.py:1538: UserWarning: dropout2d: Received a 2-D input to dropout2d, which is deprecated and will result in an error in a future release. To retain the behavior and silence this warning, please use dropout instead. Note that dropout2d exists to provide channel-wise dropout on inputs with 2 spatial dimensions, a channel dimension, and an optional batch dimension (i.e. 3D or 4D inputs).
warnings.warn(warn_msg)
c:\Users\user\anaconda3\envs\torchgpu_py3.12\Lib\site-packages\captum\attr\_utils\visualization.py:51: UserWarning: Attempting to normalize by value approximately 0, visualized resultsmay be misleading. This likely means that attribution values are allclose to 0.
warnings.warn(
integ_grads = IntegratedGradients(model) # IG accumulates gradients over multiple interpolated inputs between x and x' making it more reliable than raw gradients.attributed_ig, delta = integ_grads.attribute(captum_input, target=sample_targets[0].item(), baselines=captum_input * 0, return_convergence_delta=True)attributed_ig = np.reshape(attributed_ig.squeeze().cpu().detach().numpy(), (28, 28, 1))_ = viz.visualize_image_attr(attributed_ig, orig_image, method="blended_heat_map", sign="all", show_colorbar=True, title="Overlayed Integrated Gradients")
c:\Users\user\anaconda3\envs\opencv_torch_py3.12\Lib\site-packages\torch\nn\functional.py:1538: UserWarning: dropout2d: Received a 2-D input to dropout2d, which is deprecated and will result in an error in a future release. To retain the behavior and silence this warning, please use dropout instead. Note that dropout2d exists to provide channel-wise dropout on inputs with 2 spatial dimensions, a channel dimension, and an optional batch dimension (i.e. 3D or 4D inputs).
warnings.warn(warn_msg)
c:\Users\user\anaconda3\envs\torchgpu_py3.12\Lib\site-packages\captum\attr\_core\deep_lift.py:304: UserWarning: Setting forward, backward hooks and attributes on non-linear
activations. The hooks and attributes will be removed
after the attribution is finished
warnings.warn(
c:\Users\user\anaconda3\envs\torchgpu_py3.12\Lib\site-packages\torch\nn\functional.py:1538: UserWarning: dropout2d: Received a 2-D input to dropout2d, which is deprecated and will result in an error in a future release. To retain the behavior and silence this warning, please use dropout instead. Note that dropout2d exists to provide channel-wise dropout on inputs with 2 spatial dimensions, a channel dimension, and an optional batch dimension (i.e. 3D or 4D inputs).
warnings.warn(warn_msg)
c:\Users\user\anaconda3\envs\torchgpu_py3.12\Lib\site-packages\captum\attr\_utils\visualization.py:51: UserWarning: Attempting to normalize by value approximately 0, visualized resultsmay be misleading. This likely means that attribution values are allclose to 0.
warnings.warn(