Herramientas de usuario

Herramientas del sitio


clase:iabd:pia:1eval:tema01

Diferencias

Muestra las diferencias entre dos versiones de la página.


clase:iabd:pia:1eval:tema01 [2025/11/03 11:37] (actual) – creado - editor externo 127.0.0.1
Línea 1: Línea 1:
 +====== 1. Introducción a las redes neuronales ======
 +Es este tema vamos a ver un ejemplo concreto de una red neuronal.
 +
 +
 +
 +
 +===== Definición del problema =====
 +Vamos a ver un ejemplo muy sencillo de red neuronal que averigüe el tipo de una flor. Para ello vamos a usar un conjunto de datos que se llaman el [[https://es.wikipedia.org/wiki/Conjunto_de_datos_flor_iris|Conjunto de datos flor iris]]. 
 +
 +Para ello vamos a usar las siguientes variables de entrada:
 +  * El largo de su pétalo: Medido en cm
 +  * El ancho de su pétalo: Medido en cm
 +
 +
 +
 +
 +{{:clase:iabd:pia:1eval:flor.jpg?400|}} 
 +
 +
 +Este conjunto de datos pretende distinguir entre los siguientes tres tipos de flores:
 +  * Setosa
 +  * Versicolor
 +  * Virginica'
 +
 +{{:clase:iabd:pia:1eval:tipos_flores2.png|}}
 +
 +
 +En la siguiente figura se muestra los valores del largo y ancho del pétalo según el tipo de flor:
 +
 +{{:clase:iabd:pia:1eval:all_iris.png|}}
 +
 +
 +¿Serías capaz con tu inteligencia "natural" , averiguar el tipo de flor según los valores del largo de sépalo y pétalo?
 +
 +
 +  Si longitud_petalo < 2.5 → Setosa
 +  Si longitud_petalo ≥ 2.5:
 +    Si ancho_petalo < 1.7 → Versicolor
 +    Si ancho_petalo ≥ 1.7 → Virginica
 +
 +Este "algoritmo o IA" lo podemos representar en python así:
 +
 +<sxh python>
 +def predict(longitud_petalo,ancho_petalo):
 +    if longitud_petalo<2.5:
 +        return 0
 +    else:
 +        if ancho_petalo>=1.7:
 +            return 2
 +        else:
 +            return 1
 +</sxh>
 +
 +Y se puede mostrar en la siguiente figura
 +
 +
 +{{:clase:iabd:pia:1eval:intro_ia_algoritmo.png|}}
 +
 +
 +las IAs realmente son algoritmos, solo que el algoritmo se crea casi automáticamente a partir de los datos. 
 +
 +Una figura con el mismo problema pero creado por una IA sería el siguiente:
 +
 +{{:clase:iabd:pia:1eval:intro_ia_red_neuronal.png|}}
 +
 +
 +<note>
 +Realmente el Conjunto de datos flor iris tiene 4 datos de entrada:
 +  * El largo de su sépalo
 +  * El largo de su pétalo
 +  * El ancho de su sépalo
 +  * El ancho de su pétalo
 +
 +</note>
 +
 +===== La red neuronal =====
 +Como es el primer tema, solo vamos a usar 2 tipos de flor para hacer más fácil el problema.
 +
 +Veamos ahora algunos datos:
 +
 +|  **X**  ||  **Y**  ||
 +|  **Largo Pétalo**  |  **Ancho Pétalo**  |  **Valor flor**  |  **Nombre Flor** 
 +|  1.4  |  0.2  |  0  |  Setosa  |
 +|  1.3  |  0.2  |  0  |  Setosa  |
 +|  1.3  |  0.3  |  0  |  Setosa  |
 +|  1.5  |  0.4  |  0  |  Setosa  |
 +|  1.4  |  0.2  |  0  |  Setosa  |
 +|  1.2  |  0.2  |  0  |  Setosa  |
 +|  1.7  |  0.4  |  0  |  Setosa  |
 +|  1.6  |  0.2  |  0  |  Setosa  |
 +|  1.3  |  0.2  |  0  |  Setosa  |
 +|  1.2  |  0.2  |  0  |  Setosa  |
 +|  3.5  |  1.0  |  1  |  Versicolor  |
 +|  4.5  |  1.5  |  1  |  Versicolor  |
 +|  3.5  |  1.0  |  1  |  Versicolor  |
 +|  4.4  |  1.4  |  1  |  Versicolor  |
 +|  3.5  |  1.0  |  1  |  Versicolor  |
 +|  4.1  |  1.3  |  1  |  Versicolor  |
 +|  4.8  |  1.8  |  1  |  Versicolor  |
 +|  4.4  |  1.3  |  1  |  Versicolor  |
 +|  3.9  |  1.2  |  1  |  Versicolor  |
 +|  4.5  |  1.3  |  1  |  Versicolor  |
 +
 +
 +
 +La red neuronal lo único que va a hacer es "aprender" a crear una función matemática que dado el largo del pétalo y el ancho del pétalo calcule el tipo de flor:
 +
 +$$ tipo \: flor=f(largo \: petalo,ancho \: petalo) $$
 +
 +<note tip>Debido a que las redes neuronales solo trabajan con números usaremos los siguientes números para los tipos de flor:
 +  * **0**:Setosa
 +  * **1**:Versicolor
 +</note>
 +
 +
 +Vamos a hacer la siguiente red neuronal:
 +
 +{{:clase:iabd:pia:1eval:ejemplo_primera_red_neuronal.svg?800|}}
 +
 +
 +Esta red neuronal, consta de una serie de neuronas (ya contaremos mas adelante que es una neurona) que se pasan valores de unas a otras. Son cada uno de los círculos. Las neuronas se organiza en capas:
 +  * Capa de entrada (Círculos amarillos): Es una única capa por donde entran los datos de entrada. Es decir los valores del largo del pétalo y el ancho del pétalo. Por lo tanto en este caso debe haber **2 neuronas** , una por cada valor de entrada.
 +  * Capas ocultas (Círculos verdes): Son varias capas, las cuales calculan de que tipo es cada flor. La primera capa oculta consta de **6 neuronas**. La segunda capa oculta consta de **12 neuronas** . La última capa oculta consta de **6 neuronas**.
 +  * Capa de salida (Círculos rojos): Es una única capa que es la que genera el resultado de la red neuronal. Como la red genera un único número la capa tiene solo **1 neurona**.
 +
 +
 +===== Google Colaboratory =====
 +[[https://colab.research.google.com/|Google Colaboratory]] es un IDE para programar en Python. El formato del IDE sige lo que se llaman "Jupyter Notebooks" que son ficheros con extensión "ipynb". Estos ficheros se pueden abrir desde VS Code u otros IDEs.
 +
 +Ves a la página de [[https://colab.research.google.com/|Google Colaboratory]], pincha en "Nuevo Cuaderno" y ya puedes empezar a programar en Python.
 +
 +
 +Una explicación completa de Google Colab la puedes ver en video [[https://www.youtube.com/watch?v=8VFYs3Ot_aA|Introducción a Google Colab, una noble y completa guía]].
 +
 +<note tip>En otro tema veremos como usar Jupyter Notebooks en VS Code.</note>
 +
 +
 +===== Código en Python =====
 +Veamos ahora el código python de la red neuronal.
 +
 +El código completo es el siguiente:
 +
 +
 +<sxh python>
 +import random
 +import numpy as np
 +import tensorflow as tf
 +from tensorflow.keras.models import Sequential
 +from tensorflow.keras.layers import Dense
 +from sklearn.datasets import load_iris
 +
 +iris=load_iris()
 +
 +longitudes_petalos=iris.data[0:99,2]
 +anchos_petalos=iris.data[0:99,3]
 +flower_type=iris.target[0:99]
 +
 +x=np.column_stack((longitudes_petalos,anchos_petalos))
 +y=flower_type
 +
 +
 +np.random.seed(5)
 +tf.random.set_seed(5)
 +random.seed(5)  
 +
 +model=Sequential()
 +model.add(Dense(6, activation='relu',input_dim=2))
 +model.add(Dense(12, activation='relu'))
 +model.add(Dense(6, activation='relu'))
 +model.add(Dense(1, activation='sigmoid'))
 +model.compile(loss='binary_crossentropy')
 +
 +
 +model.fit(x, y,epochs=100) 
 +
 +
 +print(model.predict(np.array([[1.4,0.2]])))
 +print(model.predict(np.array([[4.4,1.3]])))
 +
 +</sxh>
 +
 +Ahora vamos a ver todo el código paso a paso.
 +
 +<sxh python>
 +import random
 +import numpy as np
 +import tensorflow as tf
 +from tensorflow.keras.models import Sequential
 +from tensorflow.keras.layers import Dense
 +from sklearn.datasets import load_iris
 +</sxh>
 +
 +Estas líneas simplemente hacer los "import" de varias cosas que vamos a usar. 
 +
 +<sxh python>
 +longitudes_petalos=iris.data[0:99,2]
 +anchos_petalos=iris.data[0:99,3]
 +flower_type=iris.target[0:99]
 +
 +x=np.column_stack((longitudes_petalos,anchos_petalos))
 +y=flower_type
 +</sxh>
 +
 +Hemos cargado los datos y hemos creado 3 arrays:
 +  * ''longitudes_petalos'': Con la longitud de cada pétalo que es la columna 2 de la matriz ''data''
 +  * ''anchos_petalos'': Con la anchura de cada pétalo que es la columna 3 de la matriz ''data''
 +  * ''flower_type'': Con el tipo de flor (0 o 1)
 +
 +Luego hemos creado una matriz juntando la longitud de cada pétalo y la anchura de cada pétalo, es lo que llamaremos ''x'' y luego hemos creado la ''y'' que es el tipo de flor.
 +
 +Es decir que vamos a entrenar a red neuronal con los valores de ''x'' e ''y'' para que cree la función matemática capaz de calcular el tipo de flor en función de las longitudes.
 +
 +
 +<sxh python>
 +np.random.seed(5)
 +tf.random.set_seed(5)
 +random.seed(5)  
 +</sxh>
 +
 +Para a siempre nos salgan los mismos resultados, hemos inicializado los generadores de números aleatorios.
 +
 +
 +<sxh python>
 +model=Sequential()
 +model.add(Dense(6, activation='relu',input_dim=2))
 +model.add(Dense(12, activation='relu'))
 +model.add(Dense(6, activation='relu'))
 +model.add(Dense(1, activation='sigmoid'))
 +model.compile(loss='binary_crossentropy')
 +</sxh>
 +
 +Hemos creado el la estructura de la red neuronal. Excepto la capa de entrada, cada capa se especifica por un objeto de tipo [[https://www.tensorflow.org/api_docs/python/tf/keras/layers/Dense|Dense]] y el primer número especifica el Nº de neuronas de esa capa. 
 +
 +En la primera capa también hemos indicado la propiedad ''input_dim'' con el valor ''2'' que indica el Nº de valores de entrada , es decir que estamos diciendo el tamaño de la capa de entrada.
 +
 +<note tip>Comprueba que los tamaños de cada capa coinciden con los del esquema de la red y no te preocupes ahora por el Nº de capas o del Nº de neuronas por capa o de que es la activación (función de activación) o la propiedad ''loss''.</note>
 +
 +Para acabar compilamos el modelo con el método [[https://www.tensorflow.org/api_docs/python/tf/keras/Model#compile|compile]].
 +
 +<sxh python>
 +model.fit(x, y,epochs=100) 
 +</sxh>
 +
 +Ahora vemos a entrenar con el método [[https://www.tensorflow.org/api_docs/python/tf/keras/Model#fit|fit]] la red neuronal para que ella internamente genere la función matemática. Fíjate como le pasamos la matriz con los datos de entrada ''x'' y el vector con el resultado que debe dar ''y''.
 +
 +Por último le decimos cuantas veces tiene que entrenar la red con el parámetro ''epochs''. Cuanto más lo entrenemos , en general mejor será la red (Esta frase tiene muchos matices pero ya lo iremos viendo a lo largo del curso).
 +
 +
 +<sxh base>
 +Epoch 1/100
 +4/4 ━━━━━━━━━━━━━━━━━━━━ 1s 105ms/step - loss: 0.6408
 +Epoch 2/100
 +4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 961us/step - loss: 0.6225
 +Epoch 3/100
 +4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - loss: 0.6031
 +Epoch 4/100
 +4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - loss: 0.5911
 +Epoch 5/100
 +4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - loss: 0.5854 
 +Epoch 6/100
 +4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - loss: 0.5805  
 +Epoch 7/100
 +4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - loss: 0.5755  
 +Epoch 8/100
 +4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - loss: 0.5705 
 +Epoch 9/100
 +4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - loss: 0.5657 
 +Epoch 10/100
 +4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - loss: 0.5609  
 +........
 +4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - loss: 0.1176 
 +Epoch 90/100
 +4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - loss: 0.1136 
 +Epoch 91/100
 +4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - loss: 0.1097  
 +Epoch 92/100
 +4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 958us/step - loss: 0.1059
 +Epoch 93/100
 +4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - loss: 0.1021  
 +Epoch 94/100
 +4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - loss: 0.0984 
 +Epoch 95/100
 +4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - loss: 0.0948 
 +Epoch 96/100
 +4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 979us/step - loss: 0.0913
 +Epoch 97/100
 +4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 910us/step - loss: 0.0879
 +Epoch 98/100
 +4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 2ms/step - loss: 0.0845 
 +Epoch 99/100
 +4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - loss: 0.0812  
 +Epoch 100/100
 +4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - loss: 0.0780  
 +</sxh>
 +
 +Ahora vemos el resultado del entrenamiento para cada una de las épocas, fíjate en //loss// , es lo que nos dice como de buena es nuestra red. Cuanto más pequeño sea ese valor, mejor es la red.
 +
 +Una vez acabar vamos a usar nuestra función matemática con el método [[https://www.tensorflow.org/api_docs/python/tf/keras/Model#predict|predict]] con los siguientes valores:
 +
 +
 +<sxh python>
 +print(model.predict(np.array([[1.4,0.2]])))
 +print(model.predict(np.array([[4.4,1.3]])))
 +</sxh>
 +
 +<sxh base>
 +[[0.09985255]]
 +[[0.99229264]]
 +</sxh>
 +
 +
 +|  **X**  ||  **Y Predicha**  ||  **Y Real**  |
 +|  **Largo Pétalo**  |  **Ancho Pétalo**  |  **Score Flor Predicha **(''y_score'' |  **Valor Flor Predicha**(''y_pred'' |  **Valor Flor Real**(''y_true''
 +|  1.4    0.2    0.09985255  |  0  |  0  |
 +|  4.4    1.3    0.99229264  |  1  |  1  |
 +
 +
 +
 +Vemos como los resultados no son exactamente **0** o **1** sino número cercanos como el ''0.09985255'' o el ''0.99229264'' pero no nos preocupemos, las redes neuronales no suelen dar resultados exactos.
 +
 +Entonces fijarse que hay que distinguir entre:
 +  * ''y_score'': El número que ha generado la red neuronal. Ej: ''0.99229264''
 +  * ''y_pred'': Lo que predecimos en función de la red neuronal. Si es mayor que 0.5 predecimos ''1'' y sino predecimos ''0''
 +  * ''y_true'': El valor real que debería haber predicho.
 +
 +<note tip>
 +Para crear redes neuronales de Python existen 3 librerías
 +
 +  * [[https://www.tensorflow.org/|TensorFlow]]: Es una librería de Google. El problema es que es de muy bajo nivel. Fue de las primeras.
 +
 +{{:clase:iabd:pia:1eval:logo_tensorflow.png?200|}}
 +
 +  * [[https://keras.io/|Keras]]: Es un API que está por encima de TensorFlow haciendo que sea muy sencillo crear redes neuronales.
 +
 +{{:clase:iabd:pia:1eval:logo_keras.png?200|}}
 +
 +  * [[https://pytorch.org/|Pytorch]]: Es la alternativa a Keras, está hecha por Facebook. Se usa mucho en proyectos de investigación.
 +
 +{{:clase:iabd:pia:1eval:logo_pytorch.png?200|}}
 +
 +
 +**Durante el curso vamos a usar Keras y algo de TensorFlow**
 +
 +</note>
 +
 +
 +===== Gráficas =====
 +La mayoría de veces para una mayor comprensión de los datos queremos también ver gráficos de éstos. 
 +
 +El siguiente código Python muestra la siguiente gráfica con cada una de las flores de los datos.
 +
 +<sxh python>
 +import matplotlib.pyplot as plt
 +from matplotlib.colors import ListedColormap
 +figure=plt.figure(figsize = (5, 4))
 +axes = figure.add_subplot()
 +
 +colors = ["#0E5581", "#8F0C00", "#0C8F00"
 +cmap = ListedColormap(colors[:len(np.unique(y))]) 
 +
 +
 +scatter=axes.scatter(x=x[:,0], y=x[:,1], c=y, cmap=cmap,s=6)
 +axes.set_xlabel('Largo Pétalo')  
 +axes.set_ylabel('Ancho Pétalo')
 +
 +for i, name in enumerate(["Setosa","Versicolor"]):
 +    color = scatter.cmap(scatter.norm(i))  
 +    axes.scatter([], [], color=[color], label=name+":"+str(i))  
 +axes.set_xlim(xmin=0,xmax=8)
 +axes.set_ylim(ymin=0,ymax=3)
 +axes.legend(title="Flores")
 +</sxh>
 +
 +{{:clase:iabd:pia:1eval:datos_iris.png|}}
 +
 +
 +Ahora vamos a hacer una gráfica con el resultado de la red neuronal
 +
 +<sxh python>
 +import matplotlib.pyplot as plt
 +from matplotlib.colors import ListedColormap
 +figure=plt.figure(figsize = (5, 4))
 +axes = figure.add_subplot()
 +
 +colors = ["#0E5581", "#8F0C00", "#0C8F00"
 +cmap = ListedColormap(colors[:len(np.unique(y))]) 
 +
 +
 +colors = ["#83B5F1", "#FF8175", "#75FF81"
 +cmap_fondo = ListedColormap(colors[:len(np.unique(y))]) 
 +
 +
 +xt=np.linspace(0,8,300)
 +yt=np.linspace(0,3,300)
 +xt,yt=np.meshgrid(xt,yt)
 +
 +xa=xt.reshape(-1)
 +ya=yt.reshape(-1)
 +
 +xya=np.column_stack((xa,ya))
 +
 +za=model.predict([xya])
 +
 +zt=np.reshape(za,xt.shape)
 +
 +
 +scatter=axes.scatter(x=xa, y=ya, c=za, cmap=cmap_fondo,s=6)
 +axes.set_xlabel('Largo Pétalo')  
 +axes.set_ylabel('Ancho Pétalo')
 +
 +for i, name in enumerate(["Setosa","Versicolor"]):
 +    color = scatter.cmap(scatter.norm(i)) 
 +    axes.scatter([], [], color=[color], label=name+":"+str(i)) 
 +scatter=axes.scatter(x=x[:,0], y=x[:,1], c=y, cmap=cmap,s=6)
 +axes.set_xlim(xmin=0,xmax=8)
 +axes.set_ylim(ymin=0,ymax=3)
 +axes.legend(title="Flores")
 +</sxh>
 +
 +
 +{{:clase:iabd:pia:1eval:resultado_red_neuronal_iris.png|}}
 +
 +Lo que hay que hacer es comparar los datos de las 2 gráficas para ver si son coherentes entre ellas. Y obviamente lo son
 +
 +===== Las dificultades de la IA =====
 +Al entrenar una IA lo dificil es cuando se encuentra con cosas que no habías previsto.
 +
 +{{:clase:iabd:pia:1eval:muffin_chiguagua.jpeg|}}
 +
 +Si creamos una IA, para saber si una foto es de un chihuahua pero le pasamos una foto de un muffin, lo más normal es que lo confunda con un chihuahua.🤷🏻
 +
 +
 +
 +===== Ejercicios =====
 +
 +==== Ejercicio 1.A ====
 +Usando Google collab haz una red neuronal en python con Keras que obtenga el tipo de flor en función del "Largo Pétalo" y de "Ancho Pétalo".
 +
 +
 +Obtén el resultado de la red neuronal para las siguientes entradas e indica el tipo de flor que ha calcula la red neuronal.
 +
 +|  **X**  ||  **Y Predicha**  ||  **Y Real**  |
 +|  **Largo Pétalo**  |  **Ancho Pétalo**  |  **Score Flor Predicha **(''y_score'' |  **Valor Flor Predicha**(''y_pred'' |  **Valor Flor Real**(''y_true''
 +|  1.3    0.3      |    |    |
 +|  3.9    1.2      |    |    |
 +
 +==== Ejercicio 1.B ====
 +Muestra la siguiente figura para ver como se comporta la red neuronal
 +
 +{{:clase:iabd:pia:1eval:ejer_01_01b.png|}}
 +
 +
 +==== Ejercicio 2.A ====
 +Modifica ahora la red neuronal de forma que:
 +
 +    * La 1º  capa oculta tenga 4 neuronas en vez de 6
 +    * La 2º capa oculta tenga 5 neuronas en vez de 12
 +    * La 3º capa oculta tenga 3 neuronas en vez de 6
 +    * La 4º capa seguirá teniendo 1 neurona
 +    * Sean solo 30 épocas.
 +    * La semilla sea 5.
 +
 +Usando la web [[http://alexlenail.me/NN-SVG/index.html]] dibuja la red neuronal que acabas de crear
 +
 +
 +Ahora muestra los resultados
 +
 +|  **X**  ||  **Y Predicha**  ||  **Y Real**  |
 +|  **Largo Pétalo**  |  **Ancho Pétalo**  |  **Score Flor Predicha **(''y_score'' |  **Valor Flor Predicha**(''y_pred'' |  **Valor Flor Real**(''y_true''
 +|  1.3    0.3      |    |    |
 +|  3.9    1.2      |    |    |
 +
 +==== Ejercicio 2.B ====
 +Muestra la siguiente figura para ver como se comporta la red neuronal
 +
 +{{:clase:iabd:pia:1eval:ejer_01_02b.png|}}
 +
 +
 +==== Ejercicio 3 ====
 +Usando el código de la red original, modifica las siguientes líneas:
 +<sxh python>
 +longitudes_petalos=iris.data[0:99,2]
 +anchos_petalos=iris.data[0:99,3]
 +flower_type=iris.target[0:99]
 +</sxh>
 +
 +de forma que queden así:
 +
 +<sxh python>
 +longitudes_petalos=iris.data[:,2]
 +anchos_petalos=iris.data[:,3]
 +flower_type=iris.target[:]
 +</sxh>
 +
 +Entrena la red con los nuevos datos
 +
 +Muestra la siguiente gráfica con los datos de entrada:
 +
 +{{:clase:iabd:pia:1eval:ejer_01_03.png|}}
 +
 +
 +Ahora verás que está el otro tipo de flor llamado //Virginica//.
 +
 +Prueba a ver si funciona ahora la red neuronal con el nuevo tipo de flor.
 +
 +|  **X**  ||  **Y Predicha**  ||  **Y Real**  |
 +|  **Largo Pétalo**  |  **Ancho Pétalo**  |  **Score Flor Predicha **(''y_score'' |  **Valor Flor Predicha**(''y_pred'' |  **Valor Flor Real**(''y_true''
 +|  5.1    1.5      |    |  2  |
 +|  5.8    2.2      |    |  2  |
 +
 +
 +==== Ejercicio 4 ====
 +Piensa al menos 3 problemas que se podrían resolver con una red neuronal similar a la que has usado.
 +
 +==== Ejercicio 5 ====
 +Vamos a ver ahora otro conjunto de datos relativo a la detección de cáncer de mama.
 +
 +Los datos se obtienen de la siguiente forma:
 +
 +<sxh python>
 +from sklearn.datasets import load_breast_cancer
 +
 +breast_cancer=load_breast_cancer()
 +
 +x=breast_cancer.data
 +y=breast_cancer.target
 +</sxh>
 +
 +Este conjunto de datos tiene 30 variable de entrada, que son las siguientes:
 +  * mean radius
 +  * mean texture
 +  * mean perimeter
 +  * mean area
 +  * mean smoothness
 +  * mean compactness
 +  * mean concavity
 +  * mean concave points
 +  * mean symmetry
 +  * mean fractal dimension
 +  * radius error
 +  * texture error
 +  * perimeter error
 +  * area error
 +  * smoothness error
 +  * compactness error
 +  * concavity error
 +  * concave points error
 +  * symmetry error
 +  * fractal dimension error
 +  * worst radius
 +  * worst texture
 +  * worst perimeter
 +  * worst area
 +  * worst smoothness
 +  * worst compactness
 +  * worst concavity
 +  * worst concave points
 +  * worst symmetry
 +  * worst fractal dimension
 +
 +Esto datos son relativos a imágenes de núcleos celulares como los siguientes:
 +
 +{{ :clase:iabd:pia:1eval:nucleos_celulares_cancer.png?direct&400 |}}
 +
 +Y los histogramas de todos los datos son los siguientes:
 +
 +{{ :clase:iabd:pia:1eval:breast_cancer_kde.png?direct |}}
 +
 +Podemos ven en los histogramas que no hay una forma fácil de saber si una célula es o no cancerígena.
 +
 +<note important>
 +En vez de incluir todos los datos en la red neuronal , habría que hacer un Análisis exploratorio de datos (EDA) y por ejemplo eliminar las columnas que están relacionadas.
 +</note>
 +
 +Imprime el valor de la fila 56 tanto de la ''x'' como de la ''y''.
 +
 +<sxh>
 +#Para que los datos no se muestren con notación científica
 +np.set_printoptions(suppress=True) 
 +
 +print(x[56],y[56])
 +</sxh>
 +
 +Ahora muestra los valores de la ''x'' y la ''y'' para la fila 204.
 +
 +
 +Crea una red neuronal en las que en cada capa tenga los siguientes números de neuronas:
 +
 +|  **Nº Capa**  |  **Nº Neuronas**  |
 +|   1º  |  30   |
 +|   2º  |  60   |
 +|   3º  |  100   |
 +|   4º  |  60   |
 +|   5º  |  30   |
 +|   6º  |  10   |
 +|   7º  |  1   |
 +
 +
 +Rellena la siguiente tabla y muestrala
 +
 +
 +|  **X**  |  **Y Predicha**  ||  **Y Real**  |
 +|  **Fila Datos**  |  ''y_score''  |  ''y_pred''  |  ''y_true'' 
 +|  56      |    |    |
 +|  204      |    |    |
 +
 +¿Es una buena red?
 +
 +
 +Usa hora una red más pequeña de forma que tenga las siguientes capas:
 +
 +|  **Nº Capa**  |  **Nº Neuronas**  |
 +|   1º  |  6   |
 +|   2º  |  12   |
 +|   3º  |  6   |
 +|   4º  |  1   |
 +
 +
 +Rellena la siguiente tabla y muestrala
 +
 +|  **X**  |  **Y Predicha**  ||  **Y Real**  |
 +|  **Fila Datos**  |  ''y_score''  |  ''y_pred''  |  ''y_true'' 
 +|  56      |    |    |
 +|  204      |    |    |
 +
 +¿Es una buena red?
 +
 +==== Ejercicio 6 ====
 +Repite la red pequeña del ejercicio  anterior pero ahora modificando la semilla de los números aleatorios
 +<sxh>
 +np.random.seed(5)
 +tf.random.set_seed(5)
 +random.seed(5)
 +</sxh>
 +
 +Rellena la siguiente tabla y muestrala con una **red con la semilla 6**
 +
 +|  **X**  |  **Y Predicha**  ||  **Y Real**  |
 +|  **Fila Datos**  |  ''y_score''  |  ''y_pred''  |  ''y_true''  |  
 +|  56      |    |    |
 +|  204      |    |    |
 +
 +Rellena la siguiente tabla y muestrala con una **red con la semilla 88**
 +
 +|  **X**  |  **Y Predicha**  ||  **Y Real**  |
 +|  **Fila Datos**  |  ''y_score''  |  ''y_pred''  |  ''y_true''  |  
 +|  56      |    |    |
 +|  204      |    |    |
 +
 +
 +==== Ejercicio 7.A ====
 +<note tip>El ejercicio es totalmente ficticio</note>
 +Una estrella que explota como supernova. Al explotar expulsa elementos metálicos y no metálicos.
 +
 +Al pasar 15 años se mide la distancia a la que están los elementos y mediante un arduo trabajo científico, se averigua para cada elemento si es un metal o un no metal.
 +
 +{{:clase:iabd:pia:1eval:ejercicio7_a.png|}}
 +
 +Hace una red neuronal que según la posición en la que se encuentra el elemento lo califique como metal o no metal.
 +
 +Los datos son los siguientes:
 +<sxh python>
 +x =np.array([
 +    [12.9, 11.4], [13.7, 8.3],  [15.6, 10.6], [11.0, 11.6], [12.7, 13.8],    [13.2, 11.8], [12.3, 11.7], [11.5, 14.7], [11.7, 11.2], [10.7, 9.3], 
 +    [12.6, 11.8], [10.1, 9.7],  [16.9, 9.8],  [13.4, 9.0],  [14.2, 17.0],    [17.2, 12.0], [12.2, 13.9], [14.4, 15.5], [12.2, 11.8], [10.6, 14.2], 
 +    [15.5, 15.4], [7.7, 9.8],   [9.6, 13.2],  [10.8, 12.2], [11.9, 13.0],    [10.7, 13.6], [9.0, 14.3],  [9.4, 15.0],  [14.7, 11.9], [14.7, 9.2],
 +    [14.8, 10.6], [16.2, 13.3], [14.3, 14.7], [12.6, 11.3], [16.2, 15.0],    [15.9, 11.9], [13.8, 15.0], [10.1, 7.8],  [11.9, 17.4], [8.8, 14.4],
 +    [15.6, 13.9], [14.6, 15.0], [11.6, 12.4], [15.7, 9.9],  [10.5, 12.2],    [12.1, 12.6], [12.5, 13.2], [9.8, 10.1],  [8.0, 13.6],  [14.0, 14.2],
 +    [13.1, 11.3], [15.0, 14.2], [13.0, 7.8],  [14.6, 12.1], [10.5, 13.9],    [9.0, 7.9],   [12.7, 8.9],  [13.5, 10.9], [12.8, 14.3], [10.1, 16.3], 
 +    [13.7, 16.8], [7.5, 11.5],  [12.0, 11.5], [14.7, 12.0], [12.1, 11.7],    [9.7, 9.6],   [10.2, 13.5], [14.1, 13.1], [10.4, 10.6], [12.5, 15.5], 
 +    [17.5, 11.0], [11.8, 7.8],  [11.6, 17.5], [8.9, 8.0],   [13.8, 12.4],    [10.1, 10.2], [14.2, 10.0], [13.6, 9.7],  [8.1, 15.0],  [8.3, 15.5], 
 +    [9.2, 9.5],   [16.5, 12.9], [11.4, 12.8], [12.0, 13.1], [12.9, 12.0],    [11.6, 11.9], [12.0, 11.2], [13.6, 16.6], [10.3, 14.2], [12.5, 13.0], 
 +    [8.9, 8.6],   [12.7, 6.7],  [10.3, 14.1], [11.6, 11.7], [12.3, 15.0],    [12.6, 12.3], [15.0, 10.5], [15.9, 10.8], [11.2, 8.1],  [10.4, 13.8],
 +    [8.6, 15.4],  [7.6, 5.0],   [6.2, 12.5],  [5.5, 7.2],   [16.2, 7.3],     [17.1, 10.3], [8.8, 7.7],   [4.9, 16.7],  [12.8, 5.8],  [10.0, 4.3],
 +    [4.8, 13.8],  [17.9, 11.9], [3.7, 12.8],  [16.2, 20.2], [16.6, 8.5],     [17.2, 8.9],  [7.9, 9.4],   [11.7, 17.1], [12.7, 19.0], [13.0, 6.3], 
 +    [11.3, 17.6], [18.5, 8.2],  [20.0, 13.5], [13.1, 17.6], [10.6, 18.4],    [8.1, 15.4],  [16.7, 16.7], [9.6, 7.6],   [8.4, 17.4],  [12.5, 18.3], 
 +    [17.1, 17.4], [4.0, 13.3],  [17.4, 9.6],  [6.3, 14.8],  [7.2, 9.9],      [17.1, 12.1], [13.4, 19.7], [5.9, 12.0],  [13.3, 17.1], [14.8, 20.1], 
 +    [9.5, 3.5],   [12.1, 6.6],  [16.2, 4.1],  [15.6, 20.8], [4.5, 17.9],     [9.3, 16.8],  [5.5, 14.7],  [21.4, 10.8], [7.8, 13.8],  [17.6, 9.6], 
 +    [15.7, 18.7], [5.9, 5.3],   [5.0, 7.9],   [21.4, 14.7], [3.1, 12.2],     [14.3, 6.3],  [16.2, 16.3], [11.3, 20.3], [7.5, 12.7],  [17.9, 11.2], 
 +    [8.5, 5.1],   [7.5, 4.5],   [15.2, 19.2], [14.3, 6.6],  [18.9, 5.4],     [7.9, 15.7],  [11.0, 3.9],  [17.5, 13.8], [13.9, 8.0],  [4.0, 14.3], 
 +    [14.7, 17.5], [20.2, 14.5], [9.3, 17.9],  [8.8, 9.3],   [17.0, 7.0],     [14.8, 8.5],  [5.6, 17.5],  [8.3, 5.4],   [14.6, 8.2],  [12.0, 5.9], 
 +    [4.5, 9.9],   [15.2, 7.1],  [16.5, 7.3],  [12.7, 19.0], [12.5, 17.3],    [8.1, 10.4],  [4.1, 10.1],  [11.7, 16.6], [10.3, 17.9], [19.2, 9.7], 
 +    [6.0, 7.1],   [17.6, 15.2], [17.0, 10.9], [16.4, 19.0], [7.9, 17.9],     [7.5, 9.3],   [4.8, 14.4],  [7.4, 14.5],  [9.2, 3.6],   [15.9, 19.0]
 +])
 +
 +y = np.array([
 +    1, 1, 1, 1, 1,     1, 1, 1, 1, 1, 
 +    1, 1, 1, 1, 1,     1, 1, 1, 1, 1, 
 +    1, 1, 1, 1, 1,     1, 1, 1, 1, 1, 
 +    1, 1, 1, 1, 1,     1, 1, 1, 1, 1, 
 +    1, 1, 1, 1, 1,     1, 1, 1, 1, 1, 
 +    1, 1, 1, 1, 1,     1, 1, 1, 1, 1, 
 +    1, 1, 1, 1, 1,     1, 1, 1, 1, 1, 
 +    1, 1, 1, 1, 1,     1, 1, 1, 1, 1, 
 +    1, 1, 1, 1, 1,     1, 1, 1, 1, 1, 
 +    1, 1, 1, 1, 1,     1, 1, 1, 1, 1,    
 +    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, 0, 0, 0, 0
 +
 +])
 +</sxh>
 +
 +
 +
 +Tenemos la siguiente función ''compile_model(neuronas_capa_1,neuronas_capa_2,neuronas_capa_3,neuronas_capa_4)'' que acepta como argumentos el número de neuronas de cada capa.
 +
 +
 +<sxh python>
 +def compile_model(neuronas_capa_1,neuronas_capa_2,neuronas_capa_3,neuronas_capa_4):
 +    random.seed(5) 
 +    np.random.seed(5)
 +    tf.random.set_seed(5)
 +    model=Sequential()
 +    model.add(Dense(neuronas_capa_1, activation='relu',input_dim=2))
 +    model.add(Dense(neuronas_capa_2, activation='relu'))
 +    model.add(Dense(neuronas_capa_3, activation='relu'))
 +    model.add(Dense(neuronas_capa_4, activation='sigmoid'))
 +    model.compile(loss='binary_crossentropy')
 +
 +    return model
 +
 +</sxh>
 +
 +
 +Por último tenemos la función ''plot_result(model,x,y,figure,title,filas,columns,index)'' que tiene como argumentos:
 +  * ''model'': Modelo a mostrar
 +  * ''x'': Datos a mostrar
 +  * ''y'': Resultados a mostrar
 +  * ''figure'': La figura sobre la que se dibuja la gráfica
 +  * ''title'': Título de la gráfica
 +  * ''filas'': Filas de la figura
 +  * ''columnas'': Columnas de la figura
 +  * ''index'': Posición de la gráfica dentro de la figura. El indice empieza en 1 y va de izquierda a derecha y luego de arriba a abajo.
 +
 +<sxh python>
 +def plot_result(model,x,y,figure,title,filas,columns,index):
 +    axes = figure.add_subplot(filas,columns,index)
 +    axes.set_title(title, fontsize=14,pad=30,color="#003B80")
 +    
 +    colors = ["#0E5581", "#8F0C00"
 +    cmap = ListedColormap(colors[:len(np.unique(y))]) 
 +
 +
 +    colors = ["#83B5F1", "#FF8175"
 +    cmap_fondo = ListedColormap(colors[:len(np.unique(y))]) 
 +
 +    xt=np.linspace(0,22,400)
 +    yt=np.linspace(0,22,400)
 +    xt,yt=np.meshgrid(xt,yt)
 +
 +    xa=xt.reshape(-1)
 +    ya=yt.reshape(-1)
 +
 +    xya=np.column_stack((xa,ya))
 +
 +    pred = model.predict(xya, verbose=False)
 +    za = (pred > 0.5).astype(int).ravel()
 +
 +    zt=np.reshape(za,xt.shape)
 +
 +
 +    scatter=axes.scatter(x=xa, y=ya, c=za, cmap=cmap_fondo,s=6)
 +    axes.set_xlabel('Posición del elemento en el eje X')  
 +    axes.set_ylabel('Posición del elemento en el eje Y')
 +
 +    for i, name in enumerate(['No metal',"Metal"]):
 +        color = scatter.cmap(scatter.norm(i)) 
 +        axes.scatter([], [], color=[color], label=name+":"+str(i))  
 +    scatter=axes.scatter(x=x[:,0], y=x[:,1], c=y, cmap=cmap,s=6)
 +    axes.set_xlim(xmin=0,xmax=22)
 +    axes.set_ylim(ymin=0,ymax=22)
 +    axes.legend(title="Elemento")
 +</sxh>
 +
 +Para crear una figura se usa el código:
 +
 +<sxh python>
 +figure=plt.figure(figsize = (13.5, 8))
 +</sxh> 
 +
 +Siendo ''13.8'' y ''8'' el ancho y alto de la figura.
 +
 +Por último siempre hay que poner al final:
 +
 +<sxh python>
 +figure.tight_layout()
 +</sxh>
 +
 +
 +Veamos un ejemplo de como se usa:
 +
 +<sxh python>
 +figure=plt.figure(figsize = (10, 8))
 +
 +
 +
 +model=compile_model(6,12,6,1)
 +
 +model.fit(x, y,epochs=50,verbose=False) 
 +plot_result(model,x,y,figure,"6,12,6,1 epochs=50",2,2,1)
 +
 +model.fit(x, y,epochs=50,verbose=False) 
 +plot_result(model,x,y,figure,"6,12,6,1 epochs=100",2,2,2)
 +
 +
 +
 +
 +model=compile_model(20,30,20,1)
 +
 +model.fit(x, y,epochs=100,verbose=False) 
 +plot_result(model,x,y,figure,"20,30,20,1 epochs=100",2,2,3)
 +
 +model.fit(x, y,epochs=100,verbose=False) 
 +plot_result(model,x,y,figure,"20,30,20,1 epochs=200",2,2,4)
 +
 +
 +
 +
 +
 +figure.tight_layout()
 +</sxh>
 +
 +{{:clase:iabd:pia:1eval:intro_ia_supernova.png|}}
 +
 +Veamos como quedaría como una animación de 3000 épocas.
 +
 +{{ :clase:iabd:pia:1eval:animacion_superficie.mp4 |}}
 +
 +
 +Ahora muestra 6 gráficas con lo siguiente
 +  * Red: 20,40,20,1
 +    * épocas: 400
 +    * épocas: 800
 +    * épocas: 1200
 +  * Red: 100,200,100,1
 +    * épocas: 100
 +    * épocas: 200
 +    * épocas: 300
 +==== Ejercicio 7.B ====
 +Rellena ahora la siguiente tabla con el último modelo que has creado
 +
 +|  **X**  |  **Y Predicha**  ||  **Y Real**  |
 +|  **Posición del elemento**  |  ''y_score''  |  ''y_pred''  |  ''y_true''  |  
 +|  13.1, 17.6      |    |    |
 +|  3.7, 12.8      |    |    |
 +
 +==== Ejercicio 7.C ====
 +Vuelve a entrenar la primera red con los 1200 épocas.
 +Y muestra los resultados
 +Pero ahora cambia los datos por lo datos de otra supernova y muestra solo los datos.
 +
 +<sxh python>
 +
 +x_entrenamiento =np.array([
 +    [12.9, 11.4], [13.7, 8.3],  [15.6, 10.6], [11.0, 11.6], [12.7, 13.8],    [13.2, 11.8], [12.3, 11.7], [11.5, 14.7], [11.7, 11.2], [10.7, 9.3], 
 +    [12.6, 11.8], [10.1, 9.7],  [16.9, 9.8],  [13.4, 9.0],  [14.2, 17.0],    [17.2, 12.0], [12.2, 13.9], [14.4, 15.5], [12.2, 11.8], [10.6, 14.2], 
 +    [15.5, 15.4], [7.7, 9.8],   [9.6, 13.2],  [10.8, 12.2], [11.9, 13.0],    [10.7, 13.6], [9.0, 14.3],  [9.4, 15.0],  [14.7, 11.9], [14.7, 9.2],
 +    [14.8, 10.6], [16.2, 13.3], [14.3, 14.7], [12.6, 11.3], [16.2, 15.0],    [15.9, 11.9], [13.8, 15.0], [10.1, 7.8],  [11.9, 17.4], [8.8, 14.4],
 +    [15.6, 13.9], [14.6, 15.0], [11.6, 12.4], [15.7, 9.9],  [10.5, 12.2],    [12.1, 12.6], [12.5, 13.2], [9.8, 10.1],  [8.0, 13.6],  [14.0, 14.2],
 +    [13.1, 11.3], [15.0, 14.2], [13.0, 7.8],  [14.6, 12.1], [10.5, 13.9],    [9.0, 7.9],   [12.7, 8.9],  [13.5, 10.9], [12.8, 14.3], [10.1, 16.3], 
 +    [13.7, 16.8], [7.5, 11.5],  [12.0, 11.5], [14.7, 12.0], [12.1, 11.7],    [9.7, 9.6],   [10.2, 13.5], [14.1, 13.1], [10.4, 10.6], [12.5, 15.5], 
 +    [17.5, 11.0], [11.8, 7.8],  [11.6, 17.5], [8.9, 8.0],   [13.8, 12.4],    [10.1, 10.2], [14.2, 10.0], [13.6, 9.7],  [8.1, 15.0],  [8.3, 15.5], 
 +    [9.2, 9.5],   [16.5, 12.9], [11.4, 12.8], [12.0, 13.1], [12.9, 12.0],    [11.6, 11.9], [12.0, 11.2], [13.6, 16.6], [10.3, 14.2], [12.5, 13.0], 
 +    [8.9, 8.6],   [12.7, 6.7],  [10.3, 14.1], [11.6, 11.7], [12.3, 15.0],    [12.6, 12.3], [15.0, 10.5], [15.9, 10.8], [11.2, 8.1],  [10.4, 13.8],
 +    [8.6, 15.4],  [7.6, 5.0],   [6.2, 12.5],  [5.5, 7.2],   [16.2, 7.3],     [17.1, 10.3], [8.8, 7.7],   [4.9, 16.7],  [12.8, 5.8],  [10.0, 4.3],
 +    [4.8, 13.8],  [17.9, 11.9], [3.7, 12.8],  [16.2, 20.2], [16.6, 8.5],     [17.2, 8.9],  [7.9, 9.4],   [11.7, 17.1], [12.7, 19.0], [13.0, 6.3], 
 +    [11.3, 17.6], [18.5, 8.2],  [20.0, 13.5], [13.1, 17.6], [10.6, 18.4],    [8.1, 15.4],  [16.7, 16.7], [9.6, 7.6],   [8.4, 17.4],  [12.5, 18.3], 
 +    [17.1, 17.4], [4.0, 13.3],  [17.4, 9.6],  [6.3, 14.8],  [7.2, 9.9],      [17.1, 12.1], [13.4, 19.7], [5.9, 12.0],  [13.3, 17.1], [14.8, 20.1], 
 +    [9.5, 3.5],   [12.1, 6.6],  [16.2, 4.1],  [15.6, 20.8], [4.5, 17.9],     [9.3, 16.8],  [5.5, 14.7],  [21.4, 10.8], [7.8, 13.8],  [17.6, 9.6], 
 +    [15.7, 18.7], [5.9, 5.3],   [5.0, 7.9],   [21.4, 14.7], [3.1, 12.2],     [14.3, 6.3],  [16.2, 16.3], [11.3, 20.3], [7.5, 12.7],  [17.9, 11.2], 
 +    [8.5, 5.1],   [7.5, 4.5],   [15.2, 19.2], [14.3, 6.6],  [18.9, 5.4],     [7.9, 15.7],  [11.0, 3.9],  [17.5, 13.8], [13.9, 8.0],  [4.0, 14.3], 
 +    [14.7, 17.5], [20.2, 14.5], [9.3, 17.9],  [8.8, 9.3],   [17.0, 7.0],     [14.8, 8.5],  [5.6, 17.5],  [8.3, 5.4],   [14.6, 8.2],  [12.0, 5.9], 
 +    [4.5, 9.9],   [15.2, 7.1],  [16.5, 7.3],  [12.7, 19.0], [12.5, 17.3],    [8.1, 10.4],  [4.1, 10.1],  [11.7, 16.6], [10.3, 17.9], [19.2, 9.7], 
 +    [6.0, 7.1],   [17.6, 15.2], [17.0, 10.9], [16.4, 19.0], [7.9, 17.9],     [7.5, 9.3],   [4.8, 14.4],  [7.4, 14.5],  [9.2, 3.6],   [15.9, 19.0]
 +])
 +
 +y_entrenamiento = np.array([
 +    1, 1, 1, 1, 1,     1, 1, 1, 1, 1, 
 +    1, 1, 1, 1, 1,     1, 1, 1, 1, 1, 
 +    1, 1, 1, 1, 1,     1, 1, 1, 1, 1, 
 +    1, 1, 1, 1, 1,     1, 1, 1, 1, 1, 
 +    1, 1, 1, 1, 1,     1, 1, 1, 1, 1, 
 +    1, 1, 1, 1, 1,     1, 1, 1, 1, 1, 
 +    1, 1, 1, 1, 1,     1, 1, 1, 1, 1, 
 +    1, 1, 1, 1, 1,     1, 1, 1, 1, 1, 
 +    1, 1, 1, 1, 1,     1, 1, 1, 1, 1, 
 +    1, 1, 1, 1, 1,     1, 1, 1, 1, 1,    
 +    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, 0, 0, 0, 0
 +
 +])
 +
 +x_validacion = np.array([
 +        [11.4, 13.4], [11.7, 10.2], [11.4, 12.6], [12.1, 10.4], [8.9, 11.2],         [9.2, 9.5],   [11.3, 7.7],  [6.9, 10.5],  [10.0, 14.3], [11.6, 12.5], 
 +        [15.0, 13.2], [10.7, 7.1],  [8.2, 12.1],  [12.9, 14.0], [13.2, 8.9],         [10.7, 12.7], [7.9, 12.8],  [9.6, 15.7],  [8.2, 8.0],   [9.5, 10.2], 
 +        [9.8, 10.1],  [10.5, 15.7], [10.0, 15.5], [10.9, 15.0], [9.1, 14.6],         [12.0, 12.2], [13.1, 14.7], [12.7, 10.6], [12.6, 10.6], [12.0, 13.4], 
 +        [12.0, 11.2], [12.2, 15.2], [10.5, 9.4],  [11.7, 7.1],  [14.3, 11.5],        [7.4, 9.1],   [14.4, 11.0], [6.2, 10.5],  [9.4, 9.1],   [14.0, 10.7], 
 +        [10.9, 13.3], [12.3, 7.2],  [12.5, 9.4],  [14.7, 9.0],  [12.3, 11.0],        [9.1, 11.4],  [13.7, 10.7], [9.8, 11.9],  [11.7, 9.3],  [6.8, 9.7], 
 +        [11.3, 8.5],  [9.1, 11.2],  [15.3, 11.8], [13.8, 12.7], [13.7, 13.3],        [11.0, 15.6], [14.8, 10.2], [9.6, 9.5],   [11.4, 10.1], [8.1, 9.7], 
 +        [8.5, 8.1],   [12.6, 7.1],  [12.6, 10.2], [14.0, 9.2],  [13.2, 6.8],         [12.7, 12.1], [9.6, 12.7],  [13.6, 11.6], [7.9, 10.1],  [12.4, 6.2],
 +        [14.2, 12.1], [12.7, 15.2], [8.6, 13.7],  [11.1, 13.9], [11.6, 8.9],         [9.6, 12.9],  [8.4, 7.9],   [9.3, 11.1],  [9.7, 10.2],  [12.7, 10.3], 
 +        [14.4, 9.7],  [12.9, 12.6], [12.0, 9.5],  [9.7, 12.9],  [12.1, 11.8],        [9.0, 12.8],  [6.8, 10.7],  [13.7, 10.3], [9.1, 13.0],  [12.1, 11.1], 
 +        [12.3, 9.4],  [12.0, 11.8], [9.8, 11.2],  [13.6, 7.4],  [7.2, 10.6],         [6.9, 12.4],  [11.5, 9.5],  [13.4, 11.3], [6.8, 8.9],   [8.7, 12.4], 
 +        [19.7, 10.2], [13.8, 2.6],  [15.7, 12.7], [13.5, 17.3], [4.0, 13.2],         [9.1, 4.9],   [7.8, 16.7],  [6.9, 15.9],  [16.2, 8.2],  [15.9, 9.5], 
 +        [4.4, 15.3],  [18.2, 5.6],  [8.5, 15.5],  [18.3, 15.2], [3.9, 9.8],          [8.3, 6.7],   [15.1, 7.7],  [17.9, 9.5],  [11.7, 5.6],  [11.4, 4.8], 
 +        [9.5, 5.1],   [8.3, 2.5],   [11.7, 4.2],  [17.1, 10.0], [4.9, 17.2],         [18.7, 15.4], [11.5, 18.9], [12.0, 16.5], [5.4, 17.5],  [13.5, 4.7], 
 +        [18.6, 14.0], [3.5, 13.4],  [13.9, 4.0],  [10.3, 19.0], [18.6, 14.2],        [11.3, 17.8], [17.0, 14.5], [12.9, 6.0],  [14.1, 16.7], [13.9, 19.0], 
 +        [13.3, 5.6],  [14.0, 3.6],  [4.0, 6.6],   [16.0, 8.0],  [18.5, 14.0],        [18.4, 9.3],  [3.0, 7.2],   [8.9, 17.2],  [14.7, 3.9],  [6.5, 3.9],
 +        [17.5, 10.4], [15.6, 14.7], [5.3, 7.8],   [3.5, 12.3],  [7.5, 6.1],          [11.4, 19.4], [17.1, 12.2], [3.3, 8.8],   [6.9, 15.7],  [16.5, 6.6],
 +        [2.8, 13.1],  [4.9, 14.4],  [6.0, 5.4],   [4.7, 9.9],   [17.7, 9.3],         [12.3, 5.9],  [3.9, 11.1],  [12.6, 17.6], [6.1, 7.2],   [10.9, 5.3], 
 +        [11.2, 4.6],  [17.2, 10.7], [12.3, 17.3], [3.6, 14.7],  [3.4, 15.0],         [7.4, 18.9],  [6.6, 16.0],  [2.5, 12.2],  [3.9, 9.1],   [10.1, 19.9],
 +        [14.7, 15.1], [8.4, 18.6],  [15.8, 16.6], [8.1, 17.4],  [7.5, 3.7],          [4.3, 6.0],   [19.3, 10.9], [5.1, 8.6],   [4.8, 9.0],   [6.4, 5.2], 
 +        [10.2, 5.9],  [4.8, 5.5],   [4.8, 7.1],   [5.6, 6.8],   [6.4, 17.0],         [12.5, 2.3],  [4.5, 6.0],   [8.2, 18.1],  [11.2, 16.8], [19.0, 14.8]
 +    ])
 +
 +
 +y_validacion = np.array([
 +     1, 1, 1, 1, 1,      1, 1, 1, 1, 1, 
 +     1, 1, 1, 1, 1,      1, 1, 1, 1, 1, 
 +     1, 1, 1, 1, 1,      1, 1, 1, 1, 1, 
 +     1, 1, 1, 1, 1,      1, 1, 1, 1, 1, 
 +     1, 1, 1, 1, 1,      1, 1, 1, 1, 1, 
 +     1, 1, 1, 1, 1,      1, 1, 1, 1, 1, 
 +     1, 1, 1, 1, 1,      1, 1, 1, 1, 1, 
 +     1, 1, 1, 1, 1,      1, 1, 1, 1, 1, 
 +     1, 1, 1, 1, 1,      1, 1, 1, 1, 1, 
 +     1, 1, 1, 1, 1,      1, 1, 1, 1, 1,    
 +     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, 0, 0, 0, 0
 +])
 +
 +
 +
 +figure=plt.figure(figsize = (12, 5))
 +
 +model=compile_model(20,40,20,1)
 +model.fit(x_entrenamiento, y_entrenamiento,epochs=1200,verbose=False) 
 +plot_result(model,x_entrenamiento, y_entrenamiento,figure,"Datos entrenamiento",1,2,1)
 +plot_result(model,x_validacion, y_validacion,figure,"Datos validación",1,2,2)
 +
 +</sxh>
 +
 +¿Que ha ocurrido?
 +
 +
 +
 +
 +
 +