{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"markdown","source":"# Universidad Politécnica Salesiana \n## Presentación de modelo de red neuronal convolucional CNN\n\nDescripción Dataset: \n \nEn la presente practica realizaremos la clasificación entre perros y gatos en base al conjunto de datos llamado Asirra disponible en kaggle consiste en 25,000 de imágenes que fueron clasificadas manualmente por personas de miles de refugios de animales dichas imágenes están etiquetadas como 1= perro, 0= gato , este conjunto de datos tiene cierto grado de complejidad porque las imágenes ofrecen distintos tonos de iluminación y distintas poses en las que se encuentran los perros como los gatos.\n\nEnlace \n[https://www.kaggle.com/c/dogs-vs-cats](https://)","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"<h1>Se importan las librerias necesarias para la practica</h1>","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport zipfile\nimport os\nfrom keras.preprocessing.image import load_img, ImageDataGenerator\nfrom keras.utils import to_categorical\nfrom sklearn.model_selection import train_test_split\nimport matplotlib.pyplot as plt\nimport random\nfrom keras.models import model_from_json\n\nwith zipfile.ZipFile(\"../input/dogs-vs-cats/train.zip\", \"r\") as z:\n    z.extractall(\".\")\n\nwith zipfile.ZipFile(\"../input/dogs-vs-cats/test1.zip\", \"r\") as z:\n    z.extractall(\".\")\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h2>Descripción del Dataset</h>","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"\nEste conjunto de datos está conformado por 25.000 imágenes entonces en el siguiente bloque de código procederemos a obtener información de las etiquetas, recorriéndolas mediante un ciclo for, Luego procedemos a generar el dataframe para su posterior estudio.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# Lista de las categorias\ncategorias = []\n# Lista de archivos dentro de los datos de train\narchivos = os.listdir(\"train\")\n# Bucle para obtener los nombres de los archivos (Etiquetas de salida)\nfor archivo in archivos:\n    categoria = archivo.split('.')[0]\n    if categoria == 'dog':\n        categorias.append(\"dog\")\n    else:\n        categorias.append(\"cat\")\n        \n# Se crea un dataframe en base del nombre del archivo y la categoria (tipo de animal)\ndf = pd.DataFrame({\n    'archivo': archivos,\n    'categoria': categorias\n})\nprint(categoria, '\\n', df)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h2>Splitting Del Dataset</h2>","execution_count":null},{"metadata":{},"cell_type":"markdown","source":" Separamos el conjunto de train y test, luego indicamos que los índices o puteros estén en el comienzo de los dataframes.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# Separamos dos conjuntos, train(80% del dataset) y test(20%).\ntrain, test = train_test_split(df, test_size=0.20, random_state=42)\n\n# Reseteamos los index para vayan al comienzo de daatframe.\ntrain = train.reset_index(drop=True)\ntest = test.reset_index(drop=True)\n\n# Imprimimos el tamano de los dataframes.\nprint(train.shape, '<-->', test.shape)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h2>Preprocesamiento De Los Datos</h2>","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"Establecemos un conjunto de parámetros para generar más imágenes partiendo de las que ya tenemos, buscando generar más datos para que la red neuronal entrene con mas información, estos parámetros se fijan en la variable train_image_data. Luego hacemos uso del método flow_from_dataframe() donde especificamos los parámetros anteriores y hacemos referencia a el apartado de train del dataset anterior, pro ultimo procedemos a realizar una normalización de los valores de los pixeles. \n\nLas imágenes de este conjunto de datos tienen la dimensión de 128x128 y contiene tres canales.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# Generador De Entrenamiento (Preprocesamiento de las imagenes)\nTAM_IMG = (128, 128)\n\"\"\"\nGeneramos nuevas imagenes en base a las pre existentes, por ejmplo, podemos cambiar el rango de rotacion, \ncortamos la imagen, hacemos zoom, volteamos, entre otras tecnicas para que de esta manera podamos tener\nuna mayor cantidad de imagenes para entrenar y hacer el testing.\n\n\"\"\"\ntrain_image_data = ImageDataGenerator(\n    rotation_range = 15,\n    rescale = 1./255,\n    shear_range = 0.1,\n    zoom_range=0.2,\n    horizontal_flip = True,\n    width_shift_range = 0.1,\n    height_shift_range = 0.1\n)\n\n# Procedemos ha generar las imagenes y preprocesarlas.\ntrain_generador = train_image_data.flow_from_dataframe(\n    train,\n    'train/',\n    x_col = 'archivo',\n    y_col = 'categoria',\n    target_size = TAM_IMG,\n    class_mode = 'categorical',\n    batch_size = 32\n)\n\n# Escalamos la imagen diviendo cada pixel para 255.\ntest_image_data = ImageDataGenerator(rescale=1./255)\ntest_generador = test_image_data.flow_from_dataframe(\n    test,\n    'train/',\n    x_col = 'archivo',\n    y_col = 'categoria',\n    target_size = TAM_IMG,\n    class_mode = 'categorical',\n    batch_size = 32\n)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h2>Modelo De La Red Neuronal Convolucional</h2>","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"El modelo de red neuronal propuesto presentamos tres de capas convolucionales de 32, 64, 128 neuronas las donde se aplica un filtro(kernel) de 3x3 con activación relu (en la primera capa se establece la dimensión de la imagen en este caso es 128x128 con 3 canales), además se realizamos un max pooling (obtiene los pixeles más representativos) de una dimensión de 2x2, La capa de aplanamiento consta de 256 neuronas.\n\nEn la capa de salida tenemos solamente dos neuronas porque en este caso de estudio vamos a clasificar dos clases (perros y gatos) donde aplicamos una activación softmax.\n\nEl modelo general tendrá una función de perdida categorical_crossentropy en conjunto con un optimizador rmsprop.\n","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# Modelo para el entrenamiento\nfrom keras.models import Sequential\nfrom keras.layers import Conv2D, MaxPooling2D, Dropout, Flatten, Dense, Activation, BatchNormalization\n\nmodelo = Sequential()\n\nmodelo.add(Conv2D(32, (3, 3), activation='relu', input_shape=(128, 128, 3)))\nmodelo.add(BatchNormalization())\nmodelo.add(MaxPooling2D(pool_size=(2, 2)))\nmodelo.add(Dropout(0.25))\n\nmodelo.add(Conv2D(64, (3, 3), activation='relu'))\nmodelo.add(BatchNormalization())\nmodelo.add(MaxPooling2D(pool_size=(2, 2)))\nmodelo.add(Dropout(0.25))\n\nmodelo.add(Conv2D(128, (3, 3), activation='relu'))\nmodelo.add(BatchNormalization())\nmodelo.add(MaxPooling2D(pool_size=(2, 2)))\nmodelo.add(Dropout(0.25))\n\nmodelo.add(Conv2D(128, (3, 3), activation='relu'))\nmodelo.add(BatchNormalization())\nmodelo.add(MaxPooling2D(pool_size=(2, 2)))\nmodelo.add(Dropout(0.25))\n\nmodelo.add(Flatten())\nmodelo.add(Dense(512, activation = 'relu'))\nmodelo.add(BatchNormalization())\nmodelo.add(Dropout(0.5))\nmodelo.add(Dense(2, activation='softmax'))\n\nmodelo.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy'])\nmodelo.summary()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h2> Entrenamiento De La CNN </h2>","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"train_shape = train.shape[0]\ntest_shape = test.shape[0]\n\nhistory = modelo.fit_generator(\n    train_generador,\n    epochs = 25,\n    validation_data = test_generador,\n    validation_steps = test_shape//64,\n    steps_per_epoch = train_shape//64,\n)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h2>Obtención De Los Resultados </h2>","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"accuracy_training = history.history['accuracy']\naccuracy_testing = history.history['val_accuracy']\nepochs = 26","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.rcParams[\"figure.figsize\"] = (12,8)\nplt.grid()\nplt.plot(accuracy_training, color='b', label=\"Training accuracy\")\nplt.xticks(np.arange(1, epochs, 1))\nplt.xlabel('EPOCHS')\nplt.ylabel('Accuracy en Training')\nplt.tight_layout()\nplt.show()\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.rcParams[\"figure.figsize\"] = (12,8)\nplt.grid()\nplt.plot(accuracy_testing, color='r')\nplt.xticks(np.arange(1, epochs, 1))\nplt.xlabel('EPOCHS')\nplt.ylabel('Accuracy en Testing')\nplt.tight_layout()\nplt.show()\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h2> Almacenamiento Del Modelo y Pesos </h2>","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"Declaramos las funciones que nos permitirán guardar y cargar los modelos de la red neuronal y también guardar los pesos de la misma.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def guardar_pesos(nombre_archivo='pesos.h5'):\n    modelo.save_weights(nombre_archivo)\n\ndef guardar_modelo(nombre_archivo='modelo.json'):\n    modelo_json = modelo.to_json()\n    with open(nombre_archivo, \"w\") as json_file:\n        json_file.write(modelo_json)\n\ndef cargar_modelo(archivo_modelo='modelo.json', archivo_pesos='pesos.h5'):\n    with open(archivo_modelo, 'r') as f:\n        modelo = model_from_json(f.read())\n    \n    modelo.load_weights(archivo_pesos)\n    \n    return modelo\n\nmodelo = cargar_modelo(archivo_modelo='../input/cats-v-dogs-leo/modelo.json', archivo_pesos='../input/cats-v-dogs-leo/pesos.h5')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h2> Listado De Archivos Para Testing </h2>","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"archivos_test = os.listdir(\"test1\")\ntest1 = pd.DataFrame({\n    'archivo': archivos_test\n})\nmuestras = test1.shape[0]\nprint(muestras)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h2> Preprocesamiento De Los Datos Para Testing </h2>","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"Declaramos un Preprocesador para las imagenes de test, este procesador se encarga de genenrar mas imágenes para que la red aprenda con un numero mayor de registros en test.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# Preprocesamiento y generador de imagenes para testing.\nTAM_IMG = (128, 128)\n\ntest_generador = ImageDataGenerator(rescale=1./255)\ntest_gen = test_generador.flow_from_dataframe(\n    test1,\n    'test1',\n    x_col = 'archivo',\n    y_col = None,\n    class_mode = None,\n    target_size = TAM_IMG,\n    batch_size = 32,\n    shuffle = False\n)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h2> Predicción De Los Datos De Testing </h2>","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"prediccion = modelo.predict_generator(test_gen, steps=np.ceil(muestras/32))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h2> Agrupamiento De Los Resultados</h2>","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"test1['categoria'] = np.argmax(prediccion, axis = 1)\nlabel_map = dict((v, k) for k, v in train_generador.class_indices.items())\ntest1['categoria'] = test1['categoria'].replace(label_map)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h2> Predicción De Resultados A Través De URL's </h2>","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"Declaramos una función que nos permite predecir si lo que representa una imagen corresponde a un perro o gato, como parámetro recibimos la url de la imagen a clasificar y como resultado obtenemos imprimimos la imagen ingresada acompañada del porcentaje de precisión con la que la red neuronal determina para esa imagen. ","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"from io import BytesIO\nfrom six.moves import urllib\nfrom keras.preprocessing import image\n\nTAM_IMG = (128, 128)\n\n\ndef predecir_img(URL):\n    img = None\n    with urllib.request.urlopen(URL) as url:\n        img = load_img(BytesIO(url.read()), target_size=(128, 128))\n    imagen = img\n    img = image.img_to_array(img)\n    img = np.expand_dims(img, axis=0)\n    img /= 255\n    resultado = modelo.predict(img)\n    val0 = resultado.tolist()[0][0]\n    val1 = resultado.tolist()[0][1]\n    if val0 > val1:\n        return ('GATO', val0, imagen)\n    elif val1 > val0:\n        return ('PERRO', val1, imagen)\n\nplt.figure(figsize=(12, 12))\n    \nanimal, accuracy, imagen = predecir_img('https://static.iris.net.co/semana/upload/images/2019/6/18/620159_1.jpg')\nprint(animal +', probabilidad: ', str(round(accuracy*100, 2))+'%')\nplt.subplot(5, 3, 1)\nplt.imshow(imagen)\n\nanimal, accuracy, imagen = predecir_img('https://www.petdarling.com/articulos/wp-content/uploads/2014/08/gatos-persa.jpg?width=1200&enable=upscale')\nprint(animal +', probabilidad: ', str(round(accuracy*100, 2))+'%')\nplt.subplot(5, 3, 2)\nplt.imshow(imagen)\n\nplt.tight_layout()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h3> Predicción De Imágenes A Través De Imágenes De Testing </h3>","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"Método donde se puede visualizar una imagen del dataset determinando por un índice.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# METODO \nfrom keras.preprocessing import image\n\ndef display_stats(sample_id = 5):\n    train_len = len([name for name in os.listdir('test1')])\n    \n    if sample_id < train_len:\n        names = []\n        datos = dict()\n        for name in os.listdir('test1'):\n            names.append(name)\n        file = load_img('test1/'+ names[sample_id], target_size=(128, 128))\n        datos['Imagen:'] = names[sample_id]\n        img = image.img_to_array(file)\n        datos['Valor minimo:'] = np.min(img)\n        datos['Valor maximo:'] = np.max(img)\n        datos['Shape:'] = img.shape\n        img = np.expand_dims(img, axis=0)\n        img /= 255\n        \n        resultado = modelo.predict(img)\n        val0 = resultado.tolist()[0][0]\n        val1 = resultado.tolist()[0][1]\n        if val0 > val1:\n            #return ('GATO', val0, imagen)\n            datos['% Prediccion:'] = round(val0*100, 2)\n            datos['ETIQUETA'] = 'GATO'\n        elif val1 > val0:\n            datos['% Prediccion:'] = round(val1*100, 2)\n            datos['ETIQUETA'] = 'PERRO'\n        for x, y in datos.items():\n            print(x, '\\t', y)\n        print()\n        plt.imshow(file)\n \n# EJEMPLO PERRO\ndisplay_stats(27)\n# EJEMPLO GATO\n#display_stats(98)\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Concluciones:\n\n*  En cuanto a lo elaborado en esta práctica aprendemos sobre el manejo de imágenes para ingresar dicha información en una red neuronal aplicando reducción de dimensiones y capas que obtienen la información más relevante de las imágenes.\n*  Frente a los resultados obtenidos podemos establecer que en determinados casos una optimización de parámetros no refleja mejora en la precisión de una red neuronal.\n* En particular las redes neuronales tienen mejor desempeño en comparación con otros algoritmos ya que simulan el comportamiento de las redes neuronales humanas.\n","execution_count":null}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}