Captum. Librería para interpretabilidad en PyTorch

Esta entrada es parte del curso de Deep learning con PyTorch.

Captum es una librería de PyTorch para proporcionar interpretabilidad a los modelos de deep learning. Con la complejidad de los actuales modelos de deep learning, la interpretabilidad y explicabilidad de los modelos es clave. Los algoritmos de interpretabilidad de Captum se separan en tres grupos:

  • Atribución primaria: Evalúa la contribución de cada parte de la entrada a la salida.
  • Atribución de capa: Evalúa la contribución de cada neurona de una capa a la salida.
  • Atribución de neurona: Evalúa la contribución de cada parte de la entrada en la activación de cualquier neurona oculta.

En este post vamos a analizar el método de gradiente integrado (integrated gradient) que pertenece a los algoritmos de atribución primaria.

El gradiente integrado, explicado en este artículo, calcula la integral de los gradientes de la salida respecto a la entrada a lo largo de la trayectoria que va desde la línea base a la entrada. De esta forma, calcula qué elementos de la entrada producen un mayor cambio en la salida y puede asignarles una atribución. En este post, vamos a ver un ejemplo. Primero instalamos la librería Captum con el comando pip.

!pip install captum

Creamos un modelo ejemplo sobre el cuál aplicaremos el método de gradiente integrado, creamos una instancia del modelo y vemos los parámetros. En este caso el modelo es una simple capa lineal con rectificación.

import torch
import torch.nn as nn
import captum
from captum.attr import IntegratedGradients

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()                    
        self.fc1 = nn.Linear(5, 1)  
        self.relu1 = nn.ReLU()                          
    
    def forward(self, x):                              
        out = self.fc1(x)
        out = self.relu1(out)
        return out


net = Net()
net.eval()

Net(
  (fc1): Linear(in_features=5, out_features=1, bias=True)
  (relu1): ReLU()
)

for name, param in net.named_parameters():
        print (name, param.data)
fc1.weight tensor([[ 0.1529, -0.2725, -0.1739,  0.3921,  0.2883]])
fc1.bias tensor([0.3977])

Después creamos un tensor entrada y un tensor línea de base. En muchos problemas se coge el tensor cero como línea base. Creamos una instancia del algoritmo de gradiente integrado pasándole la instancia del modelo creado. Finalmente llamamos al método de la instancia para que calcule las atribuciones de las diferentes entradas del modelo usando el tensor entrada y la línea de base creadas.

input=torch.rand(1,5)
baseline=torch.zeros(1,5)

ig = IntegratedGradients(net)

attributions, delta = ig.attribute(input, baseline, target=0, return_convergence_delta=True)
print('IG Attributions:', attributions)
print('Convergence Delta:', delta)
IG Attributions: tensor([[ 0.1125, -0.0341, -0.1563,  0.1409,  0.1620]])
Convergence Delta: tensor([0.])

El algoritmo nos proporciona dos conjuntos de valores:

  • Una delta de convergencia que cuantifica el error de aproximación. Cuanto menor es la delta, mejor la aproximación.
  • Un score de aproximación para cada elemento de la entrada. Una atribución positiva significa que dicho elemento contribuye de manera positiva a la predicción final, negativa lo contrario y cero que no contribuye.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Orgullosamente ofrecido por WordPress | Tema: Baskerville 2 por Anders Noren.

Subir ↑

A %d blogueros les gusta esto: