<jupyter_start><jupyter_text>Ejercicio a entregarEn este ejercicio se debe realizar un recomendador basado en contenidos para las imágenes que se encuentran en la carpeta 'imagenes_recomendador' dentro de 'datasets'. El recomendador consitirá en obtener las cinco imágenes más similares para una determianda imagen. Para obtener esta recomendación los pasos a dar son:1. Cargar el *path* de todas las imagenes que se encuentran en la carpeta2. Para cada imagen obtener sus features, para ello usaremos el modelo de CNN *[ResNet](https://keras.io/applications/resnet)*3. Para una determianda imagen, obtener las cinco imagenes mas cercanas Ampliación voluntariaAplicando técnicas de clustering, segmentar los distitos productos del conjunto de imágenes. Obteniendose el número de grupos en los que se dividen, asi como dos imagenes de representantes de cada grupo.Para mejorar la eficiencia del sistema de recomendación, dada una imagen para recomendar, obtener la recomendación a partir de:1. Los cinco elementos más similares al elemento dentro de su grupo2. Los cinco elementos centrales de su grupo  Parte obligatoria PASO 1: Cargar el *path* de todas las imágenes que se encuentran en la carpetaEn este paso se debe cargar en la variable `lstImagenes` la ruta a todas las imágenes. Puedes usar la función `obtenerPathJpg`. Esta función recibe como parámetro la ruta de una carpeta y devuele una lista con todos los fichero .jpg que se encuentran es su interior.<jupyter_code>from google.colab import files
uploaded = files.upload()
!unzip datasets.zip
import os

def obtenerPathJpg(path):
    lstFicheros=[]
    for file in os.listdir(path):
        if file.endswith(".jpg"):
            lstFicheros.append(os.path.join(path, file))
    return lstFicheros

#Obtner imágenes
lstImagenes = obtenerPathJpg("datasets/imagenes_recomendador")<jupyter_output><empty_output><jupyter_text>Validación de los datos cargadosTras realizar la carga de los *path* en la variable `lstImagenes`, podemos validar a continuación los resultados. Si no se muestran de manera correcta el *path* del fichero junto con su imagen, esto nos indica que no se ha realizado de manera correcta la carga de los *path* de las imagenes en la variable `lstImagenes` en el bloque anterior.<jupyter_code>from IPython.display import Image, display

print lstImagenes[3]
display(Image(filename = lstImagenes[3], width=100, height=100))
print lstImagenes[30]
display(Image(filename = lstImagenes[30], width=100, height=100))<jupyter_output>datasets/imagenes_recomendador/10898.jpg<jupyter_text>PASO 2: Para cada imagen obtener sus *features*, para ello usaremos el modelo de CNN ResNetEn primer lugar, en este paso en necesario cargar el modelo *[ResNet](https://keras.io/applications/resnet)*, y una vez tenemos cargado el modelo, preprocesar cada una de las imágenes según este para posterirormente obtener las *features* obtenidas por la red. Almacenando en la variable `lstFeature`las *features* de todas las imagenes.**NOTAS**1. Para recorrer todas las imagenes puedes usar un bucle `for`, por ejemplo, `for rutaImagen in lstImagenes:`y dentro de este bucle obtenere la feature de cada una de las imagenes y añadirla a la variable lstFeatures2. Las listas posen un método append, mediante el cual podemso añadir un elemento a esta, por ejemplo, `lstFeatures.append(features)`<jupyter_code>from keras.applications.resnet50 import ResNet50
from keras.applications.resnet50 import preprocess_input
from keras.preprocessing import image
import numpy as np

#Carga del modelo de ResNet50
model = ResNet50(weights='imagenet', include_top=False)
#Recorrer todas las imágenes y generar la lista de features  
listFeatures = []
for i in lstImagenes:
  img = image.load_img(i, target_size=(224, 224))
  #Se convierte la imagen en un vector
  x = image.img_to_array(img)
  x = np.expand_dims(x, axis=0)
  #Se realiza el preprocesamiento segun las caracteristicas de la red 
  x = preprocess_input(x)
  featuresND = model.predict(x)
  features = np.array(featuresND).flatten()
  listFeatures.append(features)<jupyter_output><empty_output><jupyter_text>A continuación se muestran las features de las 20 primeras imagenes<jupyter_code>for i in range(20):
    print listFeatures[i]<jupyter_output>[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0.        0.        0.        ... 0.        0.        0.5184884]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]<jupyter_text>PASO 3: Para una determinada imagen, obtener las cinco imágenes más cercanasIndicando la posición de una determinada imagen de la lista de imagenes `lstImagenes`, se obtiene las cinco imagenes mas similares **Posición de la imágen a recomendar**<jupyter_code>indiceImagenRecomendar = 8<jupyter_output><empty_output><jupyter_text>**Búsqueda de las mas cercanas**Se calcula la similitud con el resto de imágenes y se alamcena las cinco mas cercanas en la variable `recomendaciones`**NOTAS**1. Puedes usar la función `similitudCoseno`, esta función devuelve la distancia coseno existente entre dos vectores de features2. Para obtener de manera mas cómoda las imágenes mas cercanas usaremos un *[heap](https://docs.python.org/2/library/heapq.html)*. Esta estructura de datos nos permite obtener de una manera rápida y eficiente los elementos que un menor valor de similitud. Para añadir un nuevo elemento puede usar una sentencia como `heapq.heappush(heap, (sim, lstImagenes[i]))`, donde `heap` sería la variable donde se van alamcenando de manera ordenada los valores de similitud, `sim` es la distancia coseno que se ha obtenido entre las dos imágenes y como segundo parámetro le pasamos la ruta a la imagen, para posteriormente poder recuperarla.<jupyter_code>from sklearn.metrics.pairwise import cosine_similarity
import heapq

def similitudCoseno(F1, F2):
    sim = cosine_similarity(F1.reshape(1, -1), F2.reshape(1, -1))
    return sim

i=0
heap= []

#Recorrer todas las features para obtener las imagen mas similar
for i in range(len(listFeatures)):
  sim= similitudCoseno(listFeatures[indiceImagenRecomendar], listFeatures[i])
  some= heapq.heappush(heap, (sim, lstImagenes[i]))
  heap.append(some)

#Con la siguiente linea puedes obtener las cinco recomendaciones más cercanas
recomendaciones = heapq.nlargest(5,heap)<jupyter_output><empty_output><jupyter_text>Se muestra la imagen indicada para recomendar y las cinco más similares, que se encuentran en la variable `recomendaciones`<jupyter_code>print 'Producto'
display(Image(filename = lstImagenes[indiceImagenRecomendar], width=100, height=100))
print 'Recomendaciones'
for recomendacion in recomendaciones:
    display(Image(filename = recomendacion[1], width=100, height=100))<jupyter_output>Producto
{'fraction_non_alphanumeric': 0.09363030217052064, 'fraction_numerical': 0.029507731593133777, 'mean_word_length': 4.389908256880734, 'pattern_counts': {'":': 0, '<': 26, '<?xml version=': 0, '>': 26, 'https://': 3, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '288161', 'license': 'Unlicense', 'n_tokens_mistral': 2602, 'n_tokens_neox': 2445, 'n_words': 891, 'path': 'keras_tf_pytorch/Notebooks/.ipynb_checkpoints/Ejercicio_entrega-checkpoint.ipynb', 'repo_name': 'andresdelarosa1887/Public-Projects', 'size': '7049'}