es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Extrayendo características útiles de un modelo PyTorch – efficient net-3b.

Tengo una CNN de PyTorch basada en EfficientNet PyTorch (efficientnet-3b) que hace un muy buen trabajo en la clasificación binaria (más del 99%) de radiografías de tórax bastante complejas. Quiero extraer características y utilizarlas en un modelo relacionado. EfficientNet PyTorch tiene un método muy útil llamado “model.extract_features” con el ejemplo proporcionado.

features = model.extract_features(img)
print(features.shape) # torch.Size([1, 1280, 7, 7])

Funciona bien y obtengo esos resultados como se promete, pero necesito las características en una forma más parecida a [1, 516] o algo similar. Necesito la cantidad suficiente de características para discriminar de manera justa, pero sin demasiadas para que no sean difíciles de manejar. Estoy familiarizado con la técnica de agregar una capa, o una serie de capas, y terminar con una capa completamente conectada con las salidas del tamaño que necesito.

Si eso es lo que debo hacer aquí, ¿alguien puede guiarme a través del proceso, la arquitectura, etc.? Además, sería genial si la solución aprovechase el método mencionado anteriormente.

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Para convertir las características de salida de model.extract_features a la forma deseada de [1, 516] o similar, podemos agregar una capa de Global Average Pooling y una capa totalmente conectada al final de la CNN.

    Primero, necesitamos calcular el número de características de model.extract_features. En este caso, la forma es [1, 1280, 7, 7], por lo que el número total de características es 1280 x 7 x 7 = 62,720.

    A continuación, podemos agregar una capa de Global Average Pooling para reducir las dimensiones espaciales. Esta capa calcula la media de cada dimensión del mapa de características, lo que resulta en un vector de características de tamaño [1, 1280]. Esto se logra con el siguiente código:

    import torch.nn as nn
    
    class GlobalAvgPool2d(nn.Module):
        def __init__(self):
            super(GlobalAvgPool2d, self).__init__()
    
        def forward(self, x):
            return nn.functional.adaptive_avg_pool2d(x, 1).view(x.shape[0], -1)
    
    g_avg = GlobalAvgPool2d()
    features = g_avg(features)
    print(features.shape) # torch.Size([1, 1280])
    

    Ahora, tenemos un vector de características de tamaño [1, 1280]. A continuación, podemos agregar una capa totalmente conectada para reducir el número de características al tamaño deseado. Por ejemplo, si queremos 516 características, podemos usar la siguiente arquitectura:

    import torch.nn.functional as F
    
    class Classifier(nn.Module):
        def __init__(self):
            super(Classifier, self).__init__()
            self.fc1 = nn.Linear(1280, 1024)
            self.fc2 = nn.Linear(1024, 516)
    
        def forward(self, x):
            x = F.relu(self.fc1(x))
            x = self.fc2(x)
            return x
    
    classifier = Classifier()
    features = classifier(features)
    print(features.shape) # torch.Size([1, 516])
    

    Podemos combinar todos los pasos juntos para obtener el vector de características deseado utilizando el siguiente código:

    import torch
    from efficientnet_pytorch import EfficientNet
    import torch.nn as nn
    import torch.nn.functional as F
    
    class GlobalAvgPool2d(nn.Module):
        def __init__(self):
            super(GlobalAvgPool2d, self).__init__()
    
        def forward(self, x):
            return nn.functional.adaptive_avg_pool2d(x, 1).view(x.shape[0], -1)
    
    class Classifier(nn.Module):
        def __init__(self):
            super(Classifier, self).__init__()
            self.fc1 = nn.Linear(1280, 1024)
            self.fc2 = nn.Linear(1024, 516)
    
        def forward(self, x):
            x = F.relu(self.fc1(x))
            x = self.fc2(x)
            return x
    
    # cargar el modelo e imagen de entrada
    model = EfficientNet.from_pretrained('efficientnet-b3')
    img = torch.randn(1, 3, 224, 224)
    
    # extraer características con model.extract_features
    features = model.extract_features(img)
    
    # agregar Global Average Pooling
    g_avg = GlobalAvgPool2d()
    features = g_avg(features)
    
    # agregar capas totalmente conectadas
    classifier = Classifier()
    features = classifier(features)
    
    print(features.shape) # torch.Size([1, 516])
    

    Este código cargará el modelo EfficientNet-B3 y extraerá características de una imagen de entrada utilizando model.extract_features. Luego, las características se pasan por una capa de Global Average Pooling y una capa totalmente conectada para obtener la forma deseada de [1, 516].

Comments are closed.