Esta es una adaptación al español de parte del tuto desarrollado por la gente de R Studio. Gracias a ellos por este gentil trabajo de traernos Keras a R.
He añadido unas notas buscando entender mejor y explicarlo a personas que se acercan al tema.
Si encuentra errores, por favor, no dude en escribir a villaoscarad@gmail.com
En caso de que no haya instalado Keras en R Studio, este tutorial funciona de maravilla.
Invocamos o cargamos la API, Keras, que es el framwork de trabajo que corre sbre el famoso TensorFlow.
library(keras)
Esto se logra descargando los pesos que el modelo previamente ha aprendido: el modelo restNet es un modelo de redes neuronales convolucionales con el que el equipo de Microsoft ganó el concurso ILSRVC 2015, superando el desempeño humano en el conjunto de datos ImageNet, el cual es tiene 100.000 imágenes pertenecientes a 100 categorías (1000 por cada una en promedio).
application_ es la forma en que Keras invoca modelos pre entrenados, de los cuales hay una lista. En el argumento “weights” se fija los pesos producto del entrenamiento en cual set de datos se quiere.
model <- application_resnet50(weights = 'imagenet')
Para que el experimento sea posible, vamos a cargar una imagen pertenenciente a una de las 100 categorías que conforman el ImageNet; pero no tiene que ser una igual a las incluidas allí.
creamos la ruta “img_path” a la imagen (podría ser un grupo, una carpeta) y se la pasamos a “image_load”, a la cual le pasamos el parámetro “target_size” con el fin de decirle de qué tamaño queremos que quede la imagen; 224x224 es el tamaño de las imágenes de ImageNet pasadas a ResNet50. Y finalmente volvemos esa imagen una matriz de números, que es la manera en que se pasan a los modelos.
img_path <- "/home/oscar/Pictures/Irish_wolfhound.jpeg"
img <- image_load(img_path, target_size = c(224,224))
x <- image_to_array(img)
Ahora simplemente nos aseguramos de tener un tensor cuyas dimensiones indiquen que tiene un único elemento pero con las dimensiones que necesrias para ser trabajadas por ResNet50: le hacemos el preprocesamiento necesario, redimensionamos la imagen.
Cuando decimos que “dim(x)” (las dimensiones de x) son iguales a “c(1, dim(x))”, lo que le decimos es que es de 1 x las dimensiones originales. Si fueran 50 imágenes, diríamos “c(50, dim(x))”: hablamos de un tensor o matriz tridimensional.
dim(x) <- c(1, dim(x))
x <- imagenet_preprocess_input(x)
Y al usar la función “imagenet_preprocess_input” estamos usando el método estandar de pre procesamiento de la imagen…
dim(x)
## [1] 1 224 224 3
Tenemos una imagen de 224x224 en 3 canales (RGB, Red Green Blue): se trata de una matriz de 224x224 con numeros del 0 (claro) al 255 (oscuro) para la gama de rojos, otra para la gama de verdes y otra para gama de azules. Su entretramado conforman una imagen.
Ahora hacemos la predicción o la clasificación de la imagen. Dado que ResNet50 nos va a dar la probabilidad de que pertenezca a cada una de las categorías (100 valores, cada uno del 0 al 1 indicando el grado de certeza de que la imagen pertenece a la categoría), es decir 100 valores, le vamos a pedir que nos diga los tres más probables solamente.
El operador “%>%” es como un embudo o un transductor que pasa el elemento de la izquierda al de la derecha como objeto. “predict” establece el porentaje de certeza de que la imagen pertenezca a cada una de las 100 categorías. Por eso, “imagenet_decode_prediction” toma “preds” y nos devuelve solamente las tres más altas (“top = 3”).
preds <- model %>% predict(x)
plot <- data.frame(imagenet_decode_predictions(preds, top = 3)[[1]])
library(knitr)
kable(plot, caption = "Clasificación")
| class_name | class_description | score |
|---|---|---|
| n02090721 | Irish_wolfhound | 0.8725274 |
| n02092002 | Scottish_deerhound | 0.0600075 |
| n02091244 | Ibizan_hound | 0.0286055 |
library(ggplot2)
ggplot(plot, aes(x=class_description, y=score, fill=class_description)) + geom_bar(stat = "identity") + ylab("Probabilidad de pertenencia a la clase") + xlab("Top 3 Clases a las que puede pertenecer") + ggtitle("Clasificación de la imagen según ResNet50 pre entrenado", subtitle = "Sólo las tres más probables")