Índice del contenido[Esconder][Espectáculo]
El cerebro es comparable a las redes neuronales. Esta es la analogía que generalmente se usa para ayudar a alguien nuevo en el tema a comprender las ideas detrás del aprendizaje automático y las redes neuronales artificiales.
Debido a que hay varias capas de cálculos matemáticos y estadísticos detrás de escena, definir estas redes como una función matemática es un método más avanzado.
Esto es para las personas que realmente están interesadas en el aprendizaje automático y quieren ver cómo se escribe el código de la red neuronal de Python.
En este artículo, demostraremos cómo construir una red neuronal profunda (DNN) totalmente conectada desde cero en Python 3.
Una descripción general de la estructura de archivos para nuestro código de red neuronal Python
Habrá tres archivos creados aquí. El primero es el archivo nn.py simple, que se analizará en "Configuración de funciones auxiliares" y "Construcción de la red neuronal desde cero".
También tendremos un archivo llamado mnist loader.py para cargar los datos de prueba, como se describe en "Carga de datos MNIST".
Finalmente, tendremos un archivo llamado test.py que se lanzará en la terminal para probar nuestra red neuronal.
Este archivo se describe en detalle en "Ejecución de pruebas".
Instalación
La biblioteca NumPy Python debe descargarse para poder seguir este tutorial. Puede lograr esto usando el siguiente comando en la terminal:
Importación de módulos y configuración de la función auxiliar
Las únicas dos bibliotecas que necesitamos son aleatorias y NumPy, que importaremos de inmediato. Para los pesos iniciales de nuestra red neuronal, los barajaremos usando la biblioteca aleatoria.
Para acelerar nuestros cálculos, usaremos NumPy o np (por convención, a menudo se importa como np). Nuestras dos funciones auxiliares se realizarán después de nuestras importaciones. Dos funciones sigmoideas: una y prima sigmoidea.
La regresión logística clasificará los datos mediante la función sigmoide, mientras que la retropropagación calculará el delta o el gradiente mediante la función principal sigmoide.
Crear clase de red
La construcción de una red neuronal completamente vinculada es el único enfoque de esta sección. La clase de red abarcará todas las funciones que vienen después. La función Object() { [código nativo] } se creará inicialmente en nuestra clase de red.
La función Object() { [código nativo] } requiere un argumento, tamaños. La variable tamaños es una colección de valores numéricos que representa el número de nodos de entrada presentes en cada capa de nuestra red neuronal.
Inicializamos cuatro propiedades en nuestro método __init__. Las variables de entrada, tamaños, se utilizan para establecer la lista de tamaños de capa y el número de capas, número de capas, respectivamente.
El primer paso es asignar aleatoriamente los sesgos iniciales de nuestra red a cada capa que sigue a la capa de entrada.
Finalmente, cada enlace entre las capas de entrada y salida tiene sus pesos generados aleatoriamente. Np.Random.Randn() proporciona una muestra aleatoria extraída de la distribución normal para el contexto.
Función de avance
En una red neuronal, la función feedforward envía la información. Esta función requerirá un argumento, a, que indica el vector de activación actual.
Esta función estima las activaciones en cada capa iterando sobre todos los sesgos y pesos en la red. La respuesta dada es la predicción, que son las activaciones de la última capa.
Descenso de gradiente de mini lotes
El caballo de batalla de nuestra clase Network es Gradient Descent. En esta versión, utilizamos el descenso de gradiente de mini lotes (estocástico), una variación modificada del descenso de gradiente.
Esto indica que se utilizará un pequeño lote de puntos de datos para actualizar nuestro modelo. A este método se le pasan cuatro argumentos obligatorios y uno opcional. Las cuatro variables requeridas son el conjunto de datos de entrenamiento, el número de épocas, el tamaño de los mini lotes y la tasa de aprendizaje (eta).
Los datos de prueba están disponibles a pedido. Proporcionaremos datos de prueba cuando finalmente evalúemos esta red. El número de muestras en esta función se establece inicialmente en la longitud de la lista una vez que los datos de entrenamiento se han transformado en un tipo de lista.
También aplicamos el mismo proceso para probar los datos que se proporcionan. Esto se debe a que, en lugar de devolvernos como listas, en realidad son zips de listas. Cuando carguemos las muestras de datos MNIST más tarde, aprenderemos más sobre esto.
Si podemos asegurarnos de que proporcionamos ambos tipos de datos como listas, entonces esta conversión de tipo no es necesariamente esencial.
Una vez que tenemos los datos, repasamos las épocas de entrenamiento en un bucle. Un período de entrenamiento es solo una ronda de entrenamiento de redes neuronales. Primero barajamos los datos en cada época para garantizar la aleatoriedad antes de hacer una lista de mini lotes.
La función de actualización de mini lotes, que se analiza a continuación, se llamará para cada mini lote. La precisión de la prueba también se devolverá si los datos de la prueba están disponibles.
Función auxiliar de derivada de costos
Desarrollemos primero una función de ayuda llamada derivada de costos antes de crear realmente el código de retropropagación. Si cometemos un error en nuestra capa de salida, la función derivada de costos lo mostrará.
Requiere dos entradas: la matriz de activaciones de salida y las coordenadas y de los valores de salida anticipados.
Función de retropropagación
Nuestro vector de activación actual, activación, así como cualquier otro vector de activación, activaciones y vectores z, zs, deben tenerse en cuenta. Primero se activa una capa llamada capa de entrada.
Revisaremos cada sesgo y peso después de colocarlos. Cada bucle implica calcular el vector z como el producto punto de los pesos y la activación, agregarlo a la lista de zs, volver a calcular la activación y agregar la activación actualizada a la lista de activaciones.
Finalmente, las matemáticas. El delta, que es igual al error de la capa anterior multiplicado por el primo sigmoide del último elemento de los vectores zs, se calcula antes de comenzar nuestro paso hacia atrás.
La última capa de nabla b está configurada para ser el delta, y la capa final de nabla w está configurada para ser el producto punto del delta y la penúltima capa de activaciones (transpuestas para que podamos hacer los cálculos) .
Procedemos como antes, comenzando con la segunda capa y finalizando con la última, y repetimos el proceso después de completar estas últimas capas. Luego, las nablas se devuelven como una tupla.
Actualización del descenso de gradiente de minilotes
Nuestro método SGD (descenso de gradiente estocástico) anterior incorpora actualización de mini lotes. Dado que se utiliza en SGD pero también requiere backprop, debatí dónde poner esta función.
Finalmente, tomé la decisión de publicarlo aquí. Comienza generando 0 vectores de los nablas de sesgos y pesos, tal como lo hizo nuestra función backprop.
Requiere el mini-lote y la tasa de aprendizaje eta como sus dos entradas. En el mini lote, luego usamos la función backprop para obtener el delta de cada matriz nabla para cada entrada, x, y salida, y. Las listas nabla se actualizan luego con estos deltas.
Finalmente, usamos la tasa de aprendizaje y las nablas para actualizar los pesos y sesgos de la red. Cada valor se actualiza al valor más reciente, menos la tasa de aprendizaje, se multiplica por el tamaño del minilote y luego se suma al valor nabla.
Evaluar función
La función de evaluación es la última que necesitamos escribir. Los datos de prueba son la única entrada para esta función. En esta función, solo comparamos las salidas de la red con el resultado esperado, y. Al alimentar la entrada, x, hacia adelante, se determinan las salidas de la red.
Código Completo
Cuando combinamos todo el código, así es como aparece.
Prueba de red neuronal
Cargando datos MNIST
La Datos MNIST está en formato .pkl.gz, que abriremos usando GZIP y cargaremos con pickle. Escribamos un método rápido para cargar estos datos como una tupla de tamaño tres, dividida en datos de entrenamiento, validación y prueba.
Para que nuestros datos sean más fáciles de administrar, escribiremos otra función para codificar la y en una matriz de 10 elementos. La matriz será solo 0, excepto un 1 que coincida con el dígito correcto de la imagen.
Usaremos los datos básicos de carga y un método de codificación en caliente para cargar nuestros datos en un formato legible. Se escribirá otra función que convertirá nuestros valores x en una lista de tamaño 784, que coincida con los 784 píxeles de la imagen, y nuestros valores y en su única forma vectorial codificada en caliente.
Luego combinaremos los valores de x e y de manera que un índice coincida con el otro. Esto se aplica a los conjuntos de datos de entrenamiento, validación y prueba. Luego devolvemos los datos modificados.
Ejecutando pruebas
Haremos un nuevo archivo llamado "cargador mnist" que importará tanto la red neuronal que establecimos previamente (simple nn) como el cargador del conjunto de datos MNIST antes de comenzar la prueba.
En este archivo, todo lo que tenemos que hacer es importar los datos, construir una red con un tamaño de capa de entrada de 784 y un tamaño de capa de salida de 10, ejecutar la función SGD de la red en los datos de entrenamiento y luego probarla usando los datos de prueba.
Tenga en cuenta que para nuestra lista de capas de entrada, no importa cuáles sean los números entre 784 y 10. Podemos cambiar las otras capas como queramos; solo los tamaños de entrada y salida son fijos.
No son necesarias tres capas; podríamos usar cuatro, cinco o incluso solo dos. Diviértete experimentando con él.
Conclusión
Aquí, usando Python 3, creamos una red neuronal desde cero. Junto con las matemáticas de alto nivel, también discutimos los detalles de la implementación.
Comenzamos implementando funciones auxiliares. Para que las neuronas funcionen, las funciones principales sigmoideas y sigmoideas son cruciales. Luego pusimos en práctica la función feedforward, que es el proceso fundamental para alimentar datos a la red neuronal.
A continuación, creamos la función de descenso de gradiente en Python, el motor que impulsa nuestra red neuronal. Para ubicar los "mínimos locales" y optimizar sus pesos y sesgos, nuestra red neuronal utiliza el descenso de gradiente. Creamos la función de retropropagación usando descenso de gradiente.
Al enviar actualizaciones cuando los resultados no coinciden con las etiquetas adecuadas, esta función permite que la red neuronal "aprenda".
Finalmente, ponemos nuestro nuevo Python red neural a la prueba utilizando el conjunto de datos MNIST. Todo funcionó sin problemas.
¡Feliz codificación!
Deje un comentario