Tensores, redes neuronales e imágenes#

Introducción#

En esta lección nos acercamos al objeto de trabajo del aprendizaje profundo: la redes neuronales. La hacemos mostrando como usamos tensores para representar redes neuronales. Adicionalmente, veremos como usamos los tensores en la representación de imágenes, uno de los tipos de datos mas recurrente en la inteligencia artificial.

Redes Neuronales#

La siguiente imagen muestra el estado en un instante de una una parte oculta de una red neuronal profunda.

Fuente: Alvaro Montenegro

El proceso puede modelarse en forma simplificada usando matrices y vectores como se ve a continuación.

\[\begin{split} W_{12}L_1 = L2 \to \begin{pmatrix} -1 & 0.4 & 1.5\\ 0.8 & 0.5 & 0.75 \\ 0.2 & -0.3 & 1\\ \end{pmatrix}\begin{pmatrix} 2.5\\ 4 \\ 1.2 \end{pmatrix} = \begin{pmatrix} 0.9\\ 4.9 \\ 0.5 \end{pmatrix} \end{split}\]

Observe por ejemplo que:

\[-1\times 2.5 + 0.4\times 4 + 1.5\times 1.2 = 0.9\]

En la fase de entrenamiento de la red neuronal, los pesos de la matriz se van modificando hasta que se encuentra un óptimo local. Este proceso ocurre en toda la estructura de la red.

Por lo que no parece extraño que las GPU y las TPU pasen todo el tiempo haciendo operaciones de este tipo, que al final se reduce a sumas y multiplicaciones.

Por otro lado, lo que ocurre es que los objetos que se procesan no necesariamente son vectores como en el ejemplo, y esto lleva a la necesidad de generalizar los conceptos.

Imágenes a color#

De manera clásica una imagen a color está compuesta de tres colores primarios: rojo (Red), verde (Green) y azul (Blue). Para generar una imagen a color un computador maneja tres planos de color, los cuales son controlados desde tensores tridimensionales. Considere el siguiente ejemplo.

Fuente: Alvaro Montenegro

Cada pixel (punto) de la imagen es representado por una valor numérico en el rango de 0 a 255, o en rango de valores reales entre cero y 1.

Construcción aleatoria de una imagen#

Considere el siguiente código Python.

import numpy as np
I=np.random.randint(0,255,size=(3,10,10))
print(I)
[[[ 27  41 188 219 233  71  44 246 117  40]
  [251 213  29  98 130 123  37 194  89 196]
  [192  75 156  79  90 205 119  24 112  89]
  [206 205  84 235 205  96 210  36 179  70]
  [249 115  92   0 231  50  93 193  23 233]
  [  1  80 142  56 198 158 238 216   3 193]
  [  8 142  31 186   5  47 214 179 107  89]
  [ 19 171  78 136 176  27 224 224  98 181]
  [ 85  87 203 156 140 233   5 220  54 198]
  [ 80 168  18  83 228  40  11   6 157  15]]

 [[ 22 144 252 237  16 245  71  66 239 174]
  [148  77 252  57  44  27 223 114 165 112]
  [174 164  23 124  42 220   0  49  97 227]
  [151 228  99  61 190 241   9 114 215 156]
  [185 138  40 176   5 241  22  91 160 118]
  [208 189 106 225 105   5 218 153 235 129]
  [ 63  87 176  10  77  68 146  13  93 132]
  [199  63  35 213  34  85  13 218 207 193]
  [ 57 207  44 200  90  21 142 137  33   0]
  [243  86  74  94 199 194 206 197 159 137]]

 [[146  60  93 232 130  96 137  32 164  65]
  [115 104  39   5  30 245 162   8 118  83]
  [241 250  63 217  43 108 139  53 246 183]
  [136  92 207   4 138  35  88  13 226 177]
  [ 20  95 191  59 117  55 116 171 209 226]
  [ 63 116 130  11  21 222  31 200 122  54]
  [ 59  19  53 151 110 153   9 179 207 121]
  [ 18  95 137 169 250 212 108  47 238 249]
  [188 155  73  95  88  68  86 152  85  79]
  [ 40 115 200  12  18  26 114 240 118  74]]]

Este tensor representa una imagen de tamaño \(10 \times 10\). Son tres planos de color \(10 \times 10\).

Observe que la primera dimensión corresponde a cada plano de color y las restantes dos dimensiones a las intensidades de cada color para cada punto.

Renderizar (dibujar en este caso), nos lleva a la siguiente imagen. Para esta sección require instalar matplotlib

# !conda install -c conda-forge matplotlib
import matplotlib.pyplot as plt

plt.imshow(I.T)
plt.show()
../../_images/t3_19_0.png

Observe que

(I.T).shape
(10, 10, 3)

Porque Python maneja las imágenes en este formato: Fila, columna y plano de color.

Imagen real#

Vamos a trabajar ahora con una imagen real. Para este ejercicio requiere instalar sklearn.

# conda install -c anaconda scikit-image
import numpy as np
import matplotlib.pyplot as plt


from skimage import data
from skimage.color import rgb2gray

original = data.astronaut()
grayscale = rgb2gray(original)

fig, axes = plt.subplots(1, 2, figsize=(8, 4))
ax = axes.ravel()

ax[0].imshow(original)
ax[0].set_title("Original")
ax[1].imshow(grayscale, cmap=plt.cm.gray)
ax[1].set_title("Grayscale")

fig.tight_layout()
plt.show()
../../_images/t3_26_0.png
Idata=np.array(grayscale)
print("\nLa imagen tiene forma: ",Idata.shape,"\n")
print(Idata)
La imagen tiene forma:  (512, 512) 

[[5.83434902e-01 4.14859216e-01 2.44058431e-01 ... 4.75007843e-01
  4.58213333e-01 4.69121961e-01]
 [6.75588235e-01 5.56006667e-01 4.49052941e-01 ... 4.68548627e-01
  4.56501176e-01 4.55958431e-01]
 [7.66334902e-01 7.00524314e-01 6.49276078e-01 ... 4.76406667e-01
  4.62104314e-01 4.53978431e-01]
 ...
 [6.81696471e-01 6.81979216e-01 6.71889020e-01 ... 0.00000000e+00
  2.82745098e-04 0.00000000e+00]
 [6.74694510e-01 6.68532941e-01 6.64030196e-01 ... 2.82745098e-04
  3.92156863e-03 0.00000000e+00]
 [6.70482353e-01 6.63189804e-01 6.52838824e-01 ... 0.00000000e+00
  3.92156863e-03 0.00000000e+00]]

Planos de color#

Idata = np.array(original)
print("\nLa imagen tiene forma: ",Idata.shape,"\n")
print("\nEscala de Rojos:\n\n",Idata[:511,:511,0],"\n")
print("\nEscala de Verdes:\n\n",Idata[:511,:511,1],"\n")
print("\nEscala de Azules:\n\n",Idata[:511,:511,2],"\n")
La imagen tiene forma:  (512, 512, 3) 


Escala de Rojos:

 [[154 109  63 ... 126 127 120]
 [177 144 113 ... 126 127 124]
 [201 182 168 ... 125 128 126]
 ...
 [186 188 184 ...   0   0   0]
 [186 186 183 ...   2   0   0]
 [183 182 185 ...  21   0   1]] 


Escala de Verdes:

 [[147 103  58 ... 120 120 117]
 [171 141 114 ... 118 118 115]
 [194 178 165 ... 119 120 116]
 ...
 [169 169 167 ...   0   0   0]
 [170 170 168 ...   2   0   0]
 [169 167 164 ...  21   0   1]] 


Escala de Azules:

 [[151 124 102 ... 114 115 106]
 [171 143 124 ... 111 112 108]
 [193 175 164 ... 113 117 112]
 ...
 [174 177 170 ...   0   0   1]
 [176 177 170 ...   3   0   1]
 [170 171 176 ...  16   1   1]] 
fig, (ax1, ax2,ax3) = plt.subplots(1, 3,figsize=(15,15))

ax1.imshow(Idata[:,:,0],cmap="Reds")
ax1.set_xlabel('Red')
ax2.imshow(Idata[:,:,1],cmap="Greens")
ax2.set_xlabel('Green')
ax3.imshow(Idata[:,:,2],cmap="Blues")
ax3.set_xlabel('Blue')
plt.show()
../../_images/t3_30_0.png

Manipulación de imágenes#

Intercambia dos planos de color#

import numpy as np
import matplotlib.pyplot as plt

from skimage import data
from skimage.color import rgb2gray

original = data.astronaut()

Idata_m = Idata
Idata_m[:,:,0], Idata_m[:,:,2] = Idata_m[:,:,2], Idata_m[:,:,0]

fig, axes = plt.subplots(1, 2, figsize=(8, 4))
ax = axes.ravel()

ax[0].imshow(original)
ax[0].set_title("Original")
ax[1].imshow(Idata_m)
ax[1].set_title("Modificada")

fig.tight_layout()
plt.show()
../../_images/t3_33_0.png

Suma una constante a la imagen#

fig, axes = plt.subplots(1, 2, figsize=(8, 4))
ax = axes.ravel()

k = 10
ax[0].imshow(original)
ax[0].set_title("Original")
ax[1].imshow(original + k)
ax[1].set_title("Modificada")

fig.tight_layout()
plt.show()
../../_images/t3_35_0.png
fig, axes = plt.subplots(1, 2, figsize=(8, 4))
ax = axes.ravel()

k = 2
ax[0].imshow(original)
ax[0].set_title("Original")
ax[1].imshow(original //k)
ax[1].set_title("Modificada")

fig.tight_layout()
plt.show()
../../_images/t3_36_0.png
Idata_m = Idata

Idata_m[:,:,0 ]=0

fig, axes = plt.subplots(1, 2, figsize=(8, 4))
ax = axes.ravel()

ax[0].imshow(original)
ax[0].set_title("Original")
ax[1].imshow(Idata_m)
ax[1].set_title("Modificada")

fig.tight_layout()
plt.show()
../../_images/t3_37_0.png
Idata
array([[[  0, 147, 151],
        [  0, 103, 124],
        [  0,  58, 102],
        ...,
        [  0, 120, 115],
        [  0, 117, 106],
        [  0, 119, 110]],

       [[  0, 171, 171],
        [  0, 141, 143],
        [  0, 114, 124],
        ...,
        [  0, 118, 112],
        [  0, 115, 108],
        [  0, 116, 105]],

       [[  0, 194, 193],
        [  0, 178, 175],
        [  0, 165, 164],
        ...,
        [  0, 120, 117],
        [  0, 116, 112],
        [  0, 114, 109]],

       ...,

       [[  0, 170, 176],
        [  0, 170, 177],
        [  0, 168, 170],
        ...,
        [  0,   0,   0],
        [  0,   0,   1],
        [  0,   0,   0]],

       [[  0, 169, 170],
        [  0, 167, 171],
        [  0, 164, 176],
        ...,
        [  0,   0,   1],
        [  0,   1,   1],
        [  0,   0,   0]],

       [[  0, 167, 172],
        [  0, 165, 169],
        [  0, 162, 171],
        ...,
        [  0,   0,   0],
        [  0,   1,   1],
        [  0,   0,   0]]], dtype=uint8)
fig, axes = plt.subplots(1, 2, figsize=(8, 4))
ax = axes.ravel()
ax[0].imshow(original)
ax[0].set_title("Original")
ax[1].imshow(255 - Idata)
ax[1].set_title("Modificada")

fig.tight_layout()
plt.show()
../../_images/t3_39_0.png

Colocar dos imagenes en un tensor#

Esta es una forma para organizar conjuntos de imágenes en un único tensor

original= np.expand_dims(original,axis=0)
original.shape
(1, 512, 512, 3)
Idata_m= np.expand_dims(Idata_m,axis=0)
images = np.concatenate((original, Idata_m),axis=0)
images.shape
(2, 512, 512, 3)
fig, axes = plt.subplots(1, 2, figsize=(8, 4))
ax = axes.ravel()
ax[0].imshow(images[0])
ax[0].set_title("Original")
ax[1].imshow(images[1])
ax[1].set_title("Modificada")

fig.tight_layout()
plt.show()
../../_images/t3_47_0.png

Ejercicios#

  1. Baje una imagen de Internet y la almacena localmente, o léala por ejemplo del repositorio de Aprendizaje Profundo.

  2. Lea la imagen. Apóyese en el siguiente código

  3. Repita el tratamiento de la imagen como hicimos en la lección

La imagen del ave fue tomada originalmente de omes-va.com.

import matplotlib.pyplot as plt
import numpy as np
from skimage import io

file_1 = 'https://raw.githubusercontent.com/AprendizajeProfundo/Libro-Fundamentos/main/Fundamentacion_Matematica/Imagenes/ave.jpeg'
# Fuente: Esta es la imagen original tomada de [omes-va.com](https://omes-va.com/trasladar-rotar-escalar-recortar-una-imagen-opencv/). Código tomado del mismo sitio.
img_array=io.imread(file_1)
plt.imshow(img_array)
plt.show()

original = np.array(img_array)
original.shape
../../_images/t3_50_0.png
(426, 640, 3)