[PYTHON] Grad-CAM et convolution dilatée

introduction

Grad-CAM est un bon moyen de visualiser où le modèle cherche à déterminer. Cependant, comme plainte personnelle, Grad-CAM a une faible résolution de (14,14) par rapport à la taille de l'image (224,224). La raison pour laquelle la résolution de Grad-CAM est si faible est que le modèle VGG16 a un total de 4 regroupements. Cependant, à l'exception de la couche de mise en commun, seules les caractéristiques à courte portée de l'image peuvent être extraites et les caractéristiques à longue portée ne peuvent pas être extraites. Je me suis demandé si je pouvais obtenir un Grad-CAM haute résolution en utilisant la convolution dilatée, j'ai donc créé un modèle équivalent de VGG16 qui utilise la convolution dilatée et expérimenté. En conséquence, la résolution de Grad-CAM a augmenté, mais il n'est pas revenu à la haute résolution d'origine. gradcam.jpg gradcam.jpg Gauche: Grad-CAM normal, Droite: Grad-CAM utilisant la convolution dilatée

Qu'est-ce que la convolution dilatée?

Comme le montre la figure ci-dessous, il s'agit d'une méthode de pliage d'un filtre avec des dents manquantes. Si vous augmentez dilation_rate, vous pouvez plier une longue distance avec une petite taille de filtre sans utiliser la mise en commun. Si vous l'utilisez, la taille de l'image ne sera pas réduite car le regroupement n'est pas utilisé. image.png

modèle

J'ai créé un modèle écrit en Keras ci-dessous. Ce modèle est appelé modèle dilated_VGG16 pour plus de commodité. Il peut calculer des convolutions longue distance avec une taille (224,224) en ajustant dilation_rate. Par conséquent, la résolution avant la combinaison complète a la résolution de (224,224) au lieu de (14,14). Le nom de la couche de convolution finale est «bloc5_conv3» pour Grad-CAM plus tard. Notez que le modèle VGG16 et le modèle dilated_VGG16 ont le même nombre de paramètres.

python


    inputs = Input(shape=(224,224,3))
    x = Conv2D( 64, (3, 3), padding='same', activation='relu', dilation_rate=1)(inputs)
    x = Conv2D( 64, (3, 3), padding='same', activation='relu', dilation_rate=1)(x)
    x = Conv2D(128, (3, 3), padding='same', activation='relu', dilation_rate=2)(x)
    x = Conv2D(128, (3, 3), padding='same', activation='relu', dilation_rate=2)(x)
    x = Conv2D(256, (3, 3), padding='same', activation='relu', dilation_rate=4)(x)
    x = Conv2D(256, (3, 3), padding='same', activation='relu', dilation_rate=4)(x)
    x = Conv2D(256, (3, 3), padding='same', activation='relu', dilation_rate=4)(x)
    x = Conv2D(512, (3, 3), padding='same', activation='relu', dilation_rate=8)(x)
    x = Conv2D(512, (3, 3), padding='same', activation='relu', dilation_rate=8)(x)
    x = Conv2D(512, (3, 3), padding='same', activation='relu', dilation_rate=8)(x)
    x = Conv2D(512, (3, 3), padding='same', activation='relu', dilation_rate=16)(x)
    x = Conv2D(512, (3, 3), padding='same', activation='relu', dilation_rate=16)(x)
    x = Conv2D(512, (3, 3), padding='same', activation='relu', dilation_rate=16, name='block5_conv3')(x)
    x = MaxPooling2D(pool_size=32)(x)
    x = Flatten()(x)
    x = Dense(4096, activation='relu')(x)
    x = Dense(4096, activation='relu')(x)
    y = Dense(1000, activation='softmax')(x)
    
    model = Model(inputs=inputs, outputs=y)

dilated_VGG16

python


Layer (type)                 Output Shape              Param #
=================================================================
input_1 (InputLayer)         (None, 224, 224, 3)       0
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 224, 224, 64)      1792
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 224, 224, 64)      36928
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 224, 224, 128)     73856
_________________________________________________________________
conv2d_4 (Conv2D)            (None, 224, 224, 128)     147584
_________________________________________________________________
conv2d_5 (Conv2D)            (None, 224, 224, 256)     295168
_________________________________________________________________
conv2d_6 (Conv2D)            (None, 224, 224, 256)     590080
_________________________________________________________________
conv2d_7 (Conv2D)            (None, 224, 224, 256)     590080
_________________________________________________________________
conv2d_8 (Conv2D)            (None, 224, 224, 512)     1180160
_________________________________________________________________
conv2d_9 (Conv2D)            (None, 224, 224, 512)     2359808
_________________________________________________________________
conv2d_10 (Conv2D)           (None, 224, 224, 512)     2359808
_________________________________________________________________
conv2d_11 (Conv2D)           (None, 224, 224, 512)     2359808
_________________________________________________________________
conv2d_12 (Conv2D)           (None, 224, 224, 512)     2359808
_________________________________________________________________
block5_conv3 (Conv2D)        (None, 224, 224, 512)     2359808
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 7, 7, 512)         0
_________________________________________________________________
flatten_1 (Flatten)          (None, 25088)             0
_________________________________________________________________
dense_1 (Dense)              (None, 4096)              102764544
_________________________________________________________________
dense_2 (Dense)              (None, 4096)              16781312
_________________________________________________________________
dense_3 (Dense)              (None, 1000)              4097000
=================================================================
Total params: 138,357,544
Trainable params: 138,357,544
Non-trainable params: 0
_________________________________________________________________

Référence: VGG16

python


_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
input_2 (InputLayer)         (None, 224, 224, 3)       0
_________________________________________________________________
block1_conv1 (Conv2D)        (None, 224, 224, 64)      1792
_________________________________________________________________
block1_conv2 (Conv2D)        (None, 224, 224, 64)      36928
_________________________________________________________________
block1_pool (MaxPooling2D)   (None, 112, 112, 64)      0
_________________________________________________________________
block2_conv1 (Conv2D)        (None, 112, 112, 128)     73856
_________________________________________________________________
block2_conv2 (Conv2D)        (None, 112, 112, 128)     147584
_________________________________________________________________
block2_pool (MaxPooling2D)   (None, 56, 56, 128)       0
_________________________________________________________________
block3_conv1 (Conv2D)        (None, 56, 56, 256)       295168
_________________________________________________________________
block3_conv2 (Conv2D)        (None, 56, 56, 256)       590080
_________________________________________________________________
block3_conv3 (Conv2D)        (None, 56, 56, 256)       590080
_________________________________________________________________
block3_pool (MaxPooling2D)   (None, 28, 28, 256)       0
_________________________________________________________________
block4_conv1 (Conv2D)        (None, 28, 28, 512)       1180160
_________________________________________________________________
block4_conv2 (Conv2D)        (None, 28, 28, 512)       2359808
_________________________________________________________________
block4_conv3 (Conv2D)        (None, 28, 28, 512)       2359808
_________________________________________________________________
block4_pool (MaxPooling2D)   (None, 14, 14, 512)       0
_________________________________________________________________
block5_conv1 (Conv2D)        (None, 14, 14, 512)       2359808
_________________________________________________________________
block5_conv2 (Conv2D)        (None, 14, 14, 512)       2359808
_________________________________________________________________
block5_conv3 (Conv2D)        (None, 14, 14, 512)       2359808
_________________________________________________________________
block5_pool (MaxPooling2D)   (None, 7, 7, 512)         0
_________________________________________________________________
flatten (Flatten)            (None, 25088)             0
_________________________________________________________________
fc1 (Dense)                  (None, 4096)              102764544
_________________________________________________________________
fc2 (Dense)                  (None, 4096)              16781312
_________________________________________________________________
predictions (Dense)          (None, 1000)              4097000
=================================================================
Total params: 138,357,544
Trainable params: 138,357,544
Non-trainable params: 0
_________________________________________________________________

Détournement du poids VGG16

Le problème avec le modèle dilated_VGG16 est qu'il n'utilise pas de pooling, donc la taille de l'image est grande et il faut beaucoup de temps pour apprendre. Puisque le temps de pliage de la couche profonde prend ** 16 * 16 = 256 fois ** de VGG16 du rapport d'image, il semble qu'il n'est probablement pas réaliste de s'entraîner avec ce modèle. J'ai écrit ce qui suit et détourné le poids de VGG16 vers dilated_VGG16. Ceci est possible car VGG16 et dilated_VGG16 ont le même nombre de paramètres.

python


    model1 = build_dilated_model()
    model2 = VGG16(include_top=True, weights='imagenet')

    model1.set_weights(model2.get_weights())

Précision de classification

J'ai fait la prédiction de classification d'image habituelle avec dilated_VGG16 en utilisant des poids VGG16. La précision de la classification était très dégradée avec dilated_VGG16, mais elle semble être assez efficace. cat_dog.png

Prédiction avec dilated_VGG16 en utilisant les poids VGG16

Model prediction:
        Saint_Bernard   (247)   with probability 0.029
        boxer           (242)   with probability 0.026
        whippet         (172)   with probability 0.020
        tiger_cat       (282)   with probability 0.019
        vacuum          (882)   with probability 0.017

Référence: Prédiction avec VGG16

Model prediction:
        boxer           (242)   with probability 0.420
        bull_mastiff    (243)   with probability 0.282
        tiger_cat       (282)   with probability 0.053
        tiger           (292)   with probability 0.050
        Great_Dane      (246)   with probability 0.050

Résultats Grad-CAM

On m'a demandé d'écrire le résultat Grad-CAM pour la prédiction du boxeur. Une carte VGG16 Grad-CAM normale n'a qu'une résolution de (14,14), tandis que dilated_VGG16 a une résolution de (224,224). Cependant, un motif de grille est apparu et n'a pas atteint la haute résolution. gradcam.jpg gradcam.jpg Gauche: Grad-CAM normal, Droite: Grad-CAM utilisant la convolution dilatée

Résumé

Je me suis demandé si je pouvais obtenir un Grad-CAM haute résolution en effectuant une convolution dilatée, mais cela n'a pas fonctionné. Lorsque j'ai cherché, il semblait y avoir une solution au motif de grille de convolution dilatée, et l'article suivant a été trouvé. https://www.cs.princeton.edu/~funk/drn.pdf (Je n'ai pas lu le contenu ...) image.png image.png

Recommended Posts

Grad-CAM et convolution dilatée