%matplotlib inline
import warnings
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(1)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:
# 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_shapeVerifiquemos 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.layerspara 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 locationDatos 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_mapoutput = 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_mapdef 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)