Преглед изворни кода

added scripts for 2nd part of homework

Zan Klanecek пре 3 година
родитељ
комит
3541196b38

+ 64 - 0
5-naloga-cnn-klasifikacija-covid-slik/visualize_convolutions.py

@@ -0,0 +1,64 @@
+import json
+import torch
+from model import ModelCT
+from datareader import DataReader
+from torch.utils.data import DataLoader
+from matplotlib import pyplot as plt
+import torch.nn.functional as F
+import numpy as np
+import os
+
+# Razred za shranjevanje konvolucij
+class SaveOutput:
+    def __init__(self):
+        self.outputs = []
+        
+    def __call__(self, module, module_in, module_out):
+        self.outputs.append(module_out)
+        
+    def clear(self):
+        self.outputs = []
+if __name__ == '__main__':
+    
+    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
+    
+    # Nalozimo testne podatke
+    main_path_to_data = "C:/Users/Klanecek/Desktop/processed" 
+    model_folder = "trained_models/testrun123_v2"
+    with open (os.path.join(main_path_to_data, "test_info.json")) as fp:
+            test_info = json.load(fp) 
+    
+    # Nalozimo model, ki ga damo v eval mode
+    model = ModelCT()
+    model.to(device)
+    model.load_state_dict(torch.load(os.path.join(model_folder, "trained_model_weights.pth")))
+    model.eval()
+
+    # Inicializiramo razred v SO in registriramo kavlje v nasem modelu
+    SO = SaveOutput()
+    for layer in model.modules():
+        if isinstance(layer, torch.nn.modules.conv.Conv2d):
+            handle = layer.register_forward_hook(SO)
+
+    # Naredimo test_generator z batch_size=1
+    test_datareader = DataReader(main_path_to_data, test_info)
+    test_generator = DataLoader(test_datareader, batch_size=1, shuffle=False, pin_memory=True, num_workers=2)
+
+    # Vzamemo prvi testni primer npr.
+    item_test = next(iter(test_generator))
+    # Propagiramo prvi testni primer skozi mrezo, razred SaveOutput si shrani vse konvolucije
+    input_image = item_test[0].to(device)
+    _ = model(input_image)
+
+    # Izberemo katero konvolucijo bi radi pogledali (color_channel bo vedno 0)
+    color_channel = 0 # indeks barvnega kanala (pri nas le 1 kanal) 
+    idx_layer = 5 # indeks konvolucijske plasti (Conv2d) - (pri nas 21) 
+    idx_convolution = 17 # indeks konvolucije na dani plasti (max odvisen od plasti)
+
+    # Vizualiziramo
+    convolution_0_5_17 = SO.outputs[idx_layer][color_channel][idx_convolution][:,:].cpu().detach().numpy()
+    plt.figure()
+    plt.imshow(np.rot90(convolution_0_5_17), cmap="gray")
+    
+    plt.figure()
+    plt.imshow(np.rot90(input_image.cpu().numpy()[0,0,:,:]),cmap="gray")

+ 19 - 0
5-naloga-cnn-klasifikacija-covid-slik/visualize_filters.py

@@ -0,0 +1,19 @@
+from model import ModelCT
+from matplotlib import pyplot as plt
+import numpy as np
+import torch
+import os
+
+device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
+
+model_folder = "trained_models/testrun123_v2/" # mapa naucenega modela
+model = ModelCT()
+model.to(device)
+model.load_state_dict(torch.load(os.path.join(model_folder, "trained_model_weights.pth")))
+model.eval()
+# Nalozimo npr. filtre iz prve konvolucijske plasti backbone.conv1
+weights = model.backbone.conv1.weight.data.cpu().numpy()
+# weights.shape = (64,1,7,7) -> 64 filtrov, z 1 kanalom, velikosti 7x7
+
+# Vizualizacija 21. filtra iz prve plasti (backbone.conv1)
+plt.imshow(weights[20,0,:,:], cmap='gray')

+ 68 - 0
5-naloga-cnn-klasifikacija-covid-slik/visualize_saliency.py

@@ -0,0 +1,68 @@
+import torch
+import numpy as np
+from captum.attr import Saliency
+from datareader import DataReader
+from model import ModelCT
+from torch.utils.data import DataLoader
+import os
+import json
+from matplotlib import pyplot as plt
+from scipy.ndimage import gaussian_filter
+
+if __name__ == "__main__":
+    # Nalozimo testne podatke
+    main_path_to_data = "C:/Users/Klanecek/Desktop/processed" 
+    model_folder = "trained_models/testrun123_v2"
+    
+    with open (os.path.join(main_path_to_data, "test_info.json")) as fp:
+            test_info = json.load(fp)   
+
+    # Nalozimo model, ga damo v eval mode
+    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
+
+    model_folder = "trained_models/testrun123_v2/" # mapa naucenega modela
+    model = ModelCT()
+    model.to(device)
+    model.load_state_dict(torch.load(os.path.join(model_folder, "trained_model_weights.pth")))
+    model.eval()
+
+    # Naredimo testni generator
+    test_datareader = DataReader(main_path_to_data, test_info)
+    test_generator = DataLoader(test_datareader, batch_size=1, shuffle=False, pin_memory = True, num_workers=2)
+
+    # Iz knjiznice captum nalozimo Saliency
+    saliency = Saliency(model)
+    
+    # V testnih podatkih poiscemo primer z dobro klasifikacijo hude okuzbe (y==1, y_hat > 0.95)
+    for item_test in test_generator:
+        
+        x, y = item_test
+        x = x.to(device)
+        y = y.to(device)
+        
+        # Forward pass
+        y_hat = model.forward(x)
+        y_hat = torch.sigmoid(y_hat)
+        
+        if int(y) == 1 and float(y_hat) > 0.95:
+            attribution = saliency.attribute(x)
+            attribution = np.rot90(attribution.detach().cpu().numpy().squeeze())
+            original = np.rot90(x.cpu().numpy().squeeze())    
+
+            # Po zelji zgladimo saliency z gaussom
+            attribution = gaussian_filter(attribution, sigma=2)
+            
+            # Vizualiziramo saliency map in originalno sliko
+            fig, (ax1, ax2) = plt.subplots(1, 2)
+            ax1.set_title("Orignal", fontweight='bold', fontsize=10)
+            ax1.imshow(original, cmap='Greys_r')
+            ax1.axis('off')
+            
+            ax2.set_title("Relativni doprinos pikslov",  fontweight='bold', fontsize=10)
+            ax2.imshow(original, cmap='gray')
+            ax2.imshow(np.ma.masked_where(attribution==0, attribution), alpha=0.8, cmap='RdBu')
+            ax2.axis('off')
+
+            break
+    
+