Muchas veces queremos que nuestras aplicaciones cuenten con funcionalidades de Inteligencia Artificial (IA), pero programar una Red Neuronal no es algo muy trivial incluso entrenarla sería una operación que, en la mayoría de las veces, consume gran cantidad de tiempo incluso para ordenadores con buenas características. Pero todo no es negro..., existen librerías muy potentes que hacen todas estas operaciones de la manera más optimizada posible, librerías que son actualmente utilizadas en casi todo el ámbito de Internet. Les pongo un ejemplo: al realizar una simple búsqueda en Google, se están ejecutando gran cantidad de algoritmos de IA que son los que permiten filtrar nuestra búsqueda y mostrarnos el contenido más acertado. Uno de estos algoritmos son los que permiten clasificar las imágenes y que hoy les muestro como usarlo.
Antes que todo les comento brevemente acerca de las librerías y herramientas que estaremos empleando:
En este post se usará Google Colab para no preocuparnos por la configuración del entorno ni la instalación de dependencias. Aunque se puede hacer perfectamente creando un entorno virtual con virtualenv
o con conda
.
Empezaremos importando las librería necesarias:
Importamos las librerías de Numpy
, TensorFlow
y Keras
:
import numpy
import tensorflow as tf
import keras
Importamos el módulo necesario para el trabajo con imágenes.
from keras.preprocessing import image
El trabajo con imágenes lo podemos hacer con cualquier librería de Python para procesar imágenes, pero ya que estamos utilizando keras
empleamos la que trae implementada.
Ahora importamos InceptionV3
que es uno de los modelos que trae keras
para la clasificación de imágenes. Este modelo esta entrenado sobre el dataset de imagenet de Google y clasifica una imagen en un conjunto de 1000 clases posibles.
También importamos decode_predictions
para poder mapear las clases.
from keras.applications.inception_v3 import InceptionV3, decode_predictions
Creamos una instancia de nuestro modelo:
iv3 = InceptionV3()
Esto tardará algunos minutos porque se tendrá que descargar el modelo. Por lo que sugiero que si estas en un cuaderno jumpyter
, aisles esta línea y la ejecutes una sola vez.
Ya lo tenemos todo listo, ahora precedemos a cargar la imagen y construir el tensor de entrada.
x = image.img_to_array(image.load_img("./img/dog.jpg", target_size=(299, 299)))
Con image.load_img
cargamos la imagen y con target_size
especificamos con que ancho y alto queremos cargarla. Se escoge el valor de 299 porque lo especifica la API. Con la función image.img_to_array
convertimos la imagen en un arreglo de tres dimensiones.
Si hacemos print(x.shape)
la salida será (299, 299, 3)
(height, width, RGB)
.
Los valores de RGB pertenecen al intervalo [0, 255]
pero para la entrada debemos transformarlo al intervalo [-1, 1]
.
x /= 255
x -= 0.5
x *= 2
Hay que tener en cuenta que el tensor de entrada para InceptionV3
debe tener 4 dimensiones, esto es así porque en la primera dimensión hay que especificarle si la entrada contiene una o más imágenes. Por lo que debemos cambiar la forma de nuestro tensor.
x = x.reshape([1, x.shape[0], x.shape[1], x.shape[2]])
Si hacemos print(x.shape)
la salida será (1, 299, 299, 3)
.
Ya podemos hacer que nuestro modelo analice la imagen con la función predict
.
y = iv3.predict(x)
Esta función retorna una matriz de 1x1000
que contiene las probabilidades que corresponden a cada clase. Por lo que la probabilidad más alta será la clasificación de nuestra imagen. Podíamos encontrar nosotros mismo este valor con un simple algoritmo de búsqueda pero mejor utilizamos decode_predictions
que nos devuelve una matriz con las 5 primeras probabilidades.
print(decode_predictions(y))
Para la imagen cargada tenemos la siguiente salida:
[[('n02099601', 'golden_retriever', 0.7242692),
('n02099712', 'Labrador_retriever', 0.05614732),
('n02104029', 'kuvasz', 0.045885734),
('n02111500', 'Great_Pyrenees', 0.015037952),
('n03223299', 'doormat', 0.0037699142)]]
Como se puede apreciar le dá una probabilidad del 72,4% a golden_retriever
que es una raza de perro.
Veremos ahora algunos otros ejemplos:
[[('n02276258', 'admiral', 0.40548688),
('n02281787', 'lycaenid', 0.35930005),
('n02279972', 'monarch', 0.018525653),
('n02277742', 'ringlet', 0.009797901),
('n02264363', 'lacewing', 0.009077313)]]
[[('n03792782', 'mountain_bike', 0.36966863),
('n03127747', 'crash_helmet', 0.18513201),
('n03208938', 'disk_brake', 0.17603053),
('n03785016', 'moped', 0.107951425),
('n09193705', 'alp', 0.005377572)]]
Hasta aquí este artículos. Este modelo aunque no es exacto es bastante acertado y es utilizado en un gran número de aplicaciones. Espero que encuentres un lugar para él en tu app...