{ "cells": [ { "cell_type": "markdown", "id": "5954adbb-830b-4de2-8028-6ddac8f362db", "metadata": {}, "source": [ "# CNN en Dataset Mninst" ] }, { "cell_type": "markdown", "id": "2084c356-133e-4554-b3c3-55713da23daa", "metadata": {}, "source": [ "La base de datos MNIST es una gran base de datos de dígitos escritos a mano que se usa comúnmente para entrenar varios sistemas de procesamiento de imágenes. La base de datos también se usa ampliamente para capacitación y pruebas en el campo del aprendizaje automático." ] }, { "cell_type": "markdown", "id": "3188d685-b3a9-445f-b656-eabaf49699ba", "metadata": {}, "source": [ "![title](img/MnistExamples.png)" ] }, { "cell_type": "markdown", "id": "34b9fd50-3d58-47b1-88b9-16f45a2a5cbb", "metadata": {}, "source": [ "### Cargamos librerías" ] }, { "cell_type": "code", "execution_count": 1, "id": "def98fa3-cad9-427c-bfdf-16e88dfc7467", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "from tensorflow import keras\n", "from tensorflow.keras import layers" ] }, { "cell_type": "markdown", "id": "9ad03e85-f89c-4f59-8d5e-70f12f99356e", "metadata": {}, "source": [ "### Preparamos los datos" ] }, { "cell_type": "code", "execution_count": 15, "id": "ec960e58-451b-4dd4-b17b-4713d96c0039", "metadata": {}, "outputs": [], "source": [ "# Total de clases a predecir.\n", "num_classes = 10\n", "\n", "# Tamaño de las imágenes. Todas las imágenes deben tener las mismas dimensiones.\n", "input_shape = (28, 28, 1)" ] }, { "cell_type": "code", "execution_count": 2, "id": "2d76102e-043c-4993-b43e-d7b20b6a49d3", "metadata": {}, "outputs": [], "source": [ "df = keras.datasets.mnist.load_data()" ] }, { "cell_type": "code", "execution_count": 3, "id": "7f17e06f-4b7e-4285-86db-eb7ae8f5cf2a", "metadata": { "scrolled": true, "tags": [] }, "outputs": [ { "data": { "text/plain": [ "((array([[[0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " ...,\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0]],\n", " \n", " [[0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " ...,\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0]],\n", " \n", " [[0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " ...,\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0]],\n", " \n", " ...,\n", " \n", " [[0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " ...,\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0]],\n", " \n", " [[0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " ...,\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0]],\n", " \n", " [[0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " ...,\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0]]], dtype=uint8),\n", " array([5, 0, 4, ..., 5, 6, 8], dtype=uint8)),\n", " (array([[[0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " ...,\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0]],\n", " \n", " [[0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " ...,\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0]],\n", " \n", " [[0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " ...,\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0]],\n", " \n", " ...,\n", " \n", " [[0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " ...,\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0]],\n", " \n", " [[0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " ...,\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0]],\n", " \n", " [[0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " ...,\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0]]], dtype=uint8),\n", " array([7, 2, 1, ..., 4, 5, 6], dtype=uint8)))" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Lo que cargamos son básicamente matrices de 28x28, con rangos de variación entre 0-255 que corresponden a la intensidad del gris.\n", "# O es el blanco puro, 255 es el negro puro.\n", "df" ] }, { "cell_type": "code", "execution_count": 4, "id": "e53d0d91-c9f0-4060-b72a-54a31a37e16f", "metadata": { "scrolled": true, "tags": [] }, "outputs": [ { "data": { "text/plain": [ "array([[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0],\n", " [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0],\n", " [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0],\n", " [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0],\n", " [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0],\n", " [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,\n", " 18, 18, 18, 126, 136, 175, 26, 166, 255, 247, 127, 0, 0,\n", " 0, 0],\n", " [ 0, 0, 0, 0, 0, 0, 0, 0, 30, 36, 94, 154, 170,\n", " 253, 253, 253, 253, 253, 225, 172, 253, 242, 195, 64, 0, 0,\n", " 0, 0],\n", " [ 0, 0, 0, 0, 0, 0, 0, 49, 238, 253, 253, 253, 253,\n", " 253, 253, 253, 253, 251, 93, 82, 82, 56, 39, 0, 0, 0,\n", " 0, 0],\n", " [ 0, 0, 0, 0, 0, 0, 0, 18, 219, 253, 253, 253, 253,\n", " 253, 198, 182, 247, 241, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0],\n", " [ 0, 0, 0, 0, 0, 0, 0, 0, 80, 156, 107, 253, 253,\n", " 205, 11, 0, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0],\n", " [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 1, 154, 253,\n", " 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0],\n", " [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 253,\n", " 190, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0],\n", " [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 190,\n", " 253, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0],\n", " [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35,\n", " 241, 225, 160, 108, 1, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0],\n", " [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 81, 240, 253, 253, 119, 25, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0],\n", " [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 45, 186, 253, 253, 150, 27, 0, 0, 0, 0, 0, 0,\n", " 0, 0],\n", " [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0, 16, 93, 252, 253, 187, 0, 0, 0, 0, 0, 0,\n", " 0, 0],\n", " [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0, 0, 0, 249, 253, 249, 64, 0, 0, 0, 0, 0,\n", " 0, 0],\n", " [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 46, 130, 183, 253, 253, 207, 2, 0, 0, 0, 0, 0,\n", " 0, 0],\n", " [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39,\n", " 148, 229, 253, 253, 253, 250, 182, 0, 0, 0, 0, 0, 0,\n", " 0, 0],\n", " [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 114, 221,\n", " 253, 253, 253, 253, 201, 78, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0],\n", " [ 0, 0, 0, 0, 0, 0, 0, 0, 23, 66, 213, 253, 253,\n", " 253, 253, 198, 81, 2, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0],\n", " [ 0, 0, 0, 0, 0, 0, 18, 171, 219, 253, 253, 253, 253,\n", " 195, 80, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0],\n", " [ 0, 0, 0, 0, 55, 172, 226, 253, 253, 253, 253, 244, 133,\n", " 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0],\n", " [ 0, 0, 0, 0, 136, 253, 253, 253, 212, 135, 132, 16, 0,\n", " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0],\n", " [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0],\n", " [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0],\n", " [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0]], dtype=uint8)" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[0][0][0]" ] }, { "cell_type": "code", "execution_count": 5, "id": "df3b58f0-bb75-41fc-988d-285859671a4a", "metadata": {}, "outputs": [], "source": [ "# Para este caso particular, y por cómo están los datos en datasets, podemos usar este método de particionado.\n", "(x_train, y_train), (x_test, y_test) = df" ] }, { "cell_type": "markdown", "id": "8eb47b2e-bd48-4253-a7ff-bcc826676757", "metadata": {}, "source": [ "### Escalamos los datos" ] }, { "cell_type": "code", "execution_count": 6, "id": "816dfa59-2703-42fe-94b5-93a632c1f258", "metadata": {}, "outputs": [], "source": [ "# Escalamos los datos en el rango [0,1]\n", "x_train = x_train.astype(\"float32\") / 255\n", "x_test = x_test.astype(\"float32\") / 255" ] }, { "cell_type": "markdown", "id": "3bf22736-8be1-4db8-ab9c-3c01088171ee", "metadata": { "tags": [] }, "source": [ "### Comprobamos que todas las imágenes tengan las mismas dimensiones" ] }, { "cell_type": "code", "execution_count": 7, "id": "ce77a363-8657-40a4-8b3b-8ec7045b8281", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(60000, 28, 28)" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x_train.shape" ] }, { "cell_type": "code", "execution_count": 8, "id": "4ed56ca9-f027-4343-b192-c742387da1ba", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(10000, 28, 28)" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x_test.shape" ] }, { "cell_type": "code", "execution_count": 9, "id": "063416dc-d0f8-4db9-9927-aeee5869ed20", "metadata": {}, "outputs": [], "source": [ "x_train = np.expand_dims(x_train, 3)\n", "x_test = np.expand_dims(x_test, 3)" ] }, { "cell_type": "code", "execution_count": 10, "id": "388a328f-22c2-426f-9731-b09fdf8ba7a5", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(60000, 28, 28, 1)" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x_train.shape" ] }, { "cell_type": "code", "execution_count": 11, "id": "8151751c-2a63-485d-9e3a-3b7d99a69366", "metadata": { "scrolled": true, "tags": [] }, "outputs": [ { "data": { "text/plain": [ "array([5, 0, 4, ..., 5, 6, 8], dtype=uint8)" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Variable clase a predecir\n", "y_train" ] }, { "cell_type": "code", "execution_count": 12, "id": "d881a78d-236d-47ba-9f49-0a205c50e135", "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "(60000,)" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "y_train.shape" ] }, { "cell_type": "code", "execution_count": 13, "id": "1fef005e-819f-4522-8077-463074694d78", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(10000,)" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "y_test.shape" ] }, { "cell_type": "markdown", "id": "86192cb5-c4c7-4e06-a362-a56c8fc4699e", "metadata": {}, "source": [ "### Convertir la variable a predecir en una matriz binaria de clases" ] }, { "cell_type": "code", "execution_count": 16, "id": "38664675-da49-4359-a7f3-5be089a85a18", "metadata": {}, "outputs": [], "source": [ "# La transformación es similar a One Hot Encoding, pero con arrays\n", "y_train = keras.utils.to_categorical(y_train, num_classes)\n", "y_test = keras.utils.to_categorical(y_test, num_classes)" ] }, { "cell_type": "code", "execution_count": 17, "id": "6848335b-154e-4522-8b4d-6bc53b4689d5", "metadata": { "scrolled": true, "tags": [] }, "outputs": [ { "data": { "text/plain": [ "array([[0., 0., 0., ..., 0., 0., 0.],\n", " [1., 0., 0., ..., 0., 0., 0.],\n", " [0., 0., 0., ..., 0., 0., 0.],\n", " ...,\n", " [0., 0., 0., ..., 0., 0., 0.],\n", " [0., 0., 0., ..., 0., 0., 0.],\n", " [0., 0., 0., ..., 0., 1., 0.]], dtype=float32)" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "y_train" ] }, { "cell_type": "markdown", "id": "8789de64-64a8-4f7a-b813-c5247239fb43", "metadata": {}, "source": [ "### Construimos el modelo" ] }, { "cell_type": "code", "execution_count": 18, "id": "19031f6c-81ef-4c3a-98aa-a062ed279e4a", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2022-04-26 18:41:47.089458: E tensorflow/stream_executor/cuda/cuda_driver.cc:271] failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected\n", "2022-04-26 18:41:47.089493: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:156] kernel driver does not appear to be running on this host (mazinger): /proc/driver/nvidia/version does not exist\n", "2022-04-26 18:41:47.089859: I tensorflow/core/platform/cpu_feature_guard.cc:151] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations: AVX2 FMA\n", "To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.\n" ] } ], "source": [ "num_filtros = 32\n", "kernel_size = 3\n", "pool_size = 2\n", "\n", "model = keras.Sequential(\n", " [\n", " keras.Input(shape=input_shape), # Capa de entrada\n", " layers.Conv2D(num_filtros, kernel_size=kernel_size, activation=\"relu\"), # Total de kernels, tamaño de los mismos y función de activación a aplicar\n", " layers.MaxPooling2D(pool_size=pool_size), # Tamaño del muestreo a aplicar (devolverá número filas input / 2, número columnas input / 2)\n", " layers.Conv2D(num_filtros*2, kernel_size=kernel_size, activation=\"relu\"), # Segunda capa convolucional, puede tener el mismo tamaño\n", " layers.MaxPooling2D(pool_size=pool_size), # 2 segundo submuestreo\n", " layers.Flatten(), # Aplanamiento de la salida convolucional\n", " layers.Dropout(0.5), # Aplicamos dropout para mitigar el overfiting en nuestra CNN\n", " # Desactivamos de manera aleatoria un % de neuronas que no se tomarán en cuenta en el \n", " # forwardpropagation, ni en el backwardpropagation\n", " #layers.Dense(64, activation='relu'),\n", " layers.Dense(num_classes, activation=\"softmax\"),\n", " ]\n", ")\n" ] }, { "cell_type": "markdown", "id": "fc0df0e2-1c99-4bf7-9b33-eeddab1d8d6e", "metadata": {}, "source": [ "* La razón de utilizar un Dropout, es que generalmente las neuronas cercanas suelen aprender patrones relacionados y estas relaciones pueden llegar a formar un patrón muy específico con los datos.\n", "* Al hacer el dropout, el total de neuronas de la red se reduce, por lo que las neuronas están \"obligadas\" a trabajar de forma \"solitaria\", sin depender de las demás.\n", "* Valores en el Dropout cercanos a 0, implica no desactivación de neuronas, cercanos a 1 implica la desactivación de casi todas las neuronas.\n", "* El Dropout, puede aplicarse por capa. Aquí lo hemos aplicado al final de la red.\n", "* El Dropout NO SE APLICA en la capa de salida, ya que allí necesitamos todas la neuronas activas.\n", "* Sólo hemos usado una capa 'Dense', pero es habitual en CNN añadir más capas con más neuronas y funciones de activación ReLU\n" ] }, { "cell_type": "code", "execution_count": 19, "id": "8d8478cd-0eac-4fd0-b760-bdbe7bc80b41", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Model: \"sequential\"\n", "_________________________________________________________________\n", " Layer (type) Output Shape Param # \n", "=================================================================\n", " conv2d (Conv2D) (None, 26, 26, 32) 320 \n", " \n", " max_pooling2d (MaxPooling2D (None, 13, 13, 32) 0 \n", " ) \n", " \n", " conv2d_1 (Conv2D) (None, 11, 11, 64) 18496 \n", " \n", " max_pooling2d_1 (MaxPooling (None, 5, 5, 64) 0 \n", " 2D) \n", " \n", " flatten (Flatten) (None, 1600) 0 \n", " \n", " dropout (Dropout) (None, 1600) 0 \n", " \n", " dense (Dense) (None, 10) 16010 \n", " \n", "=================================================================\n", "Total params: 34,826\n", "Trainable params: 34,826\n", "Non-trainable params: 0\n", "_________________________________________________________________\n" ] } ], "source": [ "# Vemos qué tenemos\n", "model.summary()" ] }, { "cell_type": "markdown", "id": "1e3d6724-bbdb-4e54-ade5-38fcb866b742", "metadata": {}, "source": [ "### Entrenamiento del modelo" ] }, { "cell_type": "markdown", "id": "7cbbf04b-2714-4713-90ac-a189b0d6f433", "metadata": {}, "source": [ "Keras incluye el argumento validation_split que nos permite utilizar una fracción de los datos de entrenamiento como datos de validación. Esa fracción de datos no se usa para el entrenamiento y se reserva para evaluar la pérdida y cualquier otra métrica al final de cada ciclo.\n" ] }, { "cell_type": "code", "execution_count": 20, "id": "2072b4ad-9825-41c1-b409-e7b6f75e4a1b", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Epoch 1/15\n", "422/422 [==============================] - 18s 41ms/step - loss: 0.3685 - accuracy: 0.8876 - val_loss: 0.0832 - val_accuracy: 0.9768\n", "Epoch 2/15\n", "422/422 [==============================] - 16s 37ms/step - loss: 0.1087 - accuracy: 0.9668 - val_loss: 0.0571 - val_accuracy: 0.9855\n", "Epoch 3/15\n", "422/422 [==============================] - 17s 40ms/step - loss: 0.0817 - accuracy: 0.9749 - val_loss: 0.0490 - val_accuracy: 0.9867\n", "Epoch 4/15\n", "422/422 [==============================] - 17s 40ms/step - loss: 0.0685 - accuracy: 0.9789 - val_loss: 0.0409 - val_accuracy: 0.9895\n", "Epoch 5/15\n", "422/422 [==============================] - 17s 41ms/step - loss: 0.0598 - accuracy: 0.9814 - val_loss: 0.0410 - val_accuracy: 0.9898\n", "Epoch 6/15\n", "422/422 [==============================] - 17s 39ms/step - loss: 0.0543 - accuracy: 0.9836 - val_loss: 0.0372 - val_accuracy: 0.9900\n", "Epoch 7/15\n", "422/422 [==============================] - 17s 40ms/step - loss: 0.0505 - accuracy: 0.9843 - val_loss: 0.0365 - val_accuracy: 0.9887\n", "Epoch 8/15\n", "422/422 [==============================] - 16s 39ms/step - loss: 0.0465 - accuracy: 0.9850 - val_loss: 0.0370 - val_accuracy: 0.9887\n", "Epoch 9/15\n", "422/422 [==============================] - 18s 43ms/step - loss: 0.0431 - accuracy: 0.9859 - val_loss: 0.0329 - val_accuracy: 0.9915\n", "Epoch 10/15\n", "422/422 [==============================] - 19s 44ms/step - loss: 0.0418 - accuracy: 0.9865 - val_loss: 0.0350 - val_accuracy: 0.9898\n", "Epoch 11/15\n", "422/422 [==============================] - 17s 40ms/step - loss: 0.0381 - accuracy: 0.9873 - val_loss: 0.0308 - val_accuracy: 0.9915\n", "Epoch 12/15\n", "422/422 [==============================] - 18s 42ms/step - loss: 0.0376 - accuracy: 0.9876 - val_loss: 0.0307 - val_accuracy: 0.9917\n", "Epoch 13/15\n", "422/422 [==============================] - 17s 41ms/step - loss: 0.0356 - accuracy: 0.9880 - val_loss: 0.0298 - val_accuracy: 0.9915\n", "Epoch 14/15\n", "422/422 [==============================] - 18s 43ms/step - loss: 0.0330 - accuracy: 0.9896 - val_loss: 0.0281 - val_accuracy: 0.9928\n", "Epoch 15/15\n", "422/422 [==============================] - 17s 40ms/step - loss: 0.0325 - accuracy: 0.9894 - val_loss: 0.0278 - val_accuracy: 0.9922\n" ] }, { "data": { "text/plain": [ "" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "batch_size = 128\n", "epochs = 15\n", "\n", "model.compile(loss=\"categorical_crossentropy\", # tenemos más de 2 clases, si fuera una clasificación binaria usaríamos binary_crossentropy\n", " optimizer=\"adam\", \n", " metrics=[\"accuracy\"])\n", "\n", "model.fit(x_train, \n", " y_train, \n", " batch_size=batch_size, \n", " epochs=epochs, \n", " validation_split=0.1)" ] }, { "cell_type": "markdown", "id": "3156d516-b6a9-4920-b057-23fa0fe39f48", "metadata": {}, "source": [ "### Evaluamos el modelo" ] }, { "cell_type": "code", "execution_count": 21, "id": "d74861f4-dd77-410a-b2f1-0ae39da4aee7", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Pérdida datos Test: 0.023285096511244774\n", "Precisión datos Test: 0.9927999973297119\n" ] } ], "source": [ "score = model.evaluate(x_test, y_test, verbose=0)\n", "print(\"Pérdida datos Test:\", score[0])\n", "print(\"Precisión datos Test:\", score[1])" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.13" } }, "nbformat": 4, "nbformat_minor": 5 }