Una red neuronal simple en dos pasos
Este es el código para implementar una red neuronal muy simple para convertir de celsius a farenheit:
import tensorflow as tf import numpy as np celsius = np.array([-40, -10, 0, 8, 15, 22, 38], dtype=float) fahrenheit = np.array([-40, 14, 32, 46, 59, 72, 100], dtype=float) capa = tf.keras.layers.Dense(units=1, input_shape=[1]) modelo = tf.keras.Sequential([capa]) modelo.compile( optimizer=tf.keras.optimizers.Adam(0.1), loss='mean_squared_error' ) print("Comenzando entrenamiento...") historial = modelo.fit(celsius, fahrenheit, epochs=1000, verbose=False) print("Modelo entrenado!") import matplotlib.pyplot as plt plt.xlabel("# Epoca") plt.ylabel("Magnitud de pérdida") plt.plot(historial.history["loss"]) plt.show() print("Hagamos una predicción!") resultado = modelo.predict(np.array([100.0])) print("El resultado es " + str(resultado) + " fahrenheit!") print("Variables internas del modelo") print(capa.get_weights())
Esto nos da el siguiente resultado:
Variables internas del modelo
[array([[1.7982929]], dtype=float32), array([31.912598], dtype=float32)]
El primer array es el peso, el segundo el sesgo. Si nos fijamos es prácticamente la fórmula de celsius a farenhet: c*1.8+32
Vamos a crear una red neuronal más compleja:
# -*- coding: utf-8 -*- """Tu primera red neuronal en Python y Tensorflow Automatically generated by Colab. Original file is located at https://colab.research.google.com/drive/1ehETBOVtCqe7G6HOvm84hfXba8Gd9ILW """ import tensorflow as tf import numpy as np celsius = np.array([-40, -10, 0, 8, 15, 22, 38], dtype=float) fahrenheit = np.array([-40, 14, 32, 46, 59, 72, 100], dtype=float) #capa = tf.keras.layers.Dense(units=1, input_shape=[1]) #modelo = tf.keras.Sequential([capa]) oculta1 = tf.keras.layers.Dense(units=3, input_shape=[1]) oculta2 = tf.keras.layers.Dense(units=3) salida = tf.keras.layers.Dense(units=1) modelo = tf.keras.Sequential([oculta1, oculta2, salida]) modelo.compile( optimizer=tf.keras.optimizers.Adam(0.1), loss='mean_squared_error' ) print("Comenzando entrenamiento...") historial = modelo.fit(celsius, fahrenheit, epochs=1000, verbose=False) print("Modelo entrenado!") import matplotlib.pyplot as plt plt.xlabel("# Epoca") plt.ylabel("Magnitud de pérdida") plt.plot(historial.history["loss"]) plt.show() print("Hagamos una predicción!") resultado = modelo.predict(np.array([100.0])) print("El resultado es " + str(resultado) + " fahrenheit!") print("Variables internas del modelo") #print(capa.get_weights()) print(oculta1.get_weights()) print(oculta2.get_weights()) print(salida.get_weights())
Si observamos la función de pérdida vemos que converge mucho antes que en el ejemplo anterior.Por contra, cuando leemos los pesos de las neuronas no encontramos la fórmula por ninguna parte. Es como si estuviera repartida por toda la red:
Variables internas del modelo
[array([[ 0.01929676, 0.44041264, -0.9853406 ]], dtype=float32), array([-1.021315 , -2.922543 , -4.4550357], dtype=float32)]
[array([[-0.06822873, -0.06130026, -0.3770733 ],
[-0.97541404, -0.18267964, 1.0810823 ],
[-1.536018 , 0.20811819, 0.27868012]], dtype=float32), array([ 4.2216773, -1.8147309, -2.4485366], dtype=float32)]
[array([[ 1.7366303 ],
[-0.07388519],
[-0.5318345 ]], dtype=float32), array([4.0690985], dtype=float32)]
Vamos a ver cada línea de salida en el orden en que se imprimieron y desglosar su significado.
1. oculta1.get_weights()
[array([[ 0.02538998, -0.07799665, 0.58149683]], dtype=float32),
array([1.4827102, 3.470378 , 3.6755922], dtype=float32)]
- El primer
array
representa los pesos de la capa oculta 1 (oculta1
):array([[ 0.02538998, -0.07799665, 0.58149683]], dtype=float32)
Esto significa que la capa tiene una sola neurona de entrada y tres neuronas de salida, ya que hay tres valores en el array. Cada valor se corresponde con el peso entre la neurona de entrada y una neurona de salida.
- El segundo
array
representa los sesgos de la capa oculta 1:array([1.4827102, 3.470378 , 3.6755922], dtype=float32)
Este vector de tres valores indica que cada neurona de salida en la capa oculta 1 tiene un sesgo asociado. Estos valores se suman a las salidas después de aplicar los pesos.
2. oculta2.get_weights()
[array([[-0.6096995 , -0.7340779 , 0.43933964],
[-0.8162171 , 0.01671466, -0.20573232],
[-1.3099183 , 0.655951 , 0.8290832 ]], dtype=float32),
array([-3.69672 , 3.7285566, 2.5801601], dtype=float32)]
- El primer
array
representa los pesos de la capa oculta 2 (oculta2
):array([[-0.6096995 , -0.7340779 , 0.43933964], [-0.8162171 , 0.01671466, -0.20573232], [-1.3099183 , 0.655951 , 0.8290832 ]], dtype=float32)
Aquí tenemos una matriz de pesos con dimensiones 3×3, lo que significa que esta capa tiene tres neuronas de entrada (provenientes de
oculta1
) y tres neuronas de salida. Cada fila representa los pesos de una neurona de entrada conectada a cada neurona de salida. - El segundo
array
representa los sesgos de la capa oculta 2:array([-3.69672 , 3.7285566, 2.5801601], dtype=float32)
Esta capa también tiene tres neuronas de salida, por lo que el vector de sesgos contiene tres valores, uno para cada neurona de salida.
3. salida.get_weights()
[array([[-1.7758566 ],
[ 0.6707964 ],
[ 0.56612307]], dtype=float32),
array([3.6241126], dtype=float32)]
- El primer
array
representa los pesos de la capa de salida (salida
):array([[-1.7758566 ], [ 0.6707964 ], [ 0.56612307]], dtype=float32)
Esta matriz tiene dimensiones 3×1, lo cual sugiere que la capa de salida recibe tres neuronas de entrada (las salidas de
oculta2
) y tiene una sola neurona de salida. Esto es típico en problemas de regresión con una salida única, o en una red neuronal para clasificación binaria. - El segundo
array
representa el sesgo de la capa de salida:array([3.6241126], dtype=float32)
Esta capa tiene un solo sesgo, ya que tiene solo una neurona de salida. Este valor se sumará al producto de las entradas y los pesos para calcular la salida final.
Resumen General
- Capa
oculta1
:- Tiene 1 neurona de entrada y 3 neuronas de salida.
- Matriz de pesos: 1×3 (un valor para cada conexión).
- Vector de sesgos: tamaño 3 (uno para cada neurona de salida).
- Capa
oculta2
:- Tiene 3 neuronas de entrada y 3 neuronas de salida.
- Matriz de pesos: 3×3 (cada neurona de entrada está conectada a cada neurona de salida).
- Vector de sesgos: tamaño 3 (uno para cada neurona de salida).
- Capa
salida
:- Tiene 3 neuronas de entrada y 1 neurona de salida.
- Matriz de pesos: 3×1 (cada neurona de entrada está conectada a la única neurona de salida).
- Vector de sesgo: tamaño 1 (un solo sesgo para la neurona de salida).