Fully CNNs

Objetivos:
- Cargar un modelo de CNN preentrenado en ImageNet
- Transformar la red en una Red Fully Convolucional
- Aplicar la red para realizar una segmentación débil en imágenes

Archivos requeridos:

weights_dense.h5

dog.jpg

meta_clsloc.mat

%matplotlib inline
import warnings

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(1)
# Load a pre-trained ResNet50
# We use include_top = False for now,
# as we'll import output Dense Layer later

import tensorflow as tf
from tensorflow.keras.applications.resnet50 import ResNet50
base_model = ResNet50(include_top=False)

print(base_model.output_shape)
(None, None, None, 2048)
print(base_model.summary())
Model: "resnet50"
┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┓
┃ Layer (type)         Output Shape          Param #  Connected to      ┃
┡━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━┩
│ input_layer         │ (None, None,      │          0 │ -                 │
│ (InputLayer)        │ None, 3)          │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv1_pad           │ (None, None,      │          0 │ input_layer[0][0] │
│ (ZeroPadding2D)     │ None, 3)          │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv1_conv (Conv2D) │ (None, None,      │      9,472 │ conv1_pad[0][0]   │
│                     │ None, 64)         │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv1_bn            │ (None, None,      │        256 │ conv1_conv[0][0]  │
│ (BatchNormalizatio…None, 64)         │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv1_relu          │ (None, None,      │          0 │ conv1_bn[0][0]    │
│ (Activation)        │ None, 64)         │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ pool1_pad           │ (None, None,      │          0 │ conv1_relu[0][0]  │
│ (ZeroPadding2D)     │ None, 64)         │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ pool1_pool          │ (None, None,      │          0 │ pool1_pad[0][0]   │
│ (MaxPooling2D)      │ None, 64)         │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block1_1_conv │ (None, None,      │      4,160 │ pool1_pool[0][0]  │
│ (Conv2D)            │ None, 64)         │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block1_1_bn   │ (None, None,      │        256 │ conv2_block1_1_c… │
│ (BatchNormalizatio…None, 64)         │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block1_1_relu │ (None, None,      │          0 │ conv2_block1_1_b… │
│ (Activation)        │ None, 64)         │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block1_2_conv │ (None, None,      │     36,928 │ conv2_block1_1_r… │
│ (Conv2D)            │ None, 64)         │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block1_2_bn   │ (None, None,      │        256 │ conv2_block1_2_c… │
│ (BatchNormalizatio…None, 64)         │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block1_2_relu │ (None, None,      │          0 │ conv2_block1_2_b… │
│ (Activation)        │ None, 64)         │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block1_0_conv │ (None, None,      │     16,640 │ pool1_pool[0][0]  │
│ (Conv2D)            │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block1_3_conv │ (None, None,      │     16,640 │ conv2_block1_2_r… │
│ (Conv2D)            │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block1_0_bn   │ (None, None,      │      1,024 │ conv2_block1_0_c… │
│ (BatchNormalizatio…None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block1_3_bn   │ (None, None,      │      1,024 │ conv2_block1_3_c… │
│ (BatchNormalizatio…None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block1_add    │ (None, None,      │          0 │ conv2_block1_0_b… │
│ (Add)               │ None, 256)        │            │ conv2_block1_3_b… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block1_out    │ (None, None,      │          0 │ conv2_block1_add… │
│ (Activation)        │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block2_1_conv │ (None, None,      │     16,448 │ conv2_block1_out… │
│ (Conv2D)            │ None, 64)         │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block2_1_bn   │ (None, None,      │        256 │ conv2_block2_1_c… │
│ (BatchNormalizatio…None, 64)         │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block2_1_relu │ (None, None,      │          0 │ conv2_block2_1_b… │
│ (Activation)        │ None, 64)         │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block2_2_conv │ (None, None,      │     36,928 │ conv2_block2_1_r… │
│ (Conv2D)            │ None, 64)         │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block2_2_bn   │ (None, None,      │        256 │ conv2_block2_2_c… │
│ (BatchNormalizatio…None, 64)         │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block2_2_relu │ (None, None,      │          0 │ conv2_block2_2_b… │
│ (Activation)        │ None, 64)         │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block2_3_conv │ (None, None,      │     16,640 │ conv2_block2_2_r… │
│ (Conv2D)            │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block2_3_bn   │ (None, None,      │      1,024 │ conv2_block2_3_c… │
│ (BatchNormalizatio…None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block2_add    │ (None, None,      │          0 │ conv2_block1_out… │
│ (Add)               │ None, 256)        │            │ conv2_block2_3_b… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block2_out    │ (None, None,      │          0 │ conv2_block2_add… │
│ (Activation)        │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block3_1_conv │ (None, None,      │     16,448 │ conv2_block2_out… │
│ (Conv2D)            │ None, 64)         │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block3_1_bn   │ (None, None,      │        256 │ conv2_block3_1_c… │
│ (BatchNormalizatio…None, 64)         │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block3_1_relu │ (None, None,      │          0 │ conv2_block3_1_b… │
│ (Activation)        │ None, 64)         │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block3_2_conv │ (None, None,      │     36,928 │ conv2_block3_1_r… │
│ (Conv2D)            │ None, 64)         │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block3_2_bn   │ (None, None,      │        256 │ conv2_block3_2_c… │
│ (BatchNormalizatio…None, 64)         │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block3_2_relu │ (None, None,      │          0 │ conv2_block3_2_b… │
│ (Activation)        │ None, 64)         │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block3_3_conv │ (None, None,      │     16,640 │ conv2_block3_2_r… │
│ (Conv2D)            │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block3_3_bn   │ (None, None,      │      1,024 │ conv2_block3_3_c… │
│ (BatchNormalizatio…None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block3_add    │ (None, None,      │          0 │ conv2_block2_out… │
│ (Add)               │ None, 256)        │            │ conv2_block3_3_b… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv2_block3_out    │ (None, None,      │          0 │ conv2_block3_add… │
│ (Activation)        │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block1_1_conv │ (None, None,      │     32,896 │ conv2_block3_out… │
│ (Conv2D)            │ None, 128)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block1_1_bn   │ (None, None,      │        512 │ conv3_block1_1_c… │
│ (BatchNormalizatio…None, 128)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block1_1_relu │ (None, None,      │          0 │ conv3_block1_1_b… │
│ (Activation)        │ None, 128)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block1_2_conv │ (None, None,      │    147,584 │ conv3_block1_1_r… │
│ (Conv2D)            │ None, 128)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block1_2_bn   │ (None, None,      │        512 │ conv3_block1_2_c… │
│ (BatchNormalizatio…None, 128)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block1_2_relu │ (None, None,      │          0 │ conv3_block1_2_b… │
│ (Activation)        │ None, 128)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block1_0_conv │ (None, None,      │    131,584 │ conv2_block3_out… │
│ (Conv2D)            │ None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block1_3_conv │ (None, None,      │     66,048 │ conv3_block1_2_r… │
│ (Conv2D)            │ None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block1_0_bn   │ (None, None,      │      2,048 │ conv3_block1_0_c… │
│ (BatchNormalizatio…None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block1_3_bn   │ (None, None,      │      2,048 │ conv3_block1_3_c… │
│ (BatchNormalizatio…None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block1_add    │ (None, None,      │          0 │ conv3_block1_0_b… │
│ (Add)               │ None, 512)        │            │ conv3_block1_3_b… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block1_out    │ (None, None,      │          0 │ conv3_block1_add… │
│ (Activation)        │ None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block2_1_conv │ (None, None,      │     65,664 │ conv3_block1_out… │
│ (Conv2D)            │ None, 128)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block2_1_bn   │ (None, None,      │        512 │ conv3_block2_1_c… │
│ (BatchNormalizatio…None, 128)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block2_1_relu │ (None, None,      │          0 │ conv3_block2_1_b… │
│ (Activation)        │ None, 128)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block2_2_conv │ (None, None,      │    147,584 │ conv3_block2_1_r… │
│ (Conv2D)            │ None, 128)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block2_2_bn   │ (None, None,      │        512 │ conv3_block2_2_c… │
│ (BatchNormalizatio…None, 128)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block2_2_relu │ (None, None,      │          0 │ conv3_block2_2_b… │
│ (Activation)        │ None, 128)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block2_3_conv │ (None, None,      │     66,048 │ conv3_block2_2_r… │
│ (Conv2D)            │ None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block2_3_bn   │ (None, None,      │      2,048 │ conv3_block2_3_c… │
│ (BatchNormalizatio…None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block2_add    │ (None, None,      │          0 │ conv3_block1_out… │
│ (Add)               │ None, 512)        │            │ conv3_block2_3_b… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block2_out    │ (None, None,      │          0 │ conv3_block2_add… │
│ (Activation)        │ None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block3_1_conv │ (None, None,      │     65,664 │ conv3_block2_out… │
│ (Conv2D)            │ None, 128)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block3_1_bn   │ (None, None,      │        512 │ conv3_block3_1_c… │
│ (BatchNormalizatio…None, 128)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block3_1_relu │ (None, None,      │          0 │ conv3_block3_1_b… │
│ (Activation)        │ None, 128)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block3_2_conv │ (None, None,      │    147,584 │ conv3_block3_1_r… │
│ (Conv2D)            │ None, 128)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block3_2_bn   │ (None, None,      │        512 │ conv3_block3_2_c… │
│ (BatchNormalizatio…None, 128)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block3_2_relu │ (None, None,      │          0 │ conv3_block3_2_b… │
│ (Activation)        │ None, 128)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block3_3_conv │ (None, None,      │     66,048 │ conv3_block3_2_r… │
│ (Conv2D)            │ None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block3_3_bn   │ (None, None,      │      2,048 │ conv3_block3_3_c… │
│ (BatchNormalizatio…None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block3_add    │ (None, None,      │          0 │ conv3_block2_out… │
│ (Add)               │ None, 512)        │            │ conv3_block3_3_b… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block3_out    │ (None, None,      │          0 │ conv3_block3_add… │
│ (Activation)        │ None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block4_1_conv │ (None, None,      │     65,664 │ conv3_block3_out… │
│ (Conv2D)            │ None, 128)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block4_1_bn   │ (None, None,      │        512 │ conv3_block4_1_c… │
│ (BatchNormalizatio…None, 128)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block4_1_relu │ (None, None,      │          0 │ conv3_block4_1_b… │
│ (Activation)        │ None, 128)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block4_2_conv │ (None, None,      │    147,584 │ conv3_block4_1_r… │
│ (Conv2D)            │ None, 128)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block4_2_bn   │ (None, None,      │        512 │ conv3_block4_2_c… │
│ (BatchNormalizatio…None, 128)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block4_2_relu │ (None, None,      │          0 │ conv3_block4_2_b… │
│ (Activation)        │ None, 128)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block4_3_conv │ (None, None,      │     66,048 │ conv3_block4_2_r… │
│ (Conv2D)            │ None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block4_3_bn   │ (None, None,      │      2,048 │ conv3_block4_3_c… │
│ (BatchNormalizatio…None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block4_add    │ (None, None,      │          0 │ conv3_block3_out… │
│ (Add)               │ None, 512)        │            │ conv3_block4_3_b… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv3_block4_out    │ (None, None,      │          0 │ conv3_block4_add… │
│ (Activation)        │ None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block1_1_conv │ (None, None,      │    131,328 │ conv3_block4_out… │
│ (Conv2D)            │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block1_1_bn   │ (None, None,      │      1,024 │ conv4_block1_1_c… │
│ (BatchNormalizatio…None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block1_1_relu │ (None, None,      │          0 │ conv4_block1_1_b… │
│ (Activation)        │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block1_2_conv │ (None, None,      │    590,080 │ conv4_block1_1_r… │
│ (Conv2D)            │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block1_2_bn   │ (None, None,      │      1,024 │ conv4_block1_2_c… │
│ (BatchNormalizatio…None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block1_2_relu │ (None, None,      │          0 │ conv4_block1_2_b… │
│ (Activation)        │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block1_0_conv │ (None, None,      │    525,312 │ conv3_block4_out… │
│ (Conv2D)            │ None, 1024)       │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block1_3_conv │ (None, None,      │    263,168 │ conv4_block1_2_r… │
│ (Conv2D)            │ None, 1024)       │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block1_0_bn   │ (None, None,      │      4,096 │ conv4_block1_0_c… │
│ (BatchNormalizatio…None, 1024)       │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block1_3_bn   │ (None, None,      │      4,096 │ conv4_block1_3_c… │
│ (BatchNormalizatio…None, 1024)       │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block1_add    │ (None, None,      │          0 │ conv4_block1_0_b… │
│ (Add)               │ None, 1024)       │            │ conv4_block1_3_b… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block1_out    │ (None, None,      │          0 │ conv4_block1_add… │
│ (Activation)        │ None, 1024)       │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block2_1_conv │ (None, None,      │    262,400 │ conv4_block1_out… │
│ (Conv2D)            │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block2_1_bn   │ (None, None,      │      1,024 │ conv4_block2_1_c… │
│ (BatchNormalizatio…None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block2_1_relu │ (None, None,      │          0 │ conv4_block2_1_b… │
│ (Activation)        │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block2_2_conv │ (None, None,      │    590,080 │ conv4_block2_1_r… │
│ (Conv2D)            │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block2_2_bn   │ (None, None,      │      1,024 │ conv4_block2_2_c… │
│ (BatchNormalizatio…None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block2_2_relu │ (None, None,      │          0 │ conv4_block2_2_b… │
│ (Activation)        │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block2_3_conv │ (None, None,      │    263,168 │ conv4_block2_2_r… │
│ (Conv2D)            │ None, 1024)       │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block2_3_bn   │ (None, None,      │      4,096 │ conv4_block2_3_c… │
│ (BatchNormalizatio…None, 1024)       │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block2_add    │ (None, None,      │          0 │ conv4_block1_out… │
│ (Add)               │ None, 1024)       │            │ conv4_block2_3_b… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block2_out    │ (None, None,      │          0 │ conv4_block2_add… │
│ (Activation)        │ None, 1024)       │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block3_1_conv │ (None, None,      │    262,400 │ conv4_block2_out… │
│ (Conv2D)            │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block3_1_bn   │ (None, None,      │      1,024 │ conv4_block3_1_c… │
│ (BatchNormalizatio…None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block3_1_relu │ (None, None,      │          0 │ conv4_block3_1_b… │
│ (Activation)        │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block3_2_conv │ (None, None,      │    590,080 │ conv4_block3_1_r… │
│ (Conv2D)            │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block3_2_bn   │ (None, None,      │      1,024 │ conv4_block3_2_c… │
│ (BatchNormalizatio…None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block3_2_relu │ (None, None,      │          0 │ conv4_block3_2_b… │
│ (Activation)        │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block3_3_conv │ (None, None,      │    263,168 │ conv4_block3_2_r… │
│ (Conv2D)            │ None, 1024)       │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block3_3_bn   │ (None, None,      │      4,096 │ conv4_block3_3_c… │
│ (BatchNormalizatio…None, 1024)       │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block3_add    │ (None, None,      │          0 │ conv4_block2_out… │
│ (Add)               │ None, 1024)       │            │ conv4_block3_3_b… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block3_out    │ (None, None,      │          0 │ conv4_block3_add… │
│ (Activation)        │ None, 1024)       │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block4_1_conv │ (None, None,      │    262,400 │ conv4_block3_out… │
│ (Conv2D)            │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block4_1_bn   │ (None, None,      │      1,024 │ conv4_block4_1_c… │
│ (BatchNormalizatio…None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block4_1_relu │ (None, None,      │          0 │ conv4_block4_1_b… │
│ (Activation)        │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block4_2_conv │ (None, None,      │    590,080 │ conv4_block4_1_r… │
│ (Conv2D)            │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block4_2_bn   │ (None, None,      │      1,024 │ conv4_block4_2_c… │
│ (BatchNormalizatio…None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block4_2_relu │ (None, None,      │          0 │ conv4_block4_2_b… │
│ (Activation)        │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block4_3_conv │ (None, None,      │    263,168 │ conv4_block4_2_r… │
│ (Conv2D)            │ None, 1024)       │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block4_3_bn   │ (None, None,      │      4,096 │ conv4_block4_3_c… │
│ (BatchNormalizatio…None, 1024)       │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block4_add    │ (None, None,      │          0 │ conv4_block3_out… │
│ (Add)               │ None, 1024)       │            │ conv4_block4_3_b… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block4_out    │ (None, None,      │          0 │ conv4_block4_add… │
│ (Activation)        │ None, 1024)       │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block5_1_conv │ (None, None,      │    262,400 │ conv4_block4_out… │
│ (Conv2D)            │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block5_1_bn   │ (None, None,      │      1,024 │ conv4_block5_1_c… │
│ (BatchNormalizatio…None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block5_1_relu │ (None, None,      │          0 │ conv4_block5_1_b… │
│ (Activation)        │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block5_2_conv │ (None, None,      │    590,080 │ conv4_block5_1_r… │
│ (Conv2D)            │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block5_2_bn   │ (None, None,      │      1,024 │ conv4_block5_2_c… │
│ (BatchNormalizatio…None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block5_2_relu │ (None, None,      │          0 │ conv4_block5_2_b… │
│ (Activation)        │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block5_3_conv │ (None, None,      │    263,168 │ conv4_block5_2_r… │
│ (Conv2D)            │ None, 1024)       │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block5_3_bn   │ (None, None,      │      4,096 │ conv4_block5_3_c… │
│ (BatchNormalizatio…None, 1024)       │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block5_add    │ (None, None,      │          0 │ conv4_block4_out… │
│ (Add)               │ None, 1024)       │            │ conv4_block5_3_b… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block5_out    │ (None, None,      │          0 │ conv4_block5_add… │
│ (Activation)        │ None, 1024)       │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block6_1_conv │ (None, None,      │    262,400 │ conv4_block5_out… │
│ (Conv2D)            │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block6_1_bn   │ (None, None,      │      1,024 │ conv4_block6_1_c… │
│ (BatchNormalizatio…None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block6_1_relu │ (None, None,      │          0 │ conv4_block6_1_b… │
│ (Activation)        │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block6_2_conv │ (None, None,      │    590,080 │ conv4_block6_1_r… │
│ (Conv2D)            │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block6_2_bn   │ (None, None,      │      1,024 │ conv4_block6_2_c… │
│ (BatchNormalizatio…None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block6_2_relu │ (None, None,      │          0 │ conv4_block6_2_b… │
│ (Activation)        │ None, 256)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block6_3_conv │ (None, None,      │    263,168 │ conv4_block6_2_r… │
│ (Conv2D)            │ None, 1024)       │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block6_3_bn   │ (None, None,      │      4,096 │ conv4_block6_3_c… │
│ (BatchNormalizatio…None, 1024)       │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block6_add    │ (None, None,      │          0 │ conv4_block5_out… │
│ (Add)               │ None, 1024)       │            │ conv4_block6_3_b… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv4_block6_out    │ (None, None,      │          0 │ conv4_block6_add… │
│ (Activation)        │ None, 1024)       │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block1_1_conv │ (None, None,      │    524,800 │ conv4_block6_out… │
│ (Conv2D)            │ None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block1_1_bn   │ (None, None,      │      2,048 │ conv5_block1_1_c… │
│ (BatchNormalizatio…None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block1_1_relu │ (None, None,      │          0 │ conv5_block1_1_b… │
│ (Activation)        │ None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block1_2_conv │ (None, None,      │  2,359,808 │ conv5_block1_1_r… │
│ (Conv2D)            │ None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block1_2_bn   │ (None, None,      │      2,048 │ conv5_block1_2_c… │
│ (BatchNormalizatio…None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block1_2_relu │ (None, None,      │          0 │ conv5_block1_2_b… │
│ (Activation)        │ None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block1_0_conv │ (None, None,      │  2,099,200 │ conv4_block6_out… │
│ (Conv2D)            │ None, 2048)       │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block1_3_conv │ (None, None,      │  1,050,624 │ conv5_block1_2_r… │
│ (Conv2D)            │ None, 2048)       │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block1_0_bn   │ (None, None,      │      8,192 │ conv5_block1_0_c… │
│ (BatchNormalizatio…None, 2048)       │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block1_3_bn   │ (None, None,      │      8,192 │ conv5_block1_3_c… │
│ (BatchNormalizatio…None, 2048)       │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block1_add    │ (None, None,      │          0 │ conv5_block1_0_b… │
│ (Add)               │ None, 2048)       │            │ conv5_block1_3_b… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block1_out    │ (None, None,      │          0 │ conv5_block1_add… │
│ (Activation)        │ None, 2048)       │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block2_1_conv │ (None, None,      │  1,049,088 │ conv5_block1_out… │
│ (Conv2D)            │ None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block2_1_bn   │ (None, None,      │      2,048 │ conv5_block2_1_c… │
│ (BatchNormalizatio…None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block2_1_relu │ (None, None,      │          0 │ conv5_block2_1_b… │
│ (Activation)        │ None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block2_2_conv │ (None, None,      │  2,359,808 │ conv5_block2_1_r… │
│ (Conv2D)            │ None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block2_2_bn   │ (None, None,      │      2,048 │ conv5_block2_2_c… │
│ (BatchNormalizatio…None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block2_2_relu │ (None, None,      │          0 │ conv5_block2_2_b… │
│ (Activation)        │ None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block2_3_conv │ (None, None,      │  1,050,624 │ conv5_block2_2_r… │
│ (Conv2D)            │ None, 2048)       │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block2_3_bn   │ (None, None,      │      8,192 │ conv5_block2_3_c… │
│ (BatchNormalizatio…None, 2048)       │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block2_add    │ (None, None,      │          0 │ conv5_block1_out… │
│ (Add)               │ None, 2048)       │            │ conv5_block2_3_b… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block2_out    │ (None, None,      │          0 │ conv5_block2_add… │
│ (Activation)        │ None, 2048)       │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block3_1_conv │ (None, None,      │  1,049,088 │ conv5_block2_out… │
│ (Conv2D)            │ None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block3_1_bn   │ (None, None,      │      2,048 │ conv5_block3_1_c… │
│ (BatchNormalizatio…None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block3_1_relu │ (None, None,      │          0 │ conv5_block3_1_b… │
│ (Activation)        │ None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block3_2_conv │ (None, None,      │  2,359,808 │ conv5_block3_1_r… │
│ (Conv2D)            │ None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block3_2_bn   │ (None, None,      │      2,048 │ conv5_block3_2_c… │
│ (BatchNormalizatio…None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block3_2_relu │ (None, None,      │          0 │ conv5_block3_2_b… │
│ (Activation)        │ None, 512)        │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block3_3_conv │ (None, None,      │  1,050,624 │ conv5_block3_2_r… │
│ (Conv2D)            │ None, 2048)       │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block3_3_bn   │ (None, None,      │      8,192 │ conv5_block3_3_c… │
│ (BatchNormalizatio…None, 2048)       │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block3_add    │ (None, None,      │          0 │ conv5_block2_out… │
│ (Add)               │ None, 2048)       │            │ conv5_block3_3_b… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv5_block3_out    │ (None, None,      │          0 │ conv5_block3_add… │
│ (Activation)        │ None, 2048)       │            │                   │
└─────────────────────┴───────────────────┴────────────┴───────────────────┘
 Total params: 23,587,712 (89.98 MB)
 Trainable params: 23,534,592 (89.78 MB)
 Non-trainable params: 53,120 (207.50 KB)
None
res5c = base_model.layers[-1]
type(res5c)
keras.src.layers.activations.activation.Activation
res5c
<Activation name=conv5_block3_out, built=True>

ResNet totalmente convolucional

  • A la salida del bloque residual res5c, la ResNet genera un tensor de forma \(W \times H \times 2048\).
  • Para la entrada predeterminada de ImageNet, \(224 \times 224\), el tamaño de salida es \(7 \times 7 \times 2048\).

ResNet layers

La cabeza de ResNet después del modelo base es la siguiente:

x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Dense(1000)(x)
x = Softmax()(x)

https://github.com/keras-team/keras-applications/blob/master/keras_applications/resnet50.py

En esta versión

  • Queremos recuperar la información de las etiquetas, que está almacenada en la capa Dense. Cargaremos estos pesos después.
  • Cambiaremos la capa Dense a una capa Convolution2D para conservar la información espacial, con una salida de \(W \times H \times 1000\).
  • Podemos usar un tamaño de kernel de (1, 1) para esa nueva capa Convolution2D con el fin de mantener la organización espacial de la capa anterior sin cambios (esto se llama pointwise convolution).
  • Queremos aplicar un softmax solo en la última dimensión para preservar la información espacial \(W \times H\).

Softmax

Para aplicar softmax sólo a la última dimensión de un tensor:

from tensorflow.keras import layers

# A custom layer in Keras must implement the four following methods:
class SoftmaxMap(layers.Layer):
    # Init function
    def __init__(self, axis=-1, **kwargs):
        self.axis = axis
        super(SoftmaxMap, self).__init__(**kwargs)

    # There's no parameter, so we don't need this one
    def build(self, input_shape):
        pass

    # This is the layer we're interested in: 
    # very similar to the regular softmax but note the additional
    # that we accept x.shape == (batch_size, w, h, n_classes)
    # which is not the case in Keras by default.
    # Note also that we substract the logits by their maximum to
    # make the softmax numerically stable.
    def call(self, x, mask=None):
        e = tf.exp(x - tf.math.reduce_max(x, axis=self.axis, keepdims=True))
        s = tf.math.reduce_sum(e, axis=self.axis, keepdims=True)
        return e / s

    # The output shape is the same as the input shape
    def get_output_shape_for(self, input_shape):
        return input_shape

Verifiquemos si podemos usar esta capa para normalizar las probabilidades de las clases de algunas predicciones espaciales aleatorias:

n_samples, w, h, n_classes = 10, 3, 4, 5
random_data = np.random.randn(n_samples, w, h, n_classes).astype("float32")
random_data.shape
(10, 3, 4, 5)
random_data[0].sum(axis=-1)
array([[ 0.27685624, -1.248265  , -0.17073488, -1.5251491 ],
       [ 2.3490455 , -1.4799201 , -3.292039  ,  1.5062871 ],
       [-0.08336051,  2.3915372 , -1.7528347 ,  3.5274372 ]],
      dtype=float32)

Función SoftmaxMap:

softmaxMap = SoftmaxMap()
softmax_mapped_data = softmaxMap(random_data).numpy()
softmax_mapped_data.shape
(10, 3, 4, 5)

Todos los valores están en [0, 1]:

softmax_mapped_data[0]
array([[[0.56862915, 0.06077185, 0.06606976, 0.0383178 , 0.2662114 ],
        [0.01185074, 0.6777243 , 0.05529718, 0.16287254, 0.09225518],
        [0.48184162, 0.01423021, 0.08089001, 0.07605473, 0.3469834 ],
        [0.07524366, 0.19022258, 0.09395019, 0.23576528, 0.4048183 ]],

       [[0.03309341, 0.31252265, 0.24507003, 0.16442387, 0.24489003],
        [0.11887496, 0.20828551, 0.09239109, 0.180172  , 0.40027645],
        [0.19135876, 0.25699514, 0.19221951, 0.1641212 , 0.19530542],
        [0.09936516, 0.03292248, 0.1272154 , 0.52914804, 0.21134888]],

       [[0.10071651, 0.05022516, 0.05779989, 0.6628838 , 0.12837464],
        [0.04103367, 0.09390692, 0.6337432 , 0.08749201, 0.1438242 ],
        [0.34717003, 0.18080053, 0.08203337, 0.1813269 , 0.20866917],
        [0.17282423, 0.22243509, 0.24389896, 0.12789878, 0.23294285]]],
      dtype=float32)

La última dimensión suma app uno. Podemos usarla como probabilidad de una clase:

softmax_mapped_data[0].sum(axis=-1)
array([[0.99999994, 0.99999994, 1.        , 1.        ],
       [1.        , 1.        , 1.        , 1.        ],
       [1.        , 1.        , 1.        , 0.9999999 ]], dtype=float32)

Note que el canal más activado para cada ubicación espacial sigue siendo el mismo antes y después del mapa softmax. El orden de las activaciones se conserva ya que softmax es una función monótona (cuando se considera elemento por elemento):

random_data[0].argmax(axis=-1)
array([[0, 1, 0, 4],
       [1, 4, 1, 3],
       [3, 2, 0, 2]])
softmax_mapped_data[0].argmax(axis=-1)
array([[0, 1, 0, 4],
       [1, 4, 1, 3],
       [3, 2, 0, 2]])

Ejercicio

  • Cuál es la forma del kernel de convolución que queremos aplicar para reemplazar la capa Dense?
  • Construir el modelo totalmente convolucional como se describió arriba. Queremos que la salida preserve las dimensiones espaciales pero que produzca 1000 canales (un canal por clase).
  • Puedes inspeccionar los últimos elementos de base_model.layers para encontrar qué capa eliminar.
  • Puedes usar la capa Keras Convolution2D(output_channels, filter_w, filter_h) y nuestro SotfmaxMap para normalizar el resultado como probabilidades por clase.
  • Por ahora, ignora los pesos de la(s) nueva(s) capa(s) (déjalos inicializados de forma aleatoria): solo concéntrate en construir la arquitectura correcta con la forma de salida adecuada.
from tensorflow.keras.layers import Convolution2D
from tensorflow.keras.models import Model

input = base_model.input

# Take the output of the last layer of the convnet
# layer:
x = base_model.layers[-1].output

# A 1x1 convolution, with 1000 output channels, one per class
x = Convolution2D(1000, (1, 1), name='conv1000')(x)

# Softmax on last axis of tensor to normalize the class
# predictions in each spatial area
output = SoftmaxMap(axis=-1)(x)

fully_conv_ResNet = Model(inputs=input, outputs=output)

# A 1x1 convolution applies a Dense to each spatial grid location

Datos aleatorios para verificar que es posible ejecutar un forward pass en una imagen RGB aleatoria:

prediction_maps = fully_conv_ResNet(np.random.randn(1, 200, 300, 3)).numpy()
prediction_maps.shape
(1, 7, 10, 1000)

Las probabilidades de clases deben sumar uno en cada áreas de la imagen de salida:

prediction_maps.sum(axis=-1)
array([[[1.        , 1.        , 0.99999994, 1.        , 1.        ,
         1.0000001 , 1.        , 0.9999999 , 1.0000001 , 1.        ],
        [1.        , 1.        , 1.        , 0.99999994, 1.        ,
         1.        , 1.        , 1.0000001 , 0.99999994, 1.        ],
        [0.99999994, 1.        , 0.99999994, 1.0000001 , 1.        ,
         1.        , 1.        , 1.        , 0.9999999 , 1.0000001 ],
        [0.9999999 , 0.9999999 , 0.99999994, 1.        , 1.        ,
         1.        , 1.        , 1.        , 0.99999994, 1.        ],
        [1.0000002 , 0.99999994, 1.        , 1.        , 0.9999999 ,
         1.        , 1.        , 1.        , 1.        , 1.        ],
        [0.99999994, 1.        , 1.0000001 , 1.0000001 , 1.        ,
         1.        , 1.        , 0.99999994, 1.        , 1.        ],
        [1.        , 1.        , 1.        , 0.99999994, 0.99999994,
         1.0000001 , 0.99999994, 1.        , 1.0000001 , 0.9999999 ]]],
      dtype=float32)

Pesos de la capa Densa

  • Los pesos de la capa Densa de ResNet50 están en weights_dense.h5
  • Nuestra última capa es conv de 1x1 en vez de una fully connected
import h5py

with h5py.File('weights_dense.h5', 'r') as h5f:
    w = h5f['w'][:]
    b = h5f['b'][:]
last_layer = fully_conv_ResNet.layers[-2]

print("Loaded weight shape:", w.shape)
print("Last conv layer weights shape:", last_layer.get_weights()[0].shape)
Loaded weight shape: (2048, 1000)
Last conv layer weights shape: (1, 1, 2048, 1000)
# reshape the weights
w_reshaped = w.reshape((1, 1, 2048, 1000))

# set the conv layer weights
last_layer.set_weights([w_reshaped, b])

Forward pass

Se reformatea la entrada a un tamaño dado y luego se usa el método model.predict para calcular la salida

from tensorflow.keras.applications.imagenet_utils import preprocess_input
from skimage.io import imread
from skimage.transform import resize

def forward_pass_resize(img_path, img_size):
    img_raw = imread(img_path)
    print("Image shape before resizing: %s" % (img_raw.shape,))
    img = resize(img_raw, img_size, mode='reflect', preserve_range=True)
    img = preprocess_input(img[np.newaxis])
    print("Image batch size shape before forward pass:", img.shape)
    prediction_map = fully_conv_ResNet(img).numpy()
    return prediction_map
output = forward_pass_resize("dog.jpg", (800, 600))
print("prediction map shape", output.shape)
Image shape before resizing: (1600, 2560, 3)
Image batch size shape before forward pass: (1, 800, 600, 3)
prediction map shape (1, 25, 19, 1000)

Clases relacionadas a perros

ImageNet utiliza una ontología de conceptos, de la cual se derivan las clases. Un synset corresponde a un nodo en la ontología.

Por ejemplo, todas las especies de perros son hijos del synset n02084071 (Perro, perro doméstico, Canis familiaris):

# #### Helper tool from convnets-keras github
import numpy as np
from scipy.io import loadmat

synsets = loadmat("meta_clsloc.mat")["synsets"][0]
SYNSET_LIMIT = 1000

# Create mappings between ids and sorted indices
sorted_synsets = sorted([(int(s[0].item()), s[1][0]) for s in synsets[:SYNSET_LIMIT]], key=lambda x: x[1])
id2idx = {id_: i for i, (id_, _) in enumerate(sorted_synsets)}
idx2id = {i: id_ for id_, i in id2idx.items()}

def dfs(id_, out=None):
    if out is None: out = []
    id_ = id_ if isinstance(id_, int) else next(int(s[0].item()) for s in synsets if s[1][0] == id_)
    out.append(id_)
    for c in synsets[id_-1][5][0]: dfs(int(c), out)
    return out

def synset_to_dfs_ids(synset):
    return [id2idx[x] for x in dfs(synset) if x in id2idx]

def id_to_synset(idx): return synsets[idx2id[idx]-1][1][0]
def id_to_words(idx): return synsets[idx2id[idx]-1][2][0]

def pprint_output(out, n=10):
    for u in out.argsort()[::-1][:n]:
        print(f"{round(100*out[u],2):.2f} : {id_to_words(u)}")
synset = "n02084071" # synset de dogs
ids = synset_to_dfs_ids(synset)
print("All dog classes ids (%d):" % len(ids))
print(ids)
All dog classes ids (118):
[251, 268, 256, 253, 255, 254, 257, 159, 211, 210, 212, 214, 213, 216, 215, 219, 220, 221, 217, 218, 207, 209, 206, 205, 208, 193, 202, 194, 191, 204, 187, 203, 185, 192, 183, 199, 195, 181, 184, 201, 186, 200, 182, 188, 189, 190, 197, 196, 198, 179, 180, 177, 178, 175, 163, 174, 176, 160, 162, 161, 164, 168, 173, 170, 169, 165, 166, 167, 172, 171, 264, 263, 266, 265, 267, 262, 246, 242, 243, 248, 247, 229, 233, 234, 228, 231, 232, 230, 227, 226, 235, 225, 224, 223, 222, 236, 252, 237, 250, 249, 241, 239, 238, 240, 244, 245, 259, 261, 260, 258, 154, 153, 158, 152, 155, 151, 157, 156]
for dog_id in ids[:10]:
    print(id_to_words(dog_id))
print('...')
dalmatian, coach dog, carriage dog
Mexican hairless
Newfoundland, Newfoundland dog
basenji
Leonberg
pug, pug-dog
Great Pyrenees
Rhodesian ridgeback
vizsla, Hungarian pointer
German short-haired pointer
...

Mapa de calor de la clase “dog”

La siguiente función construye un mapa de calor a partir de un forward pass. Suma la representación de todos los ids correspondientes a un synset.

def build_heatmap(prediction_map, synset):
    class_ids = synset_to_dfs_ids(synset)
    class_ids = np.array([id_ for id_ in class_ids if id_ is not None])
    each_dog_proba_map = prediction_map[0, :, :, class_ids]
    # this style of indexing a tensor by an other array has the following shape effect:
    # (H, W, 1000) indexed by (118) ==> (118, H, W)
    any_dog_proba_map = each_dog_proba_map.sum(axis=0)
    print("size of heatmap: " + str(any_dog_proba_map.shape))
    return any_dog_proba_map
def display_img_and_heatmap(img_path, heatmap):
    dog = imread(img_path)
    plt.figure(figsize=(12, 8))
    plt.subplot(1, 2, 1)
    plt.imshow(dog)
    plt.axis('off')
    plt.subplot(1, 2, 2)
    plt.imshow(heatmap, interpolation='nearest', cmap="viridis")
    plt.axis('off')
  • ¿Cuál es el tamaño del mapa de calor comparado con la imagen de entrada?
  • Construir 3 o 4 mapas de calor de perro a partir de "dog.jpg", con los siguientes tamaños:
    • (200, 320)
    • (400, 640)
    • (800, 1280)
    • (1600, 2560) (opcional)

Puede graficar un mapa de calor usando la función display_img_and_heatmap mostrada arriba. También puedes reutilizar forward_pass_resize para calcular los propios mapas de clase.

# dog synset
s = "n02084071"

probas_1 = forward_pass_resize("dog.jpg", (200, 320))
heatmap_1 = build_heatmap(probas_1, synset=s)
display_img_and_heatmap("dog.jpg", heatmap_1)

probas_2 = forward_pass_resize("dog.jpg", (400, 640))
heatmap_2 = build_heatmap(probas_2, synset=s)
display_img_and_heatmap("dog.jpg", heatmap_2)

probas_3 = forward_pass_resize("dog.jpg", (800, 1280))
heatmap_3 = build_heatmap(probas_3, synset=s)
display_img_and_heatmap("dog.jpg", heatmap_3)
Image shape before resizing: (1600, 2560, 3)
Image batch size shape before forward pass: (1, 200, 320, 3)
size of heatmap: (7, 10)
Image shape before resizing: (1600, 2560, 3)
Image batch size shape before forward pass: (1, 400, 640, 3)
size of heatmap: (13, 20)
Image shape before resizing: (1600, 2560, 3)
Image batch size shape before forward pass: (1, 800, 1280, 3)
size of heatmap: (25, 40)

Combinando los 3 mapas de calor

Al combinar los mapas de calor a diferentes escalas, obtenemos una información mucho mejor sobre la ubicación del perro.

  • Combina los tres mapas de calor redimensionándolos a una forma similar y promediándolos.
  • Una norma geométrica funcionará mejor que el promedio estándar
from skimage.transform import resize

heatmap_1_r = resize(heatmap_1, (50,80), mode='reflect',
                     preserve_range=True, anti_aliasing=True)
heatmap_2_r = resize(heatmap_2, (50,80), mode='reflect',
                     preserve_range=True, anti_aliasing=True)
heatmap_3_r = resize(heatmap_3, (50,80), mode='reflect',
                     preserve_range=True, anti_aliasing=True)


heatmap_geom_avg = np.power(heatmap_1_r * heatmap_2_r * heatmap_3_r, 0.333)
display_img_and_heatmap("dog.jpg", heatmap_geom_avg)