Created
January 14, 2022 18:50
-
-
Save RodolfoFerro/b9d1ed80179bd3ed949f96706c6b7b46 to your computer and use it in GitHub Desktop.
Introducción a las redes neuronales convolucionales con TensorFlow y Keras
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"nbformat": 4, | |
"nbformat_minor": 0, | |
"metadata": { | |
"colab": { | |
"name": "Introducción a las redes neuronales convolucionales con TensorFlow y Keras", | |
"provenance": [], | |
"collapsed_sections": [], | |
"include_colab_link": true | |
}, | |
"kernelspec": { | |
"name": "python3", | |
"display_name": "Python 3" | |
}, | |
"accelerator": "GPU" | |
}, | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "view-in-github", | |
"colab_type": "text" | |
}, | |
"source": [ | |
"<a href=\"https://colab.research.google.com/gist/RodolfoFerro/b9d1ed80179bd3ed949f96706c6b7b46/introducci-n-a-las-redes-neuronales-convolucionales-con-tensorflow-y-keras.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "R6jO_1gISKxk" | |
}, | |
"source": [ | |
"# Introducción a las redes neuronales convolucionales con TensorFlow y Keras\n", | |
"\n", | |
"> **Rodolfo Ferro** <br>\n", | |
"> Google Dev Expert en ML, 2022.\n", | |
"\n", | |
"## Contenidos\n", | |
"\n", | |
"#### **Sección III**\n", | |
"\n", | |
"1. **Bases:** Aprendizaje de neuronas\n", | |
"2. **Código:** Entrenamiento de una neurona\n", | |
"3. **Bases:** Conceptos importantes\n", | |
"4. **Bases:** Imágenes\n", | |
"\n", | |
"#### **Sección IV**\n", | |
"\n", | |
"4. **Bases:** El dataset de modas\n", | |
"5. **Código:** Preparación de datos\n", | |
"6. **Código:** Creación del modelo multicapa (MLP)\n", | |
"7. **Código:** Entrenamiento del modelo\n", | |
"8. **Código:** Evaluación y predicción\n", | |
"\n", | |
"#### **Sección V**\n", | |
"\n", | |
"9. **Bases:** Convoluciones\n", | |
"10. **Código:** Creación del modelo convolucional (CNN)\n", | |
"11. **Código:** Entrenamiento del modelo\n", | |
"12. **Código:** Evaluación y predicción\n", | |
"\n", | |
"\n", | |
"13. **Cierre:** Sesión de preguntas y respuestas" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "xNVG2PnSEtQN" | |
}, | |
"source": [ | |
"## **Sección III**" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"source": [ | |
"### Aprendizaje de neuronas\n", | |
"\n", | |
"Veamos cómo se puede entrenar una sola neurona para hacer una predicción.\n", | |
"\n", | |
"Para este problema construiremos un perceptrón simple, como el propuesto por McCulloch & Pitts, usando la función sigmoide.\n", | |
"\n", | |
"#### **Planteamiento del problema:**\n", | |
"\n", | |
"Queremos mostrarle a una neurona simple un conjunto de ejemplos para que pueda aprender cómo se comporta una función. El conjunto de ejemplos es el siguiente:\n", | |
"\n", | |
"- `(1, 0)` debería devolver `1`.\n", | |
"- `(0, 1)` debe devolver `1`.\n", | |
"- `(0, 0)` debería devolver `0`.\n", | |
"\n", | |
"Entonces, si ingresamos a la neurona el valor de `(1, 1)`, debería poder predecir el número `1`.\n", | |
"\n", | |
"> ¿Puedes adivinar la función?\n", | |
"\n", | |
"#### ¿Que necesitamos hacer?\n", | |
"\n", | |
"Programar y entrenar una neurona para hacer predicciones.\n", | |
"\n", | |
"En concreto, vamos a hacer lo siguiente:\n", | |
"\n", | |
"- Construir la clase y su constructor.\n", | |
"- Definir la función sigmoidea y su derivada\n", | |
"- Definir el número de épocas para el entrenamiento.\n", | |
"- Resolver el problema y predecir el valor de la entrada deseada" | |
], | |
"metadata": { | |
"id": "2k4ZBY7drHpQ" | |
} | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"import numpy as np\n", | |
"\n", | |
"\n", | |
"class sigmoid_neuron():\n", | |
" def __init__(self, n):\n", | |
" \"\"\"Constructor of the class.\"\"\"\n", | |
" np.random.seed(123)\n", | |
" self.synaptic_weights = None # TODO. Use np.random.random((n, 1)) to gen values in (-1, 1)\n", | |
"\n", | |
" def __sigmoid(self, x):\n", | |
" \"\"\"Sigmoid function.\"\"\"\n", | |
" # TODO.\n", | |
" pass\n", | |
"\n", | |
" def __sigmoid_derivative(self, x):\n", | |
" \"\"\"Derivative of the Sigmoid function.\"\"\"\n", | |
" # TODO.\n", | |
" pass\n", | |
"\n", | |
" def train(self, training_inputs, training_output, iterations):\n", | |
" \"\"\"Training function.\"\"\"\n", | |
" for iteration in range(iterations):\n", | |
" output = self.predict(training_inputs)\n", | |
" error = training_output.reshape((len(training_inputs), 1)) - output\n", | |
" adjustment = np.dot(training_inputs.T, error *\n", | |
" self.__sigmoid_derivative(output))\n", | |
" self.synaptic_weights += adjustment\n", | |
"\n", | |
" def predict(self, inputs):\n", | |
" \"\"\"Prediction function.\"\"\"\n", | |
" return self.__sigmoid(np.dot(inputs, self.synaptic_weights))" | |
], | |
"metadata": { | |
"id": "2NKx40hxqmo4" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"source": [ | |
"### Generando las muestras\n", | |
"\n", | |
"Ahora podemos generar una lista de ejemplos basados en la descripción del problema." | |
], | |
"metadata": { | |
"id": "Ym_oEzbhxYKT" | |
} | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"# Training samples:\n", | |
"input_values = [] # TODO. Define the input values as a list of tuples.\n", | |
"output_values = [] # TODO. Define the desired outputs.\n", | |
"\n", | |
"training_inputs = np.array(input_values)\n", | |
"training_output = np.array(output_values).T.reshape((3, 1))" | |
], | |
"metadata": { | |
"id": "BYW9aYSCxc1q" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"source": [ | |
"### Entrenando la neurona\n", | |
"\n", | |
"Para hacer el entrenamiento, primero definiremos una neurona. De forma predeterminada, contendrá pesos aleatorios (ya que aún no se ha entrenado):" | |
], | |
"metadata": { | |
"id": "DJUYV8H-xf7Y" | |
} | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"# Initialize Sigmoid Neuron:\n", | |
"neuron = sigmoid_neuron(2)\n", | |
"print(\"Initial random weights:\")\n", | |
"neuron.synaptic_weights" | |
], | |
"metadata": { | |
"id": "cThkcQGMxrX8" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"# TODO.\n", | |
"# We can modify the number of epochs to see how it performs.\n", | |
"epochs = 0\n", | |
"\n", | |
"# We train the neuron a number of epochs:\n", | |
"neuron.train(training_inputs, training_output, epochs)\n", | |
"print(\"New synaptic weights after training: \")\n", | |
"neuron.synaptic_weights" | |
], | |
"metadata": { | |
"id": "WnuCP6eHxtQk" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"source": [ | |
"### Haciendo predicciones" | |
], | |
"metadata": { | |
"id": "7vPb5a65x0bA" | |
} | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"# We predict to verify the performance:\n", | |
"one_one = np.array((1, 1))\n", | |
"print(\"Prediction for (1, 1): \")\n", | |
"neuron.predict(one_one)" | |
], | |
"metadata": { | |
"id": "SrYM3ODKxwvD" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "Rtpuj0PBqWYc" | |
}, | |
"source": [ | |
"## **Sección IV**" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "1Z7JrTygMDSx" | |
}, | |
"source": [ | |
"### El dataset de modas\n", | |
"\n", | |
"Comencemos importando TensorFlow." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "LPB4nBh8MFDm" | |
}, | |
"source": [ | |
"import tensorflow as tf\n", | |
"print(tf.__version__)" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "p65n1ePSMYm8" | |
}, | |
"source": [ | |
"Los datos de Fashion MNIST están disponibles directamente en la API de conjuntos de datos de `tf.keras`. Los cargas así:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "Wgked3UaMJW4" | |
}, | |
"source": [ | |
"fashion_mnist = tf.keras.datasets.fashion_mnist" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "UsEGBNwrMSac" | |
}, | |
"source": [ | |
"Llamar a `load_data` en este objeto nos dará dos conjuntos con los valores de entrenamiento y prueba para los gráficos que contienen las prendas y sus etiquetas." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "1XdP6qF1MLR6" | |
}, | |
"source": [ | |
"(training_images, training_labels), (test_images, test_labels) = fashion_mnist.load_data()" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "6c0eSrlvMs6H" | |
}, | |
"source": [ | |
"¿Cómo se ven estos valores?\n", | |
"\n", | |
"Imprimamos una imagen de entrenamiento y una etiqueta de entrenamiento para ver." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "3CdTltfNM0qF" | |
}, | |
"source": [ | |
"import numpy as np\n", | |
"import matplotlib.pyplot as plt\n", | |
"np.set_printoptions(linewidth=200)\n", | |
"\n", | |
"\n", | |
"# Set index of image to be seen\n", | |
"img_index = 5999 # 6000 -1\n", | |
"\n", | |
"# Plot image\n", | |
"plt.imshow(training_images[img_index], cmap='gray')\n", | |
"plt.axis(False)\n", | |
"\n", | |
"print(\"Label:\", training_labels[img_index])\n", | |
"print(\"Matrix:\", training_images[img_index])" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "CxfNdPU3NQge" | |
}, | |
"source": [ | |
"### Preparación de los datos\n", | |
"\n", | |
"Notarás que todos los valores están entre 0 y 255. Si estamos entrenando una red neuronal, por varias razones es más fácil si transformamos los valores para tratar todos con valores entre 0 y 1. Este proceso se llama **normalización**." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "vWoPQWCGNdnB" | |
}, | |
"source": [ | |
"training_images = training_images / 255.0\n", | |
"test_images = test_images / 255.0" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "32Dx5PzgJ3gK" | |
}, | |
"source": [ | |
"import numpy as np\n", | |
"import matplotlib.pyplot as plt\n", | |
"np.set_printoptions(linewidth=200)\n", | |
"\n", | |
"\n", | |
"# Set index of image to be seen\n", | |
"img_index = 3000 # 6000 -1\n", | |
"\n", | |
"# Plot image\n", | |
"plt.imshow(training_images[img_index], cmap='gray')\n", | |
"plt.axis(False)\n", | |
"\n", | |
"print(\"Label:\", training_labels[img_index])\n", | |
"print(\"Matrix:\", training_images[img_index])" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "6QLVhw7SOCd8" | |
}, | |
"source": [ | |
"training_images[0].shape" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "bTaT1RjyNjqV" | |
}, | |
"source": [ | |
"### Creación del modelo\n", | |
"\n" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "g-myY9JWNvtY" | |
}, | |
"source": [ | |
"mlp_model = tf.keras.models.Sequential([\n", | |
" tf.keras.layers.Flatten(), \n", | |
" # TODO. Dense -> 256, ReLU\n", | |
" # TODO. Dense -> 10, Softmax\n", | |
"])" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "dwkxtrHdNvHg" | |
}, | |
"source": [ | |
"### Entrenamiento del modelo" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "F9LHH0f6N5Hi" | |
}, | |
"source": [ | |
"mlp_model.compile(\n", | |
" optimizer=tf.optimizers.SGD(),\n", | |
" loss='sparse_categorical_crossentropy',\n", | |
" metrics=['accuracy']\n", | |
")" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"model.summary()" | |
], | |
"metadata": { | |
"id": "tRaD1lDx7Du5" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "ybq9AzJiN8ZV" | |
}, | |
"source": [ | |
"mlp_model.fit(training_images, training_labels, epochs=3)" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "cH9mfZMTN8_H" | |
}, | |
"source": [ | |
"### Evaluación del modelo" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "rHCV5BrAN-pq" | |
}, | |
"source": [ | |
"mlp_model.evaluate(test_images, test_labels)" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "w-hQX4NNOd_D" | |
}, | |
"source": [ | |
"### Predicción\n" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "GaDFuXyROfZY" | |
}, | |
"source": [ | |
"import random\n", | |
"\n", | |
"test_index = random.randint(0, 10000 - 1)\n", | |
"\n", | |
"plt.imshow(test_images[test_index], cmap='viridis')\n", | |
"plt.axis(False)\n", | |
"\n", | |
"print(\"Label:\", test_labels[test_index])\n", | |
"input_image = np.reshape(test_images[test_index], (1, 784))\n", | |
"prediction = mlp_model.predict(np.expand_dims(input_image, axis=-1))\n", | |
"print(\"Prediction:\", np.argmax(prediction))" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "RHA0nk24QEVz" | |
}, | |
"source": [ | |
"prediction" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "3jLJvM0V1edu" | |
}, | |
"source": [ | |
"## **Sección V**" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"import numpy as np\n", | |
"from scipy import misc\n", | |
"import matplotlib.pyplot as plt\n", | |
"\n", | |
"\n", | |
"# We load a sample image\n", | |
"img = misc.ascent()\n", | |
"\n", | |
"plt.imshow(img, cmap='gray')\n", | |
"plt.grid(False)\n", | |
"plt.axis('off')\n", | |
"plt.show()" | |
], | |
"metadata": { | |
"id": "B7Ke46U11KYN" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"img_transformed = np.copy(img)\n", | |
"size_x = img_transformed.shape[0]\n", | |
"size_y = img_transformed.shape[1]" | |
], | |
"metadata": { | |
"id": "LQQzn0cO2EMW" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"# Let's experiment with different values\n", | |
"\n", | |
"filter = [[1, 2, 1], [2, 4, 2], [1, 2, 1]]\n", | |
"# filter = [[-1, -2, -1], [0, 0, 0], [1, 2, 1]]\n", | |
"# filter = [[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]\n", | |
"\n", | |
"weight = 1/8" | |
], | |
"metadata": { | |
"id": "U6qAVNzF2En4" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"for x in range(1, size_x - 1):\n", | |
" for y in range(1, size_y - 1):\n", | |
" convolution = 0.0\n", | |
" convolution = convolution + (img[x - 1, y - 1] * filter[0][0])\n", | |
" convolution = convolution + (img[x, y - 1] * filter[0][1])\n", | |
" convolution = convolution + (img[x + 1, y - 1] * filter[0][2])\n", | |
" convolution = convolution + (img[x - 1, y] * filter[1][0])\n", | |
" convolution = convolution + (img[x, y] * filter[1][1])\n", | |
" convolution = convolution + (img[x + 1, y] * filter[1][2])\n", | |
" convolution = convolution + (img[x - 1, y + 1] * filter[2][0])\n", | |
" convolution = convolution + (img[x, y + 1] * filter[2][1])\n", | |
" convolution = convolution + (img[x + 1, y + 1] * filter[2][2])\n", | |
" convolution = convolution * weight\n", | |
" \n", | |
" if convolution < 0:\n", | |
" convolution = 0\n", | |
" if convolution > 255:\n", | |
" convolution = 255\n", | |
" \n", | |
" img_transformed[x, y] = convolution" | |
], | |
"metadata": { | |
"id": "D7DtjEm62F4q" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"plt.imshow(img_transformed, cmap='gray')\n", | |
"plt.grid(False)\n", | |
"plt.axis('off')\n", | |
"plt.show()" | |
], | |
"metadata": { | |
"id": "SNS6EKJF2HKa" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "omoy_gsr22xe" | |
}, | |
"source": [ | |
"### Creación del modelo\n", | |
"\n", | |
"Para este modelo se agregarán algunas capas convolucionales.\n", | |
"\n", | |
"Como inspiración, podemos recrear LeNet5 de Yann LeCun:\n", | |
"\n", | |
"<img src=\"https://miro.medium.com/max/4348/1*PXworfAP2IombUzBsDMg7Q.png\">" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"cnn_model = tf.keras.models.Sequential([\n", | |
" \n", | |
" # First conv layer + subsampling\n", | |
" tf.keras.layers.Conv2D(64, (3, 3), activation='relu', input_shape=(28, 28, 1)),\n", | |
" tf.keras.layers.MaxPooling2D(2, 2),\n", | |
"\n", | |
" # Second conv layer + subsampling\n", | |
" # TODO. Conv2D -> 256, (3, 3), ReLU\n", | |
" # TODO. MaxPool\n", | |
"\n", | |
" # Third layer (flatten)\n", | |
" tf.keras.layers.Flatten(),\n", | |
"\n", | |
" # Fourth layer (dense)\n", | |
" # TODO. Dense -> 128, ReLU\n", | |
"\n", | |
" # Fifth layer (output)\n", | |
" tf.keras.layers.Dense(10, activation='softmax')\n", | |
"])" | |
], | |
"metadata": { | |
"id": "Bpg1bC9b2ImO" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "JBoAlg9V27t8" | |
}, | |
"source": [ | |
"### Entrenamiento del modelo" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"cnn_model.compile(\n", | |
" optimizer=tf.optimizers.SGD(),\n", | |
" loss='sparse_categorical_crossentropy',\n", | |
" metrics=['accuracy']\n", | |
")" | |
], | |
"metadata": { | |
"id": "V0dlEBI52opy" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"model.summary()" | |
], | |
"metadata": { | |
"id": "NjQCtzBM7E0k" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"cnn_model.fit(training_images, training_labels, epochs=2)" | |
], | |
"metadata": { | |
"id": "rAzIo2YA2soz" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "f381BSCR2_DQ" | |
}, | |
"source": [ | |
"### Evaluación del modelo" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"cnn_model.evaluate(test_images, test_labels)" | |
], | |
"metadata": { | |
"id": "uciUKRC12ur5" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "jz-zeSn_3CZk" | |
}, | |
"source": [ | |
"### Predicción\n" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"import random\n", | |
"\n", | |
"test_index = random.randint(0, 10000 - 1)\n", | |
"\n", | |
"plt.imshow(test_images[test_index], cmap='viridis')\n", | |
"plt.axis(False)\n", | |
"\n", | |
"print(\"Label:\", test_labels[test_index])\n", | |
"input_image = np.reshape(test_images[test_index], (1, 28, 28, 1))\n", | |
"prediction = cnn_model.predict(input_image)\n", | |
"print(\"Prediction:\", np.argmax(prediction))" | |
], | |
"metadata": { | |
"id": "vY5cgS0E2xBc" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"source": [ | |
"### Explora las siguientes situaciones\n", | |
"\n", | |
"- Modifica el número de capas y parámetros de convolución por capa\n", | |
"- Modifica el número de épocas de entrenamiento\n", | |
"- Explora resultados con otros conjuntos de datos\n", | |
"- ¿Exportar modelos entrenados? Ojo: https://www.tensorflow.org/guide/keras/save_and_serialize?hl=es-419" | |
], | |
"metadata": { | |
"id": "BpmIVA0W3-RE" | |
} | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"# Guardar el Modelo\n", | |
"model.save('path_to_my_model.h5')\n", | |
"\n", | |
"# Recrea exactamente el mismo modelo solo desde el archivo\n", | |
"new_model = keras.models.load_model('path_to_my_model.h5')" | |
], | |
"metadata": { | |
"id": "Mumt7y0v6-Uz" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
} | |
] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment