Clase 7: Redes Convolucionales
La convención más común es utilizar imágenes de 24-bits 3 canales de \(2^8\) valores (es decir 8-bits) que representan la intensidad de los colores Rojo (R), Verde (G) y Azul (B). Las dimensiones de \(H\) y \(W\) definen la resolución en píxeles de la imágen.
Para importar imágenes en Pytorch existen distintas librerías como PIL u OpenCV. Ambas usan la convención de \((H,W,C)\), la diferencia está en el orden de los canels. PIL utiliza la convención RGB, mientras que OpenCV utiliza BGR por lo que se necesitan algunas convenciones adicionales.
Lamentablemente la convención que escogió Pytorch es que una imágen tiene (C, H, W), es decir, primero canales, y luego alto y ancho. Normalmente las librerías no usan esta convención por lo que una permutación o transposición de dimensiones va a ser necesario casi la mayoría de las veces.
Cuando tenemos un batch de imágenes entonces tendremos un Tensor de 4 dimensiones de dimensiones (N,C,H,W), donde \(N\) representa el Batch Size, \(C\) el número de Canales, \(H\) el alto y \(W\) el ancho.
Luego un Tensor de Dimensiones (32,3,224,512) implica que tenemos 32 imágenes RGB de dimensiones \(224\times512\).
Existe el mito de que las Redes Convolucionales se inspiraron en el funcionamiento del Cortex Visual humano. No sé si es tan así.
¿Por qué necesitamos Redes Convolucionales? Evitar la sobreparametrización. ¿Por qué esto es un problema?
Ojo
Esto es nuevamente un término marketero, porque no es una Convolucional real, sino una operación llamada Cross Correlation.
Kernel
El Kernel va a ser el set de parámetros que la red convolucional va a aprender. En palabras sencillas, la misma red aprende cuáles son los aspectos más relevantes de la imagen que le permitirán entender cómo clasificar o detectar elementos en ella.
El Kernel se aplica a todos los canales a la vez, lo cuál inicialmente lo hace ver como una operación bastante costosa computacionalmente.
El Kernel introduce el primer hiperparámetro de las CNN que es el Kernel Size. En general son cuadrados, y de dimensión impar.
Stride
Corresponde a la cantidad de pasos en que se mueve el Kernel. Un stride más grande implica feature maps más pequeños y menos detalles. Strides más pequeños retiene más detalles, pero implica un mayor número de operaciones.
Padding
Corresponde a un relleno para dar mayor movimiento del kernel. Permite evitar la reducción de dimensionalidad por parte de la convolución además de considerar la información de los bordes de la imagen. Se llama “valid” a no usar padding, y “same” a agregar suficientes píxeles para evitar la reducción de dimensión.
Input
Este tipo de redes no requiere que se le den las dimensiones de la imagen, pero sí espera recibir tensores de dimensión \((N,C_{in}, H_{in},W_{in})\).
Output
La Red convolucional devuelve un Tensor de Dimensiones \((N,C_{out}, H_{out}, W_{out})\). Donde:
\[H_{out} = \left\lfloor \frac{H_{in} + 2 \cdot padding[0] - dilation[0]\cdot (kernel\_size[0] - 1) - 1}{stride[0]} + 1 \right\rfloor\] \[W_{out} = \left\lfloor \frac{W_{in} + 2 \cdot padding[1] - dilation[1]\cdot (kernel\_size[1] - 1) - 1}{stride[1]} + 1 \right\rfloor\]
Es importante tener noción del tamaño de la imagen para poder escoger un kernel_size que recorra la imagen completa y que no deje partes sin convolucionar.
El Pooling también se aplica de manera móvil como una convolución. Pero a diferencia de esta normalmente no genera traslape.
Acá se introduce otro hiperparámetro que es el Pooling Size. En general es cuadrado pero de dimensión par.
Ojo
stride=None
implica stride = kernel_size
.
Importante mencionar que Average Pooling no permite Dilation.
\[H_{out} = \left\lfloor \frac{H_{in} + 2 \cdot padding[0] - dilation[0]\cdot (kernel\_size[0] - 1) - 1}{stride[0]} + 1 \right\rfloor\] \[W_{out} = \left\lfloor \frac{W_{in} + 2 \cdot padding[1] - dilation[1]\cdot (kernel\_size[1] - 1) - 1}{stride[1]} + 1 \right\rfloor\]
Feature Extractor - Encoder - Backbone
Corresponde al bloque de que generalmente contiene CNNs que se encargará de extraer features.
Flatten
Corresponde a una Operación Intermedia que dejará todos los píxeles de la imagen como un vector fila que puede ser tomado por la FFN.
Prediction Head - Head - MLP
Corresponde a una FFN que tomará las features aprendidas por la CNN y generará una predicción.
En este caso la implementación en Pytorch es similar a la 2D sólo que esperando tensores de dimensiones \((N,C_{in}, L_{in})\), donde \(C_{in}\) corresponde al número de canales, que en el caso de series de tiempo equivale a features, y \(L_{in}\) corresponde al largo de la secuencia.
La salida de la Conv1d tendrá dimensiones \((N,C_{out},L_{out})\) con:
\[L_{out} = \left\lfloor \frac{L_{in} + 2 \cdot padding - dilation \cdot (kernel\_size - 1) - 1}{stride} + 1 \right\rfloor\]
Este caso también es similar sólo que se esperan tensores de dimensiones \((N, C_{in}, D_{in}, H_{in}, W_{in})\) donde \(C_in\) corresponde al número de canales, \(D\) en el caso de un video corresponde al número de frames de tamaño \(H_{in} \times W_{in}\).
La salida de la Conv1d tendrá dimensiones \((N,C_{out},D_{out},H_{out},W_{out})\) con:
\[D_{out} = \left\lfloor \frac{D_{in} + 2 \cdot padding[0] - dilation[0] \cdot (kernel\_size[0] - 1) - 1}{stride[0]} + 1 \right\rfloor\] \[H_{out} = \left\lfloor \frac{H_{in} + 2 \cdot padding[1] - dilation[1]\cdot (kernel\_size[1] - 1) - 1}{stride[1]} + 1 \right\rfloor\] \[W_{out} = \left\lfloor \frac{W_{in} + 2 \cdot padding[2] - dilation[2]\cdot (kernel\_size[2] - 1) - 1}{stride[2]} + 1 \right\rfloor\]