#@title Importar librerías
#importar librerías necesarias
import random
import numpy as np
import pandas as pd
from tqdm.notebook import tqdm
from matplotlib import pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.neural_network import MLPClassifier
from sklearn.datasets import fetch_openml
from sklearn.metrics import classification_report, confusion_matrix
from sklearn import set_config
='diagram')
set_config(displayimport seaborn as sns
import random
import tensorflow as tf
import tensorflow.keras as keras
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, Activation, Input
from tensorflow.keras.optimizers import SGD
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.datasets import mnist
from tensorflow.keras.utils import plot_model
Implementado un Perceptrón multi-capa usando frameworks
#@title Funciones complementarias
def plot_samples_dataset(X, y):
# Convertir las etiquetas a enteros
= y.astype(int)
y
# Crear la grilla de 4x4
= plt.subplots(4, 4, figsize=(6, 6))
fig, axes 'Grilla de imágenes del dataset MNIST')
fig.suptitle(
# Iterar para mostrar las primeras 16 imágenes con sus etiquetas
for i, ax in enumerate(axes.flat):
= X.iloc[i].values.reshape(28, 28)
img = y[i]
label ='gray')
ax.imshow(img, cmapf'Label: {label}')
ax.set_title('off')
ax.axis(
plt.show()
def plot_curva_aprendizaje(mlp):
=(8, 5))
plt.figure(figsize='o')
plt.plot(mlp.loss_curve_, marker'Pérdida durante el entrenamiento del MLP por iteración')
plt.title('Iteración')
plt.xlabel('Pérdida (Loss)')
plt.ylabel(
plt.grid()
plt.show()
def plot_matriz_confusion(cm):
# Visualizar la matriz de confusión usando Seaborn
=(10, 7))
plt.figure(figsize=True, fmt='d', cmap='Blues', xticklabels=range(10), yticklabels=range(10))
sns.heatmap(cm, annot'Etiqueta predicha')
plt.xlabel('Etiqueta real')
plt.ylabel('Matriz de Confusión para el MLP en el dataset MNIST')
plt.title(
plt.show()
def encontrar_dim_imagen(n_neurons):
"""
Encuentra la mejor forma cuadrada (filas, columnas) para una cantidad dada de neuronas.
"""
= int(np.sqrt(n_neurons)) # Calcular la raíz cuadrada del número de neuronas
side_length if side_length * side_length == n_neurons:
return (side_length, side_length) # Si es un cuadrado perfecto
else:
# Si no es un cuadrado perfecto, buscamos la mejor aproximación (filas, columnas)
for i in range(side_length, 0, -1):
if n_neurons % i == 0:
return (i, n_neurons // i) # Devolver filas y columnas
return (n_neurons, 1) # Si no encuentra, retornar en forma de vector (n_neurons, 1)
def visualizacion_pesos_mlp(mlp):
# Definir la figura con 3 filas y 5 columnas
= plt.subplots(3, 5, figsize=(15, 9))
fig, axes
# Asignar las dimensiones para visualizar cada capa
= [encontrar_dim_imagen(layer.shape[0]) for layer in mlp.coefs_]
layer_shapes
# Recorrer cada capa de coeficientes del MLP
for layer_index, (layer_coefs, ax_row) in enumerate(zip(mlp.coefs_, axes)):
# Seleccionar aleatoriamente 5 neuronas de la capa actual
= layer_coefs.shape[1]
num_neurons = random.sample(range(num_neurons), 5)
random_neurons
# Obtener la forma de visualización para esta capa
= layer_shapes[layer_index]
layer_shape
= layer_coefs.min(), layer_coefs.max()
vmin, vmax
# Visualizar las neuronas seleccionadas
for neuron_index, ax in zip(random_neurons, ax_row):
# Seleccionar los pesos de la neurona específica y reestructurarlos en una matriz 2D
= layer_coefs[:, neuron_index].reshape(layer_shape)
neuron_weights # Dibujar la imagen de los pesos de la neurona
=plt.cm.gray, vmin=0.5 * vmin, vmax=0.5 * vmax)
ax.matshow(neuron_weights, cmap
ax.set_xticks([])
ax.set_yticks([])f'Capa {layer_index+1}, Neurona {neuron_index}')
ax.set_title(
'Visualización de Pesos de las Neuronas en las Capas Ocultas')
plt.suptitle(
plt.tight_layout()
plt.show()
def plot_loss_historia_keras(history):
# Graficar el histórico de pérdida durante el entrenamiento
'loss'], label='Pérdida de Entrenamiento')
plt.plot(history.history['val_loss'], label='Pérdida de Validación')
plt.plot(history.history['Pérdida durante el Entrenamiento')
plt.title('Época')
plt.xlabel('Pérdida')
plt.ylabel(
plt.legend()
plt.show()
def plot_acc_historia_keras(history):
# Graficar la precisión durante el entrenamiento
'accuracy'], label='Precisión de Entrenamiento')
plt.plot(history.history['val_accuracy'], label='Precisión de Validación')
plt.plot(history.history['Precisión durante el Entrenamiento')
plt.title('Época')
plt.xlabel('Precisión')
plt.ylabel(
plt.legend()
plt.show()
def visualizacion_pesos_mlp_keras(model):
# Obtener los pesos del modelo (par de listas [pesos, biases] para cada capa)
= model.get_weights()
weights
# Extraer solo los pesos de cada capa oculta, ignorando los bias
= [weights[i] for i in range(0, len(weights), 2)] # Solo los pesos, no los sesgos
layer_weights
# Definir la figura con 3 filas (una por cada capa) y 5 columnas (5 neuronas al azar)
= plt.subplots(len(layer_weights), 5, figsize=(15, 9))
fig, axes
# Calcular las formas de cada capa de manera dinámica
= [encontrar_dim_imagen(layer.shape[0]) for layer in layer_weights]
layer_shapes
# Recorrer cada capa y sus pesos
for layer_index, (layer_coefs, ax_row) in enumerate(zip(layer_weights, axes)):
# Seleccionar aleatoriamente 5 neuronas de la capa actual
= layer_coefs.shape[1]
num_neurons = random.sample(range(num_neurons), 5)
random_neurons
# Obtener la forma de visualización para esta capa
= layer_shapes[layer_index]
layer_shape = layer_coefs.min(), layer_coefs.max()
vmin, vmax
# Visualizar las neuronas seleccionadas
for neuron_index, ax in zip(random_neurons, ax_row):
# Seleccionar los pesos de la neurona específica y reestructurarlos en una matriz 2D
= layer_coefs[:, neuron_index].reshape(layer_shape)
neuron_weights # Dibujar la imagen de los pesos de la neurona
=plt.cm.gray, vmin=0.5 * vmin, vmax=0.5 * vmax)
ax.matshow(neuron_weights, cmap
ax.set_xticks([])
ax.set_yticks([])f'Capa {layer_index+1}, Neurona {neuron_index}')
ax.set_title(
'Visualización de Pesos de las Neuronas en las Capas Ocultas de Keras')
plt.suptitle(
plt.tight_layout() plt.show()
Dataset MNIST (Clasificación multiclase)
Trabajaremos con el clásico dataset de imágenes de digitos escritos a mano. Esta dataset puede ser descargado de diversas fuentes incluido sklearn.
# Cargar el dataset de MNIST
= fetch_openml('mnist_784', version=1)
mnist = mnist['data'], mnist['target'] X, y
# Visualizamos algunas imágenes
plot_samples_dataset(X, y)
Un breve vistazo del dataset nos indica que la mayoría de pixeles de la imágen estan en 0 y que los que tiene valor estan en 255. Esta escala, es los valores de intensidad en escala de grises. Además, vemos que la información esta organizada en un dataframe con 784 columnas lo que se traduce en una versión vectorizada de una imágen de 28x28 píxeles.
X.describe()
pixel1 | pixel2 | pixel3 | pixel4 | pixel5 | pixel6 | pixel7 | pixel8 | pixel9 | pixel10 | ... | pixel775 | pixel776 | pixel777 | pixel778 | pixel779 | pixel780 | pixel781 | pixel782 | pixel783 | pixel784 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
count | 70000.0 | 70000.0 | 70000.0 | 70000.0 | 70000.0 | 70000.0 | 70000.0 | 70000.0 | 70000.0 | 70000.0 | ... | 70000.000000 | 70000.000000 | 70000.000000 | 70000.000000 | 70000.000000 | 70000.000000 | 70000.0 | 70000.0 | 70000.0 | 70000.0 |
mean | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | ... | 0.197414 | 0.099543 | 0.046629 | 0.016614 | 0.012957 | 0.001714 | 0.0 | 0.0 | 0.0 | 0.0 |
std | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | ... | 5.991206 | 4.256304 | 2.783732 | 1.561822 | 1.553796 | 0.320889 | 0.0 | 0.0 | 0.0 | 0.0 |
min | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | ... | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.0 |
25% | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | ... | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.0 |
50% | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | ... | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.0 |
75% | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | ... | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.0 |
max | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | ... | 254.000000 | 254.000000 | 253.000000 | 253.000000 | 254.000000 | 62.000000 | 0.0 | 0.0 | 0.0 | 0.0 |
8 rows × 784 columns
Antes de hacer la división del conjunto de datos, podemos hacer una normalización de los valores de los píxeles para que esten entre 0-1, así es más fácil para la red optimizar la función de pérdida.
# Normalización
= X / 255. X
# usar train test split para dividir los datos X y y
= train_test_split(X, y,
X_train, X_test, y_train, y_test =0.30, random_state=42)
test_size
print('Dimensión X_train: {}'.format(X_train.shape))
print('Dimensión X_test: {}'.format(X_test.shape))
Dimensión X_train: (49000, 784)
Dimensión X_test: (21000, 784)
MLP clasificador multiclase en Sklearn
Seguidamente, vamos a crear un clasificador MLP usando la librería sklearn, pueden encontrar toda la documentación en: Documentación MLP.
= MLPClassifier(hidden_layer_sizes=(225, 100), activation = 'relu',
mlp =30, alpha=1e-4,
max_iter='sgd', verbose=10, random_state=1,
solver= 'adaptive',
learning_rate = 0.1,
learning_rate_init =False, validation_fraction=0.2)
early_stopping
mlp
MLPClassifier(hidden_layer_sizes=(225, 100), learning_rate='adaptive', learning_rate_init=0.1, max_iter=30, random_state=1, solver='sgd', validation_fraction=0.2, verbose=10)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
MLPClassifier(hidden_layer_sizes=(225, 100), learning_rate='adaptive', learning_rate_init=0.1, max_iter=30, random_state=1, solver='sgd', validation_fraction=0.2, verbose=10)
# Entrenar el clasificador MLP en los datos de entrenamiento
mlp.fit(X_train, y_train)
Iteration 1, loss = 0.29809553
Iteration 2, loss = 0.10153217
Iteration 3, loss = 0.07025477
Iteration 4, loss = 0.05107289
Iteration 5, loss = 0.03813628
Iteration 6, loss = 0.02863240
Iteration 7, loss = 0.02136907
Iteration 8, loss = 0.01639116
Iteration 9, loss = 0.01391393
Iteration 10, loss = 0.00862180
Iteration 11, loss = 0.00514989
Iteration 12, loss = 0.00551735
Iteration 13, loss = 0.00416624
Iteration 14, loss = 0.00174071
Iteration 15, loss = 0.00094037
Iteration 16, loss = 0.00082533
Iteration 17, loss = 0.00067903
Iteration 18, loss = 0.00057994
Iteration 19, loss = 0.00053067
Iteration 20, loss = 0.00050842
Iteration 21, loss = 0.00048905
Iteration 22, loss = 0.00047281
Iteration 23, loss = 0.00045934
Iteration 24, loss = 0.00044890
Iteration 25, loss = 0.00043982
Iteration 26, loss = 0.00042988
Iteration 27, loss = 0.00042256
Iteration 28, loss = 0.00041607
Training loss did not improve more than tol=0.000100 for 10 consecutive epochs. Setting learning rate to 0.020000
Iteration 29, loss = 0.00040552
Iteration 30, loss = 0.00040366
/usr/local/lib/python3.11/dist-packages/sklearn/neural_network/_multilayer_perceptron.py:691: ConvergenceWarning: Stochastic Optimizer: Maximum iterations (30) reached and the optimization hasn't converged yet.
warnings.warn(
MLPClassifier(hidden_layer_sizes=(225, 100), learning_rate='adaptive', learning_rate_init=0.1, max_iter=30, random_state=1, solver='sgd', validation_fraction=0.2, verbose=10)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
MLPClassifier(hidden_layer_sizes=(225, 100), learning_rate='adaptive', learning_rate_init=0.1, max_iter=30, random_state=1, solver='sgd', validation_fraction=0.2, verbose=10)
# imprimir la curva de evolución de la pérdida
plot_curva_aprendizaje(mlp)
Evaluación completa
Realizaremos una evaluación completa revisando el rendimiento en ambos conjuntos, seguidamente generaremos el reporte de clasificación y la matriz de confusión.
print(f"Training set score: {mlp.score(X_train, y_train):.3f}")
print(f"Test set score: {mlp.score(X_test, y_test):.3f}")
Training set score: 1.000
Test set score: 0.982
# Realizar predicciones
= mlp.predict(X_test)
y_pred
# Imprimir el reporte de métricas
print("Reporte de Clasificación del MLP en MNIST:\n")
print(classification_report(y_test, y_pred))
# Generar la matriz de confusión
= confusion_matrix(y_test, y_pred)
cm
# visualizar la matriz de confusión
plot_matriz_confusion(cm)
Reporte de Clasificación del MLP en MNIST:
precision recall f1-score support
0 0.99 0.99 0.99 2058
1 0.99 0.99 0.99 2364
2 0.98 0.98 0.98 2133
3 0.98 0.98 0.98 2176
4 0.98 0.98 0.98 1936
5 0.98 0.98 0.98 1915
6 0.98 0.99 0.99 2088
7 0.98 0.98 0.98 2248
8 0.98 0.97 0.97 1992
9 0.98 0.97 0.98 2090
accuracy 0.98 21000
macro avg 0.98 0.98 0.98 21000
weighted avg 0.98 0.98 0.98 21000
Visualización de pesos
# pesos de la primera capa oculta. Todas las neuronas conectadas con cada pixel
print('Dimensión de la primera capa oculta: {}'.format(mlp.coefs_[0].shape))
print('Dimensión de la segunda capa oculta: {}'.format(mlp.coefs_[1].shape))
print('Dimensión de la tercera capa oculta: {}'.format(mlp.coefs_[2].shape))
Dimensión de la primera capa oculta: (784, 225)
Dimensión de la segunda capa oculta: (225, 100)
Dimensión de la tercera capa oculta: (100, 10)
visualizacion_pesos_mlp(mlp)
Tutoriales relacionados
MLP Clasificador multiclase en keras
# Asumiendo que X_train y y_train ya están definidos como en el ejemplo anterior
# Preprocesar las etiquetas para que sean categóricas (one-hot encoding)
= to_categorical(y_train)
y_train_categorical y_train_categorical
array([[1., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
...,
[0., 1., 0., ..., 0., 0., 0.],
[1., 0., 0., ..., 0., 0., 0.],
[1., 0., 0., ..., 0., 0., 0.]])
# crear modelo usando el API secuencial
def MLPClassifier_keras():
# Definir el modelo similar al de sklearn
= Sequential()
model =(784,)))
model.add(Input(shape225, activation='relu')) # Primera capa con 225 neuronas
model.add(Dense(0.3)) # Regularización con Dropout
model.add(Dropout(100, activation='relu')) # Segunda capa con 100 neuronas
model.add(Dense(0.3)) # Regularización con Dropout
model.add(Dropout(10, activation='softmax')) # Capa de salida para 10 clases
model.add(Dense(
return model
= MLPClassifier_keras() mlp_keras
# Compilar el modelo
compile(loss='categorical_crossentropy',
mlp_keras.=SGD(),
optimizer=['accuracy'])
metrics
# Entrenar el modelo
= mlp_keras.fit(X_train.values.astype(float), y_train_categorical,
history =30,
epochs=128,
batch_size=0.2,
validation_split=1) verbose
Epoch 1/30 307/307 ━━━━━━━━━━━━━━━━━━━━ 3s 8ms/step - accuracy: 0.3138 - loss: 2.0007 - val_accuracy: 0.7991 - val_loss: 0.9513 Epoch 2/30 307/307 ━━━━━━━━━━━━━━━━━━━━ 3s 9ms/step - accuracy: 0.6957 - loss: 1.0220 - val_accuracy: 0.8515 - val_loss: 0.5812 Epoch 3/30 307/307 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.7769 - loss: 0.7337 - val_accuracy: 0.8764 - val_loss: 0.4649 Epoch 4/30 307/307 ━━━━━━━━━━━━━━━━━━━━ 3s 7ms/step - accuracy: 0.8102 - loss: 0.6144 - val_accuracy: 0.8880 - val_loss: 0.4049 Epoch 5/30 307/307 ━━━━━━━━━━━━━━━━━━━━ 3s 8ms/step - accuracy: 0.8331 - loss: 0.5537 - val_accuracy: 0.8968 - val_loss: 0.3667 Epoch 6/30 307/307 ━━━━━━━━━━━━━━━━━━━━ 3s 9ms/step - accuracy: 0.8495 - loss: 0.4994 - val_accuracy: 0.9018 - val_loss: 0.3398 Epoch 7/30 307/307 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.8636 - loss: 0.4648 - val_accuracy: 0.9084 - val_loss: 0.3175 Epoch 8/30 307/307 ━━━━━━━━━━━━━━━━━━━━ 2s 7ms/step - accuracy: 0.8706 - loss: 0.4392 - val_accuracy: 0.9133 - val_loss: 0.3014 Epoch 9/30 307/307 ━━━━━━━━━━━━━━━━━━━━ 2s 7ms/step - accuracy: 0.8823 - loss: 0.4042 - val_accuracy: 0.9170 - val_loss: 0.2878 Epoch 10/30 307/307 ━━━━━━━━━━━━━━━━━━━━ 4s 11ms/step - accuracy: 0.8859 - loss: 0.3866 - val_accuracy: 0.9202 - val_loss: 0.2748 Epoch 11/30 307/307 ━━━━━━━━━━━━━━━━━━━━ 2s 6ms/step - accuracy: 0.8905 - loss: 0.3744 - val_accuracy: 0.9239 - val_loss: 0.2640 Epoch 12/30 307/307 ━━━━━━━━━━━━━━━━━━━━ 3s 7ms/step - accuracy: 0.8948 - loss: 0.3648 - val_accuracy: 0.9256 - val_loss: 0.2542 Epoch 13/30 307/307 ━━━━━━━━━━━━━━━━━━━━ 2s 6ms/step - accuracy: 0.8986 - loss: 0.3451 - val_accuracy: 0.9276 - val_loss: 0.2458 Epoch 14/30 307/307 ━━━━━━━━━━━━━━━━━━━━ 2s 7ms/step - accuracy: 0.9012 - loss: 0.3449 - val_accuracy: 0.9299 - val_loss: 0.2373 Epoch 15/30 307/307 ━━━━━━━━━━━━━━━━━━━━ 4s 11ms/step - accuracy: 0.9062 - loss: 0.3241 - val_accuracy: 0.9307 - val_loss: 0.2308 Epoch 16/30 307/307 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.9036 - loss: 0.3243 - val_accuracy: 0.9319 - val_loss: 0.2244 Epoch 17/30 307/307 ━━━━━━━━━━━━━━━━━━━━ 2s 7ms/step - accuracy: 0.9093 - loss: 0.3088 - val_accuracy: 0.9339 - val_loss: 0.2181 Epoch 18/30 307/307 ━━━━━━━━━━━━━━━━━━━━ 2s 7ms/step - accuracy: 0.9100 - loss: 0.3071 - val_accuracy: 0.9350 - val_loss: 0.2124 Epoch 19/30 307/307 ━━━━━━━━━━━━━━━━━━━━ 3s 9ms/step - accuracy: 0.9136 - loss: 0.2921 - val_accuracy: 0.9363 - val_loss: 0.2066 Epoch 20/30 307/307 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.9184 - loss: 0.2851 - val_accuracy: 0.9379 - val_loss: 0.2027 Epoch 21/30 307/307 ━━━━━━━━━━━━━━━━━━━━ 3s 7ms/step - accuracy: 0.9173 - loss: 0.2758 - val_accuracy: 0.9390 - val_loss: 0.1975 Epoch 22/30 307/307 ━━━━━━━━━━━━━━━━━━━━ 2s 7ms/step - accuracy: 0.9189 - loss: 0.2712 - val_accuracy: 0.9409 - val_loss: 0.1928 Epoch 23/30 307/307 ━━━━━━━━━━━━━━━━━━━━ 4s 10ms/step - accuracy: 0.9228 - loss: 0.2618 - val_accuracy: 0.9431 - val_loss: 0.1893 Epoch 24/30 307/307 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.9235 - loss: 0.2622 - val_accuracy: 0.9435 - val_loss: 0.1858 Epoch 25/30 307/307 ━━━━━━━━━━━━━━━━━━━━ 3s 7ms/step - accuracy: 0.9252 - loss: 0.2520 - val_accuracy: 0.9446 - val_loss: 0.1824 Epoch 26/30 307/307 ━━━━━━━━━━━━━━━━━━━━ 3s 7ms/step - accuracy: 0.9275 - loss: 0.2514 - val_accuracy: 0.9453 - val_loss: 0.1784 Epoch 27/30 307/307 ━━━━━━━━━━━━━━━━━━━━ 4s 10ms/step - accuracy: 0.9265 - loss: 0.2499 - val_accuracy: 0.9472 - val_loss: 0.1744 Epoch 28/30 307/307 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.9262 - loss: 0.2520 - val_accuracy: 0.9478 - val_loss: 0.1717 Epoch 29/30 307/307 ━━━━━━━━━━━━━━━━━━━━ 2s 7ms/step - accuracy: 0.9307 - loss: 0.2360 - val_accuracy: 0.9496 - val_loss: 0.1685 Epoch 30/30 307/307 ━━━━━━━━━━━━━━━━━━━━ 2s 6ms/step - accuracy: 0.9329 - loss: 0.2284 - val_accuracy: 0.9506 - val_loss: 0.1661
plot_loss_historia_keras(history)
plot_acc_historia_keras(history)
=True, show_layer_names=True, dpi=80) plot_model(mlp_keras, show_shapes
Evaluación completa
= to_categorical(y_test)
y_test_categorical
= mlp_keras.evaluate(X_test.values.astype(float), y_test_categorical, batch_size=128)
score
score
165/165 ━━━━━━━━━━━━━━━━━━━━ 1s 3ms/step - accuracy: 0.9484 - loss: 0.1750
[0.175654336810112, 0.9481428861618042]
# Realizar predicciones en el conjunto de prueba
= mlp_keras.predict(X_test.values.astype(float))
y_pred
# Convertir las predicciones en etiquetas (la clase con mayor probabilidad)
= np.argmax(y_pred, axis=1)
y_pred_classes = y_test.values.astype(int) # Las etiquetas reales del conjunto de prueba y_true
657/657 ━━━━━━━━━━━━━━━━━━━━ 1s 2ms/step
# Generar el reporte de clasificación
print("Reporte de Clasificación para el MLP en MNIST:\n")
print(classification_report(y_true, y_pred_classes))
# Crear la matriz de confusión
= confusion_matrix(y_true, y_pred_classes)
cm
# Visualizar la matriz de confusión usando Seaborn
plot_matriz_confusion(cm)
Reporte de Clasificación para el MLP en MNIST:
precision recall f1-score support
0 0.97 0.98 0.97 2058
1 0.96 0.98 0.97 2364
2 0.95 0.94 0.94 2133
3 0.93 0.94 0.93 2176
4 0.94 0.95 0.94 1936
5 0.95 0.93 0.94 1915
6 0.96 0.97 0.97 2088
7 0.95 0.96 0.95 2248
8 0.95 0.92 0.93 1992
9 0.93 0.92 0.93 2090
accuracy 0.95 21000
macro avg 0.95 0.95 0.95 21000
weighted avg 0.95 0.95 0.95 21000
Visualización de pesos
visualizacion_pesos_mlp_keras(mlp_keras)
✅ Cómo transformar tus datos para usar un MLP estándar (Keras o scikit-learn)
Tipo de dato o problema | ¿Qué debes hacer para usar un MLP? | Ejemplo sencillo |
---|---|---|
📝 Texto | Convertir el texto a vectores. Usa técnicas como Bag of Words (BoW), TF-IDF. | Clasificación de sentimientos: convertir cada comentario en un vector TF-IDF |
⏱ Series temporales | Dividir en ventanas de tiempo fijas y calcular características estadísticas (media, std, min, max, energía, etc.) por ventana. | Predicción de fallas: usar estadísticas de 10s de datos de sensores como entrada al MLP |
❗ Anomalías | Etiquetar datos anómalos (si puedes). | Detección de fraude: marcar transacciones normales y anómalas y entrenar un clasificador |
🖼 Imágenes | Extraer características manuales (como color, textura, tamaño, etc.) o redimensionar las imágenes y vectorizarlas. | Clasificación de imágenes de zapatos: usar un modelo CNN preentrenado para extraer features |
🔊 Audio | Extraer features de audio como MFCCs, espectrogramas, energía, pitch, etc., y construir vectores con esas estadísticas. | Detección de emociones en voz: usar MFCCs y energía para representar cada audio |
🧭 Guía paso a paso para construir tu baseline con un MLP
Sigue estos pasos para convertir tu idea o proyecto en un experimento funcional con un Perceptrón Multicapa (MLP), usando scikit-learn o Keras.
1️⃣ Define el objetivo de predicción
- ¿Tu problema es de clasificación o regresión?
- ¿Cuál es la variable que quieres predecir?
- Ejemplos:
- Clasificación: ¿Este artículo es de biología o matemáticas?
- Regresión: ¿Cuál será el consumo energético el próximo mes?
2️⃣ Identifica tu tipo de datos
- ¿Qué tipo de datos tienes?
- Texto
- Series temporales
- Datos tabulares
- Imágenes
- Audio
🔍 Revisa la tabla anterior para ver cómo transformar tus datos para usarlos con un MLP.
3️⃣ Preprocesa y vectoriza tus datos
- Normaliza tus valores si son numéricos (por ejemplo, entre 0 y 1).
- Si tienes texto, usa TF-IDF o BoW.
- Si tienes imágenes, vectorízalas (flatten).
- Si tienes secuencias, divide en ventanas y calcula estadísticas (media, std, etc.).
📌 Asegúrate de que cada fila sea un ejemplo y cada columna una característica.
4️⃣ Define el tipo de salida y la función de pérdida
- Clasificación binaria →
sigmoid
+binary_crossentropy
- Clasificación multiclase →
softmax
+categorical_crossentropy
- Regresión →
linear
+mean_squared_error
omean_absolute_error
⚠️ Si usas Keras
, recuerda convertir las etiquetas con to_categorical()
si usas softmax.
5️⃣ Construye tu MLP
- Decide cuántas capas ocultas y neuronas usar (ej. 2 capas de 128 y 64).
- Usa
relu
como activación oculta ysoftmax
osigmoid
según el caso. - Añade regularización (
Dropout
,L2
) si hay riesgo de sobreajuste.