Resolviendo Ecuaciones Matemáticas Básicas Usando RNN [Con Ejemplo de Codificación]
Publicado: 2020-12-07Si la vida te da RNN, haz una calculadora
Una red neuronal recurrente es una de las redes neuronales artificiales clásicas, donde las conexiones entre los nodos forman un gráfico dirigido secuencial. Los RNN son famosos por aplicaciones como reconocimiento de voz, reconocimiento de escritura a mano, etc. debido a su memoria de estado interna para procesar secuencias de longitud variable.
Los RNN se clasifican además en dos tipos. El primero es un impulso finito cuya red neuronal tiene la forma de un gráfico acíclico dirigido donde un nodo puede conectarse con uno o más nodos que están adelante sin un ciclo visible en la red. Otro es un impulso infinito cuya red neuronal tiene la forma de un gráfico cíclico dirigido que no se puede desenrollar en una red neuronal de avance.
Tabla de contenido
¿Que vamos a hacer?
Construyamos un modelo que prediga el resultado de una expresión aritmética. Por ejemplo, si introduzco '11+88', entonces el modelo debería predecir la siguiente palabra en la secuencia como '99'. La entrada y la salida son una secuencia de caracteres ya que un RNN trata con datos secuenciales.
Ahora, diseñar la arquitectura del modelo parece una tarea sencilla en comparación con la recopilación de conjuntos de datos. La generación de datos o la recopilación de conjuntos de datos es una tarea extenuante porque los modelos de IA con avidez de datos requieren una buena cantidad de datos para lograr una precisión aceptable.
Así que este modelo se puede implementar en 6 pasos básicos:

- Generando datos
- Construyendo un modelo
- Vectorizar y desvectorizar los datos
- Hacer un conjunto de datos
- Entrenando al modelo
- Probando el modelo
Antes de sumergirnos en la implementación del modelo, importemos todas las bibliotecas necesarias.
importar numpy como np importar tensorflow como tf de tensorflow.keras.models import Sequential de tensorflow.keras.layers import Dense, Dropout, SimpleRNN, RepeatVector, TimeDistributed desde tensorflow.keras.callbacks import EarlyStopping, LambdaCallback de termcolor importación coloreada |
1. Generación de datos
Definamos una cadena de caracteres que contenga todos los caracteres que necesitamos para escribir una ecuación aritmética básica. Entonces, la cadena consta de todos los caracteres del 0 al 9 y todos los operadores aritméticos como /, *, +, -, .(decimal).
No podemos introducir directamente los datos numéricos en nuestro modelo, necesitamos pasar los datos en forma de tensores. Convertir la cadena en los datos en un vector codificado one-hot nos dará un rendimiento de modelo optimizado. Un vector codificado one-hot es una matriz con una longitud igual a la longitud de nuestra cadena de caracteres, cada vector one-hot tiene unos solo en el índice respectivo de carácter presente en cada cadena.
Por ejemplo, digamos que nuestra cadena de caracteres es '0123456789', y si queremos codificar una cadena como '12', entonces el vector único sería [ [0,1,0,0,0,0,0,0 ,0,0], [0,0,1,0,0,0,0,0,0,0] ]. Para hacer eso, necesitamos crear dos diccionarios con un índice como claves y caracteres como valores y el otro como viceversa.
char_string = ' 0123456789/*+-. ' num_chars = len (char_string) character_to_index = dict ((c, i) para i, c en enumerar (char_string)) index_to_character = dict ((i, c) para i, c en enumerar (char_string)) |
Ahora escribamos una función que devuelva una ecuación aritmética aleatoria junto con el resultado de esa ecuación.
definición división (n, d): devuelve n / d si d != 0 sino 0 def datagen (): random1 = np.random.randint(bajo = 0 , alto = 100 ) random2 = np.random.randint(bajo = 0 , alto = 100 ) op = np.random.randint(bajo = 0 , alto = 4 ) si op == 1 : arit = cadena (aleatorio1) + ' + ' + cadena (aleatorio2) res = cadena (aleatorio1 + aleatorio2) elif op == 1 : arit = cadena (aleatorio1) + ' – ' + cadena (aleatorio2) res = cadena (aleatorio1 – aleatorio2) elif op == 2 : arit = cadena (aleatorio1) + ' * ' + cadena (aleatorio2) res = cadena (aleatorio1 * aleatorio2) más : arit = cadena (aleatoria1) + ' / ' + cadena (aleatoria2) res = str ( ronda (división (aleatorio1, aleatorio2), 2 )) volver aritm, res |
Lea también: Ideas interesantes para proyectos de redes neuronales
2. Construcción de un modelo
El modelo tendrá un codificador y un decodificador. El codificador es un modelo RNN simple con forma de entrada como (Ninguno, num_chars) y 128 unidades ocultas, la razón por la que elegimos unidades ocultas como 32, 64, 128, etc. es por el mejor rendimiento de la CPU o GPU con unidades ocultas como potencias de 2.
Nuestro codificador será una red totalmente conectada y la salida de estos se retroalimentará a la red, así es como funciona un RNN. Una capa RNN usa la activación 'tanh' por defecto, no vamos a cambiar porque se ajusta mejor al codificador. La salida de esta capa será un solo vector y para lograr un solo vector de toda la salida usaremos la capa RepeatVector() con el número requerido de veces como parámetro.
Ahora el vector de salida tendrá la esencia de la entrada dada, y este vector se alimentará al decodificador.
El decodificador se compone de una capa RNN simple y esto generará la secuencia de salida, ya que necesitamos que la capa RNN devuelva la secuencia predicha, vamos a marcar las 'secuencias de retorno' como verdaderas. Al asignar 'return_sequences' como Verdadero, la capa RNN devolverá la secuencia predicha para cada paso de tiempo (muchos a muchos RNN).
La salida de esta capa RNN se alimenta a una capa densa con el número de unidades ocultas 'num_chars' y usaremos la activación softmax ya que necesitamos la probabilidad de cada carácter. Antes de implementar una capa densa, debemos reducir esta capa a una capa distribuida en el tiempo porque necesitamos implementar la capa densa para la salida de cada paso de tiempo.
unidades_ocultas = 128 max_time_steps = 5 #estamos codificando la salida para que sea de 5 caracteres modelo de definición (): modelo = Secuencial() model.add(SimpleRNN(hidden_units, input_shape = ( Ninguno , num_chars))) modelo.add(RepetirVector(max_time_steps)) modelo.add(SimpleRNN(unidades_ocultas, secuencias_retorno = Verdadero )) modelo.add(TiempoDistribuido(Dense(num_chars, activación = ' softmax ' ))) modelo de vuelta modelo = modelo() Resumen Modelo() model.compile(pérdida = ' categorical_crossentropy ' , optimizador = ' adam ' , métricas = [ ' precisión ' ]) |
La arquitectura del modelo será como se muestra arriba.
Debe leer: Tutorial de redes neuronales
3. Vectorizar y Desvectorizar los Datos
Definamos funciones para vectorizar y desvectorizar los datos.
Aquí está la función para vectorizar la expresión aritmética y el resultado juntos.
def vectorizar (arith, res): x = np.ceros((max_time_steps, num_chars)) y = np.ceros((max_time_steps, num_chars)) x_remaining = max_time_steps – len (arith) ![]() y_remaining = max_time_steps – len (res) para i, c en enumerar (arith): x[x_restante + i, carácter_a_índice[c]] = 1 para i en rango (x_remaining): x[i, carácter_a_índice[ ' 0 ' ]] = 1 para i, c en enumerar (res): y[y_restante + i, carácter_a_índice[c]] = 1 para i en el rango (y_remaining): y[i, carácter_a_índice[ ' 0 ' ]] = 1 devuelve x, y |
Del mismo modo, aquí está la función para desvectorizar la cadena. Dado que la salida que recibimos es un vector de probabilidades, usaremos np.argmax() para elegir el carácter con la probabilidad más alta. Ahora el diccionario index_to_character se usa para rastrear el carácter en ese índice.
def desvectorizar (entrada): res = [index_to_character[np.argmax(vec)] para i, vec en enumerar ( entrada )] volver ' ' .unirse(res) |
Ahora, la restricción que tenemos con la función 'desvectorizar' es que va a rellenar los caracteres finales con ceros. Por ejemplo, si el vector de entrada es ('1-20', '-19'), la salida desvectorizada será ('01-20', '00-19'). Tenemos que ocuparnos de estos ceros extra acolchados. Escribamos una función para quitar la cadena.
eliminación de definición (entrada): bandera = falso salida = ' ' para c en la entrada : si no marca y c == ' 0 ' : Seguir si c == ' + ' o c == ' – ' o c == ' * ' o c == ' / ' o c == ' . ' : bandera = falso más : bandera = Verdadero salida += c salida de retorno |
4. Hacer un conjunto de datos
Ahora que terminamos de definir una función para generar los datos, usemos esa función y hagamos un conjunto de datos con muchos de estos pares (expresión aritmética, resultado).
def create_dataset (núm_ecuaciones): x_train = np.zeros((num_ecuaciones, max_time_steps, num_chars)) y_train = np.zeros((num_ecuaciones, max_time_steps, num_chars)) para i en rango (num_ecuaciones): e, l = generador de datos() x, y = vectorizar(e, l) tren_x[i] = x y_tren[i] = y volver x_tren, y_tren |
5. Entrenando al modelo
Vamos a crear un conjunto de datos de 50 000 muestras, que es un número justo para entrenar nuestro modelo de hambre de datos, usaremos el 25 % de estos datos para la validación. Además, creemos una devolución de llamada para la interrupción del entrenamiento inteligente si la precisión permanece sin cambios durante 8 épocas. Esto se puede lograr configurando el parámetro de paciencia en 8.

tren_x, tren_y = crear_conjunto de datos ( 50000 ) registrador_simple = LambdaCallback ( on_epoch_end = lambda e, l: print ( ' {:.2f} ' .format(l[ ' val_accuracy ' ]), end = ' _ ' ) ) early_stopping = EarlyStopping(monitor = ' val_loss ' , paciencia = 8 ) model.fit(x_train, y_train, epochs = 100 , validation_split = 0.25 , detallado = 0 , devoluciones de llamada = [simple_logger, early_stopping]) |
6. Prueba del modelo
Ahora probemos nuestro modelo creando un conjunto de datos del tamaño 30.
x_test, y_test = create_dataset(núm_ecuaciones = 20 ) preds = modelo.predecir(x_test) secuencia_completa_acc = 0 para i, pred en enumerar (preds): pred_str = quitar (desvectorizar (pred)) y_test_str = eliminación (desvectorizar (y_test [i])) x_test_str = eliminación (desvectorizar (x_test [i])) col = ' verde ' if pred_str == y_test_str else ' rojo ' full_seq_acc += 1 / len (preds) * int (pred_str == y_test_str) outstring = ' Entrada: {}, Salida: {}, Predicción: {} ' .format(x_test_str, y_test_str, pred_str) imprimir (coloreado (outstring, col)) print ( ' \n Precisión de secuencia completa: {:.3f} % ' .format( 100 * full_seq_acc)) |
La salida será la siguiente
Podemos ver que la precisión es un poco pobre aquí, de todos modos podemos optimizarla modificando algunos hiperparámetros como el número de unidades ocultas, división de validación, número de épocas, etc.
Conclusión
Entendimos el flujo de trabajo básico de una RNN, entendimos que las RNN son más adecuadas para datos secuenciales, generamos un conjunto de datos de ecuaciones aritméticas aleatorias, desarrollamos un modelo secuencial para predecir el resultado de una expresión aritmética básica, entrenamos ese modelo con el conjunto de datos que hemos creado y finalmente probado ese modelo con un pequeño conjunto de datos que el modelo nunca antes había visto.
Si está interesado en obtener más información sobre RNN, aprendizaje automático, consulte el Diploma PG en aprendizaje automático e IA de IIIT-B y upGrad, que está diseñado para profesionales que trabajan y ofrece más de 450 horas de capacitación rigurosa, más de 30 estudios de casos y asignaciones, Estado de ex alumnos de IIIT-B, más de 5 proyectos prácticos finales y asistencia laboral con las mejores empresas.
¿Cuáles son los diferentes tipos de redes neuronales en el aprendizaje automático?
En el aprendizaje automático, las redes neuronales artificiales son básicamente modelos computacionales que han sido diseñados para parecerse al cerebro humano. Existen diferentes tipos de redes neuronales artificiales que emplea el aprendizaje automático en función del cálculo matemático que debe lograrse. Estas redes neuronales son un subconjunto de diferentes técnicas de aprendizaje automático que aprenden de los datos de diferentes maneras. Algunos de los tipos de redes neuronales más utilizados son: red neuronal recurrente: memoria a largo plazo a corto plazo, red neuronal feedforward: neurona artificial, red neuronal de función de base radial, red neuronal autoorganizada de Kohonen, red neuronal convolucional y red neuronal modular. entre otros.
¿Cuáles son las ventajas de una red neuronal recurrente?
Las redes neuronales recurrentes se encuentran entre las redes neuronales artificiales más utilizadas en el aprendizaje profundo y el aprendizaje automático. En este tipo de modelo de red neuronal, el resultado obtenido en el paso anterior se alimenta como entrada al paso siguiente. Una red neuronal recurrente tiene varias ventajas, como: puede retener cada bit de información a lo largo del tiempo, incluidas sus entradas anteriores, lo que la hace ideal para la predicción de series temporales. Este tipo es la mejor instancia de memoria larga-corta. Además, las redes neuronales recurrentes proporcionan una vecindad de píxeles constructiva mediante el uso de capas convolucionales.
¿Cómo se emplean las redes neuronales en aplicaciones del mundo real?
Las redes neuronales artificiales son una parte integral del aprendizaje profundo, que nuevamente es una rama súper especializada del aprendizaje automático y la inteligencia artificial. Las redes neuronales se utilizan en diferentes industrias para lograr varios objetivos críticos. Algunas de las aplicaciones del mundo real más interesantes de las redes neuronales artificiales incluyen pronósticos del mercado de valores, reconocimiento facial, autopilotaje de alto rendimiento y diagnóstico de fallas en la industria aeroespacial, análisis de ataques armados y ubicación de objetos en el sector de defensa, procesamiento de imágenes, descubrimiento de fármacos y detección de enfermedades en el sector sanitario, verificación de firma, análisis de escritura a mano, previsión meteorológica y previsión de tendencias en redes sociales, entre otros.