Si llevamos las funciones anteriores a nuestra clase, el resultado es el siguiente:
import numpy as np
def sigmoid(a: np.ndarray):
""" Aplica la función sigmoide al array a elemento por elemento """
return 1 / (1 + np.exp(-a))
class NNClassifier(object):
def __init__(self, sizes, learning_rate = 0.01, batch_size = 16, epochs = 10):
""" Constructor de la red neuronal """
self.num_layers = len(sizes) # Número total de capas de la red
self.sizes = sizes # Lista conteniendo el número de neuronas por capa
self.learning_rate = learning_rate # Tasa de aprendizaje
self.batch_size = batch_size # Tamaño del batch
self.epochs = epochs # Número de epochs durante los que entrenar la red
self.weights = [np.random.randn(x, y) for (x, y) in zip(sizes[1:], sizes[:-1])]
self.biases = [np.random.randn(n, 1) for n in sizes[1:]]
def fit(self, X, y):
""" Entrenamiento de la red neuronal"""
pass
def getOutput(self, x: np.ndarray):
""" Obtención de la predicción para una muestra """
for b, w in zip(self.biases, self.weights):
x = sigmoid(np.dot(w, x) + b)
return x
def predict(self, X: pd.core.frame.DataFrame):
""" Obtención de la predicción para las muestras contenidas en un DataFrame """
predictions = np.zeros(shape = len(X))
X.reset_index(inplace = True, drop = True)
for i, sample in X.iterrows():
prediction = model.getOutput(sample.values.reshape(-1, 1))
predictions[i] = np.argmax(prediction)
return predictions
Podemos probar nuestro código instanciando la clase:
model = NNClassifier(
sizes = [784, 16, 10],
learning_rate = 0.01,
batch_size = 32,
epochs = 10
)
...y realizando la predicción para, por ejemplo, las dos primeras muestras del dataset de validación:
model.predict(x_test.iloc[:2])
array([8., 6.])
Según nuestra red, dichas imágenes contienen la representación de un "8" y de un "6" cuando, en realidad, contienen un "3" y un "6":
y_test.iloc[:2]
3048 3
19563 6
Name: 0, dtype: int64
...pero recordemos que nuestra red ha sido inicializada con parámetros aleatorios. De hecho podemos invocar el método getOutput directamente pasando como argumento la primera muestra (convertida en array NumPy y redimensionada adecuadamente) para ver los 10 valores devueltos por la capa de salida:
model.getOutput(x_test.iloc[:1].values.reshape(-1, 1))
array([[0.30523477],
[0.57950046],
[0.28522335],
[0.46637227],
[0.77167217],
[0.02410213],
[0.65351747],
[0.01062654],
[0.77868403],
[0.04864604]]).