Introducción a las redes neuronales con Scikit-Learn

I

¿Qué es una red neuronal?

Los seres humanos tienen la capacidad de identificar patrones dentro de la información accesible con un grado asombrosamente alto de precisión. Siempre que vea un automóvil o una bicicleta, podrá reconocer inmediatamente lo que son. Esto se debe a que hemos aprendido durante un período de tiempo cómo se ven un automóvil y una bicicleta y cuáles son sus características distintivas. Las redes neuronales artificiales son sistemas de computación que intentan imitar las capacidades de aprendizaje humano a través de una arquitectura compleja que se asemeja al sistema nervioso humano.

En este artículo, revisaremos brevemente qué son las redes neuronales, cuáles son los pasos computacionales que atraviesa una red neuronal (sin entrar en las complejas matemáticas detrás de ella) y cómo se pueden implementar utilizando Scikit-Learn, que es una biblioteca de IA popular para Python.

El sistema nervioso humano

El sistema nervioso humano consta de miles de millones de neuronas. Estas neuronas procesan colectivamente la información recibida de los órganos sensoriales, procesan la información y decide qué hacer en reacción a la información. Una neurona típica del sistema nervioso humano tiene tres partes principales: dendritas, núcleo y axones. La información que se pasa a una neurona es recibida por las dendritas. El núcleo se encarga de procesar esta información. La salida de una neurona pasa a otras neuronas a través del axón, que está conectado a las dendritas de otras neuronas más abajo en la red.

Perceptrones

Las redes neuronales artificiales se inspiran en la arquitectura de la red neuronal humana. La red neuronal más simple consta de una sola neurona y se llama perceptrón , como se muestra en la siguiente figura:

Un perceptrón tiene una capa de entrada y una neurona. La capa de entrada actúa como dendritas y es responsable de recibir las entradas. El número de nodos en la capa de entrada es igual al número de entidades en el dataset de entrada. Cada entrada se multiplica por un peso (que normalmente se inicializa con algún valor aleatorio) y los resultados se suman. Luego, la suma pasa a través de una función de activación . La función de activación de un perceptrón se asemeja al núcleo de la neurona del sistema nervioso humano. Procesa la información y produce una salida. En el caso de un perceptrón, esta salida es el resultado final. Sin embargo, en el caso de perceptrones multicapa, la salida de las neuronas de la capa anterior sirve como entrada a las neuronas de la capa anterior.

Red neuronal artificial (perceptrón multicapa)

Ahora que sabemos qué es un perceptrón de una sola capa, podemos extender esta discusión a los perceptrones de múltiples capas, o más comúnmente conocidas como redes neuronales artificiales. Un perceptrón de una sola capa puede resolver problemas simples donde los datos se pueden separar linealmente en an ‘n’ dimensiones, donde ‘n’ es el número de entidades en el conjunto de datos. Sin embargo, en el caso de datos separables de forma no lineal, la precisión del perceptrón de una sola capa disminuye significativamente. Los perceptrones multicapa, por otro lado, pueden trabajar de manera eficiente con datos separables de forma no lineal.

Los perceptrones multicapa, o más comúnmente denominados redes neuronales artificiales, son una combinación de múltiples neuronas conectadas en forma de red. Una red neuronal artificial tiene una capa de entrada, una o más capas ocultas y una capa de salida. Esto se muestra en la siguiente imagen:

Una red neuronal se ejecuta en dos fases: Feed-Forward y Back Propagation.

Feed-Forward

Los siguientes son los pasos realizados durante la fase de feed-forward:

  • Los valores recibidos en la capa de entrada se multiplican por los pesos. Se agrega un sesgo a la suma de las entradas y los pesos para evitar valores nulos.
  • Cada neurona en la primera capa oculta recibe diferentes valores de la capa de entrada dependiendo de los pesos y el sesgo. Las neuronas tienen una función de activación que opera sobre el valor recibido de la capa de entrada. La función de activación puede ser de muchos tipos, como función escalonada, función sigmoidea, función relu o función tanh . Como regla general, la función relu se usa en las neuronas de la capa oculta y la función sigmoidea se usa para la neurona de la capa de salida.
  • Las salidas de las neuronas de la primera capa oculta se multiplican por los pesos de la segunda capa oculta; los resultados se suman y pasan a las neuronas de las capas anteriores. Este proceso continúa hasta que se alcanza la capa exterior. Los valores calculados en la capa exterior son los resultados reales del algoritmo.

La fase de retroalimentación consta de estos tres pasos. Sin embargo, la salida prevista no es necesariamente correcta de inmediato; puede estar mal y debemos corregirlo. El propósito de un algoritmo de aprendizaje es hacer predicciones lo más precisas posible. Para mejorar estos resultados predichos, una red neuronal pasará por una fase de retropropagación. Durante la retropropagación, los pesos de las diferentes neuronas se actualizan de manera que la diferencia entre la salida deseada y la predicha sea lo más pequeña posible.

Propagación hacia atrás

La fase de retropropagación consta de los siguientes pasos:

  • El error se calcula cuantificando la diferencia entre la salida prevista y la salida deseada. Esta diferencia se llama “pérdida” y la función utilizada para calcular la diferencia se llama “función de pérdida”. Las funciones de pérdida pueden ser de diferentes tipos, por ejemplo, el error cuadrático medio o las funciones de entropía cruzada. Recuerde, las redes neuronales son algoritmos de aprendizaje supervisados que necesitan las salidas deseadas para un conjunto dado de entradas, que es lo que le permite aprender de los datos.
  • Una vez calculado el error, el siguiente paso es minimizar ese error. Para ello, se calcula la derivada parcial de la función de error con respecto a todos los pesos y sesgos. Esto se llama degradado decente. Las derivadas se pueden usar para encontrar la pendiente de la función de error. Si la pendiente es positiva, el valor de los pesos se puede reducir o si la pendiente es negativa, se puede aumentar el valor del peso. Esto reduce el error general. La función que se utiliza para reducir este error se denomina función de optimización.

Este ciclo de propagación de retroalimentación hacia adelante y hacia atrás se llama una “época”. Este proceso continúa hasta que se logra una precisión razonable. No existe un estándar para una precisión razonable, lo ideal sería que se esforzara por lograr una precisión del 100%, pero esto es extremadamente difícil de lograr para cualquier conjunto de datos no trivial. En muchos casos, se considera aceptable una precisión de más del 90%, pero realmente depende de su caso de uso.

Implementando una red neuronal con Scikit-Learn

Ahora sabemos qué son las redes neuronales y cuáles son los diferentes pasos que debemos realizar para construir una red neuronal simple y densamente conectada. En esta sección intentaremos construir una red neuronal simple que prediga la clase a la que pertenece una determinada planta de iris. Usaremos la biblioteca Scikit-Learn de Python para crear nuestra red neuronal que realiza esta tarea de clasificación. Las instrucciones de descarga e instalación de la biblioteca Scikit-Learn están disponibles en: http://scikit-learn.org/stable/install.html

Nota : Los scripts proporcionados con este tutorial se han ejecutado y probado en un cuaderno de Python Jupyter.

Conjunto de datos

El conjunto de datos que vamos a utilizar para este tutorial es el popular conjunto de datos Iris, disponible en https://archive.ics.uci.edu/ml/datasets/iris . Los detalles del conjunto de datos están disponibles en el enlace mencionado anteriormente.

Pasemos directamente al código. El primer paso es importar este conjunto de datos a nuestro programa. Para hacerlo, usaremos la biblioteca pandas de Python .

Ejecute el siguiente comando para cargar el conjunto de datos de iris en un marco de datos de Python:

import pandas as pd

# Location of dataset
url = "https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data"

# Assign colum names to the dataset
names = ['sepal-length', 'sepal-width', 'petal-length', 'petal-width', 'Class']

# Read dataset to pandas dataframe
irisdata = pd.read_csv(url, names=names)

El script anterior simplemente descarga los datos del iris, asigna los nombres, es decir, ‘sepal-length’, ‘sépal-width’, ‘petal-length’, ‘petal-width’ y ‘Class’ a las columnas del conjunto de datos, y luego lo carga en el irisdatamarco de datos.

Para ver cómo se ve realmente este conjunto de datos, ejecute el siguiente comando:

irisdata.head()

La ejecución del script anterior mostrará las primeras cinco filas de nuestro conjunto de datos, como se muestra a continuación:

de longitud sépalo
sépalo ancho de
pétalo de longitud
pétalo de ancho de
Clase

05.13.51.40.2Iris-setosa
14.93.01.40.2Iris-setosa
24.73.21.30.2Iris-setosa
34.63.11.50.2Iris-setosa
45.03.61.40.2Iris-setosa

Preprocesamiento

Puede ver que nuestro conjunto de datos tiene cinco columnas. La tarea es predecir la clase (que son los valores en la quinta columna) a la que pertenece la planta de iris, que se basa en la longitud del sépalo, el ancho del sépalo, la longitud del pétalo y el ancho del pétalo (las primeras cuatro columnas) . El siguiente paso es dividir nuestro conjunto de datos en atributos y etiquetas. Ejecute el siguiente script para hacerlo:

# Assign data from first four columns to X variable
X = irisdata.iloc[:, 0:4]

# Assign data from first fifth columns to y variable
y = irisdata.select_dtypes(include=[object])

Para ver cómo se yve, ejecute el siguiente código:

y.head()

Clase

0Iris-setosa
1Iris-setosa
2Iris-setosa
3Iris-setosa
4Iris-setosa

Puede ver que los valores de la yserie son categóricos. Sin embargo, las redes neuronales funcionan mejor con datos numéricos. Nuestra siguiente tarea es convertir estos valores categóricos en valores numéricos. Pero primero veamos cuántos valores únicos tenemos en nuestra yserie. Ejecute el siguiente script:

y.Class.unique()

Salida:

array(['Iris-setosa', 'Iris-versicolor', 'Iris-virginica'], dtype=object)

Tenemos tres clases únicas ‘Iris-setosa’, ‘Iris-versicolor’ e ‘Iris-virginica’. Convirtamos estos valores categóricos en valores numéricos. Para ello usaremos la LabelEncoderclase de Scikit-Learn .

Ejecute el siguiente script:

from sklearn import preprocessing
le = preprocessing.LabelEncoder()

y = y.apply(le.fit_transform)

Ahora, si vuelve a comprobar valores únicos en la yserie, verá los siguientes resultados:

array([0, 1, 2], dtype=int64)

Puede ver que los valores categóricos se han codificado en valores numéricos, es decir, 0, 1 y 2.

Prueba de tren dividida

Para evitar un ajuste excesivo , dividiremos nuestro conjunto de datos en divisiones de entrenamiento y de prueba. Los datos de entrenamiento se usarán para entrenar la red neuronal y los datos de prueba se usarán para evaluar el rendimiento de la red neuronal. Esto ayuda con el problema de sobreajuste porque estamos evaluando nuestra red neuronal con datos que no ha visto (es decir, en los que no se ha entrenado) antes.

Para crear divisiones de entrenamiento y prueba, ejecute el siguiente script:

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.20)

El script anterior divide el 80% del conjunto de datos en nuestro conjunto de entrenamiento y el otro 20% en datos de prueba.

Escala de funciones

Antes de hacer predicciones reales, siempre es una buena práctica escalar las características para que todas puedan evaluarse de manera uniforme. El escalado de características se realiza solo en los datos de entrenamiento y no en los datos de prueba. Esto se debe a que en el mundo real, los datos no se escalan y el propósito final de la red neuronal es hacer predicciones sobre datos del mundo real. Por lo tanto, intentamos mantener nuestros datos de prueba lo más reales posible.

El siguiente script realiza el escalado de características:

from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit(X_train)

X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)

Entrenamiento y predicciones

Y ahora finalmente es el momento de hacer lo que ha estado esperando, entrenar una red neuronal que realmente pueda hacer predicciones. Para hacer esto, ejecute el siguiente script:

from sklearn.neural_network import MLPClassifier
mlp = MLPClassifier(hidden_layer_sizes=(10, 10, 10), max_iter=1000)
mlp.fit(X_train, y_train.values.ravel())

Sí, con Scikit-Learn, puede crear una red neuronal con estas tres líneas de código, que manejan gran parte del trabajo por usted. Veamos qué está sucediendo en el script anterior. El primer paso es importar la MLPClassifierclase de la sklearn.neural_networkbiblioteca. En la segunda línea, esta clase se inicializa con dos parámetros.

El primer parámetro, hidden_layer_sizesse utiliza para establecer el tamaño de las capas ocultas. En nuestro script crearemos tres capas de 10 nodos cada una. No existe una fórmula estándar para elegir la cantidad de capas y nodos para una red neuronal y varía bastante según el problema en cuestión. La mejor manera es probar diferentes combinaciones y ver cuál funciona mejor.

El segundo parámetro MLPClassifierespecifica el número de iteraciones, o épocas, que desea que ejecute su red neuronal. Recuerde, una época es una combinación de un ciclo de fase de propagación de retroalimentación y retroalimentación.

Por defecto, la función de activación ‘relu’ se usa con el optimizador de costos ‘adam’. Sin embargo, puede cambiar estas funciones utilizando los parámetros activationy solver, respectivamente.

En la tercera línea, la fitfunción se usa para entrenar el algoritmo en nuestros datos de entrenamiento, es decir, X_trainy y_train.

El paso final es hacer predicciones sobre nuestros datos de prueba. Para hacerlo, ejecute el siguiente script:

predictions = mlp.predict(X_test)

Evaluar el algoritmo

Creamos nuestro algoritmo e hicimos algunas predicciones sobre el conjunto de datos de prueba. Ahora es el momento de evaluar qué tan bien funciona nuestro algoritmo. Para evaluar un algoritmo, las métricas más comúnmente utilizadas son una matriz de confusión, precisión, recuperación y puntuación f1. Los métodos confusion_matrixy classification_reportde la sklearn.metricsbiblioteca pueden ayudarnos a encontrar estas partituras. El siguiente script genera un informe de evaluación para nuestro algoritmo:

from sklearn.metrics import classification_report, confusion_matrix
print(confusion_matrix(y_test,predictions))
print(classification_report(y_test,predictions))

Este código anterior genera el siguiente resultado:

[[11  0  0]
   0  8  0]
   0  1 10]]
             precision   recall   f1-score   support
          0       1.00     1.00       1.00        11
          1       0.89     1.00       0.94         8
          2       1.00     0.91       0.95        11

avg / total       0.97     0.97       0.97        30

Puede ver en la matriz de confusión que nuestra red neuronal solo clasificó erróneamente una planta de las 30 plantas en las que probamos la red. Además, el puntaje f1 de 0.97 es muy bueno, dado que solo teníamos 150 instancias para entrenar.

Sus resultados pueden ser ligeramente diferentes de estos porque train_test_splitdivide aleatoriamente los datos en conjuntos de entrenamiento y prueba, por lo que nuestras redes pueden no haber sido entrenadas / probadas con los mismos datos. Pero, en general, la precisión también debería ser superior al 90% en sus conjuntos de datos.

Conclusión

En este artículo, brindamos una breve descripción general de qué son las redes neuronales y explicamos cómo crear una red neuronal muy simple que se entrenó en el conjunto de datos del iris. Le recomendaría que intente jugar con la cantidad de capas ocultas, las funciones de activación y el tamaño de la división de entrenamiento y prueba para ver si puede lograr mejores resultados que los que presentamos aquí.

 

About the author

Ramiro de la Vega

Bienvenido a Pharos.sh

Soy Ramiro de la Vega, Estadounidense con raíces Españolas. Empecé a programar hace casi 20 años cuando era muy jovencito.

Espero que en mi web encuentres la inspiración y ayuda que necesitas para adentrarte en el fantástico mundo de la programación y conseguir tus objetivos por difíciles que sean.

Add comment

Sobre mi

Últimos Post

Etiquetas

Esta web utiliza cookies propias para su correcto funcionamiento. Al hacer clic en el botón Aceptar, aceptas el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Más información
Privacidad