Categorías
Deep Learning

Derivación de retropropagación de redes neuronales

He pasado unos días trabajando en redes neuronales como CNN y RNN. Esta publicación muestra mis notas sobre la derivación de la retropropagación de la red neuronal. La derivación de la retropropagación es uno de los algoritmos más complicados del aprendizaje automático. Hay muchos recursos para comprender cómo calcular gradientes mediante retropropagación. Pero en mi opinión, la mayoría de ellos carece de un ejemplo simple para demostrar el problema y recorrer el algoritmo.

1. Una red neuronal simple

El siguiente diagrama muestra la estructura de una red neuronal simple utilizada en esta publicación. La dimensión de entrada (dimensión de la característica) es 2, el tamaño de la capa oculta es 3 y la dimensión de salida es 1. Es bastante intuitivo calcular la predicción alimentando la red. En el siguiente diagrama, en lugar de usar números reales, utilizo cuadros para ilustrar la transformación de dimensión a través de las capas.

11

2. Función de costo

Una función de costo refleja la distancia entre la verdad del terreno y los valores predichos. Una función de costo simple es una función de error de suma al cuadrado:

12

El costo J es una función de W. Entonces el objetivo es encontrar lo mejor W que produce el costo más bajo J. La función de costo se define a menudo de una manera matemáticamente conveniente. Aparentemente, podría haber múltiples formas de evaluar la distancia entre la verdad y los valores predichos. Cada función de costo tiene sus propios casos aplicables. Puede echar un vistazo esta publicación para ver algunas otras funciones de costos.

En un espacio bidimensional simplificado, la relación entre el costo J y W puede verse como:
2

Seguimos actualizando W, de modo que el costo se mueva al punto más bajo. El algoritmo se llama descenso de gradiente. Calculando las derivadas parciales de W, podemos seguir actualizando W y hacer que el costo baje cada vez más hasta llegar al mínimo.

3

En un escenario real, sería un espacio multidimensional (difícil de visualizar aquí). Cada movimiento conducirá a una dirección en un espacio multidimensional.

3. Cálculo de derivada parcial

Primero calculemos las derivadas parciales de la segunda capa. W.

4

5

Podemos ver que esos valores solo se ven afectados por los datos de entrada que se alimentan a la red. (Tenga en cuenta que f ‘(z) se puede simplificar aún más).

De manera similar, podemos calcular las derivadas parciales de W para la primera capa.

6

7

Estos valores también se pueden calcular en función de los datos de entrada que se alimentan a la red.

Una vez que sepamos cómo actualizar W, usamos el nuevo W y hacer descenso de gradiente una y otra vez, hasta llegar al punto óptimo.

4. Visualización del cálculo

Tomemos los pesos de la segunda capa, por ejemplo.

Primero podemos ver cómo cada muestra contribuye al gradiente y luego ver cómo las 5 muestras de entrenamiento contribuyen al gradiente.

8

La dimensión del resultado es 3 por 1, que es la misma de W2.

Categorías
Deep Learning

Configurar el entorno de desarrollo para el aprendizaje profundo

El aprendizaje profundo ha ganado mucha atención porque es particularmente bueno en algún tipo de aprendizaje que es muy útil para aplicaciones del mundo real. Ejecutar algunos ejemplos simples es una buena manera de comenzar a aprender esta técnica. Configurar un entorno de desarrollo es el primer paso.

Hay diferentes formas de configurar el entorno para el aprendizaje profundo. Puede hacerlo en Windows, Mac OS o Linux. Recomiendo encarecidamente desarrollar en Mac OS o Linux, porque simplemente la mayoría de las personas en esta área usan Linux o Mac OS. Esta publicación muestra una forma sencilla de hacerlo en Ubuntu.

1. Instale Anaconda

La guía actualizada para instalar Anaconda se puede encontrar en el sitio oficial. La URL es: https://docs.continuum.io/anaconda/install/linux.html

De forma predeterminada, se instalará en / home / yourname /.

2. Cree un entorno virtual

El lenguaje Python tiene muchas versiones, como 2.6, 2.7 y 3.7. Muy a menudo, los proyectos de código abierto dependen de diferentes idiomas y versiones de paquetes. Es fácil estropear el entorno de desarrollo. La forma correcta de manejar esta situación es crear un entorno virtual separado para proyectos que dependan de los mismos paquetes y versiones. Todo lo que se instala en un entorno virtual solo afecta a ese entorno, pero a cualquier otra cosa. Básicamente, un entorno virtual es un directorio independiente.

Cree un entorno virtual con el nombre «p3» y especifique la versión del lenguaje Python como 3.7.

conda create -n p3 python=3.7 

Active el entorno virtual recién creado «p3».

source activate p3

Instale paquetes de uso común para el aprendizaje automático.

pip install numpy
pip install pandas
pip install scikit-learn
pip install seaborn

Instale paquetes para el aprendizaje profundo.

pip install tensorflow
pip install keras

También puede desactivar el entorno virtual.

source deactivate p3

3. Instale PyCharm

Descarga la versión comunitaria aquí: https://www.jetbrains.com/pycharm/download/#section=linux

Cópielo en el directorio / opt /.

sudo cp pycharm-community-2017.1.4.tar.gz /opt/

Descomprime el archivo.

cd /opt/
tar -xzvf pycharm-community-2017.1.4.tar.gz

Ejecute el script para comenzar.

. /opt/pycharm-community-2017.1.4/bin/pycharm.sh

Ahora, puede realizar un aprendizaje profundo para descubrir sus propias cosas interesantes.

Categorías
Deep Learning

¿Cómo seleccionar la herramienta adecuada para el aprendizaje profundo?

Para los principiantes en aprendizaje profundo, elegir la herramienta adecuada puede ayudar a aprender. Hay muchas herramientas diferentes disponibles y es confuso seleccionar una al principio. El siguiente diagrama muestra las herramientas más populares.

Tensorflow desarrollado por Google, CNTK por Microsoft y Theano son todas bibliotecas desarrolladas para el aprendizaje profundo que facilitan el cálculo de retropropagación mediante GPU. No son difíciles de usar, pero comparados con Keras siguen siendo muy complicados. Keras es solo una interfaz para usar las bibliotecas de aprendizaje profundo subyacentes. Usar Keras es tan simple como jugar a Lego. Sugiero que los principiantes comiencen con Keras. Porque puede obtener rápidamente una idea de lo que puede hacer el aprendizaje profundo y motivarse para realizar proyectos más interesantes.

Categorías
Deep Learning

Diferentes tipos de estructuras de redes neuronales recurrentes

La siguiente tabla resume las diferentes estructuras de redes neuronales recurrentes y los problemas que son buenos para resolver. Los diagramas de estructura son bastante intuitivos para comprender qué tipo de estructura de red es adecuada para su problema.

Estructura de red Problemas aplicables Ejemplos de
Muchos a uno
rnn muchos a una estructura
Problema de series de tiempo Predicción de stock
Muchos a muchos
rnn estructura de muchos a muchos
Problema de predicción secuencia a secuencia Programa de IA en mi publicación anterior
Cambió de muchos a muchos
rnn cambió la estructura de muchos a muchos
problemas de traducción y chatbot Traducción de idiomas y chatbot

Categorías
Deep Learning

Cree un programador de inteligencia artificial utilizando una red neuronal recurrente (1)

Las redes neuronales recurrentes (RNN) están ganando mucha atención en los últimos años porque se han mostrado muy prometedoras en muchas tareas de procesamiento del lenguaje natural. A pesar de su popularidad, hay un número limitado de tutoriales que explican cómo implementar una aplicación sencilla e interesante utilizando herramientas de última generación. En esta serie, utilizaremos una red neuronal recurrente para entrenar a un programador de IA, que puede escribir código Java como un programador real (con suerte). Se cubrirá lo siguiente:

1. Construyendo un programador de IA simple (esta publicación)
2. Mejora del programador de IA: uso de tokens
3. Mejora del programador de IA: uso de diferentes estructuras de red

Esta publicación muestra los pasos para construir una red neuronal LSTM y usarla para generar código Java. Si sigue la publicación, ejecutar el código está a solo un clic de distancia. (Pero como primer paso, deberá configurar el entorno de desarrollo para el aprendizaje profundo. Puede seguir esta publicación (http://www.programcreek.com/2017/01/set-up-development-environment-for- deep-learning /) que muestra la mejor y más sencilla forma de configurar el entorno de trabajo.

El objetivo de esta serie es proporcionar un punto de entrada para el aprendizaje profundo. Construir un modelo de aprendizaje profundo es como pintar una pintura al óleo. Puede seguir mejorando el modelo tan pronto como comience y haga funcionar su primer modelo.

1. Obtener los datos brutos de entrenamiento

Estoy usando el código fuente de JDK como datos de entrenamiento. Está disponible aquí. Estamos construyendo un modelo de predicción secuencia a secuencia y la secuencia de entrada es la secuencia de caracteres. Cada archivo .java se escanea y se agrega en un archivo llamado «jdk-chars.txt». Además, los comentarios se ignoran, porque queremos que el programador de IA aprenda a codificar. Los comentarios hacen que los datos sean ruidosos. (revisa esta publicación para ver cómo eliminar comentarios). Para su conveniencia, el archivo agregado se incluye en el repositorio de GitHub de este proyecto. Puede encontrar el enlace al final de esta publicación.

El siguiente código lee el archivo jdk-chars.txt y lo corta para que se ajuste a la capacidad de hardware de mi escritorio. En mi caso, solo usé el 20% del código como se muestra en el código.

path = "./jdk-chars.txt"
text = open(path).read()
slice = len(text)/5
slice = int(slice)
 
# slice the text to make training faster
text = text[:slice]
 
print('# of characters in file:', len(text))

2. Índice de construcción para abordar los personajes

Las entradas de LSTM solo pueden comprender números, por lo que primero debemos asignar un número entero único a cada carácter.

Por ejemplo, si hay 65 caracteres únicos en el código, asignamos un número a cada uno de los 65 caracteres. El siguiente código crea un diccionario con entradas como [ “{” : 0 ] [ “a” : 1 ], …]. El diccionario inverso también se genera para decodificar la salida de LSTM.

chars = sorted(list(set(text)))
print('# of unique chars:', len(chars))
char_indices = dict((c, i) for i, c in enumerate(chars))
indices_char = dict((i, c) for i, c in enumerate(chars))

3. Preparar las secuencias de entrenamiento con etiquetas

A continuación, necesitamos preparar datos de entrenamiento con etiquetas. Una X es una secuencia con una longitud específica que definimos (40 en mi caso) e y es el siguiente carácter de la secuencia.
Por ejemplo, de la siguiente línea:

int weekOfYear = isSet(WEEK_OF_YEAR) ? field[MAX_FIELD + WEEK_OF_YEAR] : 1; ... ... 

Una muestra de X es

int weekOfYear = isSet(WEEK_OF_YEAR) ? fi

y la y es el siguiente carácter

e

Aquí cortamos el texto en secuencias redundantes de 40 caracteres.

NUM_INPUT_CHARS = 40
STEP = 3
sequences = []
next_chars = []
 
for i in range(0, len(text) - NUM_INPUT_CHARS, STEP):
    sequences.append(text[i: i + NUM_INPUT_CHARS])
    next_chars.append(text[i + NUM_INPUT_CHARS])
 
print('# of training samples:', len(sequences))

Estamos intentando construir una red con una estructura como esta:
lstm

4. Vectorización de datos de entrenamiento

Una vez que se preparan los datos de entrenamiento, es necesario convertirlos en vectores. Como hemos preparado char_indices y indices_char en el segundo paso, el siguiente código puede convertir fácilmente nuestros datos de entrenamiento en vectores con codificación one-hot. Por ejemplo, el carácter con índice 11 sería el vector de todos los ceros y un 1 en la posición 11.

print('Vectorize training data')
X = np.zeros((len(sequences), NUM_INPUT_CHARS, len(chars)), dtype=np.bool)
y = np.zeros((len(sequences), len(chars)), dtype=np.bool)
for i, sequence in enumerate(sequences):
    for t, char in enumerate(sequence):
        X[i, t, char_indices[char]] = 1
    y[i, char_indices[next_chars[i]]] = 1

5. Construcción de un modelo LSTM de una sola capa

El siguiente código define la estructura de la red neuronal. La red contiene una capa de LSTM con 128 unidades ocultas. los input_shape El parámetro especifica la longitud de la secuencia de entrada (NUM_INPUT_CHARS) y la dimensión de la entrada en cada momento (es decir, el tamaño de los caracteres únicos).

print('Build model...')
model = Sequential()
model.add(LSTM(128, input_shape=(NUM_INPUT_CHARS, len(chars))))
model.add(Dense(len(chars)))
model.add(Activation('softmax'))
 
optimizer = RMSprop(lr=0.01)
model.compile(loss='categorical_crossentropy', optimizer=optimizer)
print(model.summary())

La capa final de Dense () está destinada a ser una capa de salida con activación softmax, lo que permite la clasificación de vías len (chars) de los vectores de entrada. Durante el entrenamiento, la propagación hacia atrás en el tiempo comienza en la capa de salida, por lo que tiene un propósito importante con el optimizador elegido = rmsprop. LSTM está destinado a ser una capa de salida en Keras.

Optimizer es la función de optimización. Si no conoce este término, es posible que esté familiarizado con la función de optimización de uso común en regresión logística: descenso de gradiente estocástico. Es algo similar.

La última línea especifica la función de costo. En este caso, usamos ‘categorical_crossentropy’. Puede echar un vistazo esta bonita publicación para entender por qué la entropía cruzada es mejor que el error cuadrático medio (MSE) en este caso.

6. Modelo de formación y generación de código Java

La función de muestra se utiliza para muestrear un índice de una matriz de probabilidad. Por ejemplo, dados preds =[0.5,0.2,0.3] y una temperatura predeterminada, la función devolvería el índice 0 con probabilidad de 0,5, 1 con probabilidad de 0,2 o 2 con probabilidad de 0,3. Se utiliza para evitar generar la misma secuencia una y otra vez. Queremos ver algunas secuencias de código diferentes que el programador AI puede codificar.

def sample(preds, temperature=1.0):
    preds = np.asarray(preds).astype('float64')
    preds = np.log(preds) / temperature
    exp_preds = np.exp(preds)
    preds = exp_preds / np.sum(exp_preds)
    probas = np.random.multinomial(1, preds, 1)
    return np.argmax(probas)
# train the model, output generated text after each iteration
for iteration in range(1, 60):
    print()
    print('-' * 50)
    print('Iteration', iteration)
    model.fit(X, y, batch_size=128, epochs=1)
 
    start_index = random.randint(0, len(text) - NUM_INPUT_CHARS - 1)
 
    for diversity in [0.2, 0.5, 1.0, 1.2]:
        print()
        print('----- diversity:', diversity)
 
        generated = ''
        sequence = text[start_index: start_index + NUM_INPUT_CHARS]
        generated += sequence
        print('----- Generating with seed: "' + sequence + '"')
        sys.stdout.write(generated)
 
        for i in range(400):
            x = np.zeros((1, NUM_INPUT_CHARS, len(chars)))
            for t, char in enumerate(sequence):
                x[0, t, char_indices[char]] = 1.
 
            preds = model.predict(x, verbose=0)[0]
            next_index = sample(preds, diversity)
            next_char = indices_char[next_index]
 
            generated += next_char
            sequence = sequence[1:] + next_char
 
            sys.stdout.write(next_char)
            sys.stdout.flush()
        print()

7. Resultados

Se necesitan algunas horas para entrenar al modelo. Y finalmente el código generado se parece a lo siguiente:

----- diversidad: 1.2 ----- Generando con semilla: "posiciones eak usadas por next () // y prev" posiciones eak usadas por next () // y previos 

The code generated does not make much sense, not even compile. But we can still see that LSTM captures some words and syntax. For example, "void fam();". You can also take a look at the code generated in the earlier iterations. They make less sense.

If you tune the parameters (such as NUM_INPUT_CHARS and STEP) and train longer, you may get better results. Feel free to try. I was running out of time and wanted to publish this post. More importantly, I know a better way to do this job which is shown in the next post.

8. What's Next?

In this post, I used characters sequences as input to train the model and the model predicts a character sequence. Other than turning the parameters of the basic LSTM neural network, we can also use tokens instead of characters and use different network structures. We will explore those in the next posts.

Source Code

1) The source code of this post is lstm_ai_coder_chars.py which is located at https://github.com/ryanlr/RNN-AI-Programmer
2) The code is modified based on the Keras example lstm_text_generation.py which is available here https://github.com/fchollet/keras/tree/master/examples.

Categorías
Deep Learning

Construya un programador de IA usando una red neuronal recurrente (2)

Las redes neuronales recurrentes (RNN) están ganando mucha atención en los últimos años porque se han mostrado muy prometedoras en muchas tareas de procesamiento del lenguaje natural. A pesar de su popularidad, hay un número limitado de tutoriales que explican cómo implementar una aplicación sencilla e interesante utilizando herramientas de última generación. En esta serie, utilizaremos una red neuronal recurrente para entrenar a un programador de IA, que puede escribir código Java como un programador real (con suerte). Se cubrirá lo siguiente:

1. Construyendo un programador de IA simple
2. Mejora del programador de IA: uso de tokens (esta publicación)
3. Mejora del programador de IA: uso de diferentes estructuras de red

En la publicación anterior, creamos un programador de IA básico utilizando una red neuronal LSTM simple de 1 capa. El código que genera el programador de IA no tiene mucho sentido. En esta publicación, usaremos tokens en lugar de secuencias de caracteres individuales para entrenar el modelo.

1. Obtener los datos brutos de entrenamiento

Estoy usando el mismo código fuente que en la publicación anterior. Está disponible aquí: https://github.com/frohoff/jdk8u-jdk. Esta vez, se escanea cada archivo .java, tokenizadoy luego se agrega en un archivo llamado «jdk-tokens.txt». Los saltos de línea no están reservados. No es necesario descargar el código fuente de JDK. Para su conveniencia, he incluido el archivo agregado en el repositorio de GitHub de este proyecto. Puede encontrar el enlace al final de esta publicación.

El siguiente código lee tokens del archivo jdk-tokens.txt y lo corta para que se ajuste a la capacidad de hardware de mi escritorio. En mi caso, solo usé el 20% del código como se muestra en el código.

path = "./jdk-tokens.txt"
filetext = open(path).read().lower()
 
# slice the whole string to overcome memory limitation
slice = len(filetext)/5  
slice = int (slice)
filetext = filetext[:slice]
 
tokenized = filetext.split()
 
print('# of tokens:', len(tokenized))

2. Índice de construcción para abordar los tokens

Las entradas LSTM solo comprenden números. Una forma de convertir tokens en números es asignar un número entero único a cada token. Por ejemplo, si hay 1000 tokens únicos en el código, podemos asignar un número único a cada uno de los 1000 tokens. El siguiente código crea un diccionario con entradas como [ “public” : 0 ] [ “static” : 1 ], …]. El diccionario inverso también se genera para decodificar la salida de LSTM.

uniqueTokens = sorted(list(set(tokenized)))
print('total # of unique tokens:', len(uniqueTokens))
token_indices = dict((c, i) for i, c in enumerate(uniqueTokens))
indices_token = dict((i, c) for i, c in enumerate(uniqueTokens))

3. Preparar las secuencias de entrenamiento con etiquetas

Aquí cortamos el texto en secuencias semi-redundantes de 10 tokens. Cada secuencia es una muestra de entrenamiento y la etiqueta de cada secuencia de token es el siguiente token.

NUM_INPUT_TOKENS = 10
step = 3
sequences = []
next_token = []
 
for i in range(0, len(tokenized) - NUM_INPUT_TOKENS, step):
    sequences.append(tokenized[i: i + NUM_INPUT_TOKENS])
    next_token.append(tokenized[i + NUM_INPUT_TOKENS])
 
print('nb sequences:', len(sequences))

4. Vectorización de datos de entrenamiento

Primero creamos dos matrices y luego le asignamos valores a cada una de ellas. Uno para las características y otro para la etiqueta. len (secuencias) es el número total de muestras de entrenamiento.

X = np.zeros((len(sequences), NUM_INPUT_TOKENS, len(uniqueTokens)), 
             dtype=np.bool)
y = np.zeros((len(sequences), len(uniqueTokens)), dtype=np.bool)
for i, sentence in enumerate(sequences):
    for t, char in enumerate(sentence):
        X[i, t, token_indices[char]] = 1
    y[i, token_indices[next_token[i]]] = 1

5. Construcción de un modelo LSTM de una sola capa

Construimos una red como la siguiente:

Además, es bastante sencillo apilar dos capas LSTM como también se muestra en el código comentado a continuación.

El siguiente código define la estructura de la red neuronal. La red contiene una capa de LSTM con 128 unidades ocultas. El parámetro input_shape especifica la longitud de la secuencia de entrada y la dimensión de la entrada en cada momento. Implementos densos () salida = activación (punto (entrada, núcleo) + sesgo) . La entrada aquí es la salida de la capa LSTM. La función de activación se especifica mediante la línea Activación (‘softmax’). Optimizer es la función de optimización. Es posible que esté familiarizado con el que se usa comúnmente en regresión logística, que es el descenso de gradiente estocástico. La última línea especifica la función de costo. En este caso, usamos ‘categorical_crossentropy’. Puede echar un vistazo esta bonita publicación para entender por qué la entropía cruzada es mejor que el error cuadrático medio (MSE).

model = Sequential()
 
# 1-layer LSTM
#model.add(LSTM(128, input_shape=(NUM_INPUT_TOKENS, len(uniqueTokens))))
 
# 2-layer LSTM
model.add(LSTM(128,return_sequences=True, 
               input_shape=(NUM_INPUT_TOKENS, len(uniqueTokens))))
model.add(LSTM(128))
 
model.add(Dense(len(uniqueTokens)))
model.add(Activation('softmax'))
 
optimizer = RMSprop(lr=0.01)
model.compile(loss='categorical_crossentropy', optimizer=optimizer)
print(model.summary())

Arriba, también incluyo el código para apilar otra capa de LSTM y convertirlo en un LSTM RNN de 2 capas.

6. Modelo de formación y generación de código Java

La función de muestra se utiliza para muestrear un índice de una matriz de probabilidad. Por ejemplo, dados preds =[0.5,0.2,0.3] y una temperatura predeterminada, el índice de retorno de la función 0 con probabilidad de 0,5, 1 con probabilidad de 0,2 o 2 con probabilidad de 0,3. Se usa para evitar generar la misma oración una y otra vez. Queremos ver una secuencia de código diferente que el programador AI pueda codificar.

def sample(preds, temperature=1.0):
    # helper function to sample an index from a probability array
    preds = np.asarray(preds).astype('float64')
    preds = np.log(preds) / temperature
    exp_preds = np.exp(preds)
    preds = exp_preds / np.sum(exp_preds)
    probas = np.random.multinomial(1, preds, 1)
    return np.argmax(probas)
 
# train the model, output generated code after each iteration
for iteration in range(1, 60):
    print()
    print('-' * 50)
    print('Iteration', iteration)
    model.fit(X, y, batch_size=128, epochs=1)
 
    start_index = random.randint(0, len(tokenized) - NUM_INPUT_TOKENS - 1)
 
    for diversity in [0.2, 0.5, 1.0, 1.2]:
        print()
        print('----- diversity:', diversity)
 
        generated = [] #''
        sequence = tokenized[start_index: start_index + NUM_INPUT_TOKENS]
 
        generated=list(sequence)
 
        print('----- Generating with seed: "' + ' '.join(sequence) + '"-------')
        sys.stdout.write(' '.join(generated))
 
        for i in range(100):
            x = np.zeros((1, NUM_INPUT_TOKENS, len(uniqueTokens)))
            for t, char in enumerate(sequence):
                x[0, t, token_indices[char]] = 1.
 
            preds = model.predict(x, verbose=0)[0]
            next_index = sample(preds, diversity)
            next_pred_token = indices_token[next_index]
 
            generated.append(next_pred_token)
            sequence = sequence[1:]
            sequence.append(next_pred_token)
 
            sys.stdout.write(next_pred_token+" ")
            sys.stdout.flush()
        print()

7. Resultados

Se necesitan algunas horas para entrenar al modelo. Me detuve en la 40a iteración y el código generado se parece a lo siguiente:

----- Generating with seed: "true ) ; } else { boolean result = definesequals"-------
true ) ; } else { boolean result = definesequals
( ) . substring ( 1 , gradients . get ( p ) ; } 
if ( val . null || ( npoints == null ) ? new void . bitlength ( ) + prefixlength ) ; 
for ( int i = 0 ; i < num ; i ++ ) } break ; } 
if ( radix result = != other . off ) ; 
int endoff = b . append ( buf , 0 , len + 1 ) ; digits ++ ] ; 

El código generado se ve mucho mejor que el código generado por el enfoque anterior basado en caracteres. Tenga en cuenta que agregué saltos de línea para facilitar la lectura. Podemos ver que LSTM captura los bucles y las condiciones bastante bien, el código comienza a tener más sentido. Por ejemplo, «for (int i = 0; i por lazo. Si ajusta los parámetros (como NUM_INPUT_CHARS y STEP) y entrena más tiempo, puede obtener mejores resultados. Siéntete libre de probar. Nuevamente, ya conozco una mejor manera de hacer este trabajo, así que me detengo aquí y hago la mejora en la próxima publicación.

También puede echar un vistazo al código generado en las iteraciones anteriores. Tienen menos sentido.

8. ¿Qué sigue?

En esta publicación, utilicé secuencias de tokens como entrada para entrenar el modelo y el modelo predice secuencias de tokens. Si todo funciona correctamente, debería funcionar mejor que el enfoque basado en personajes. Además, también podemos utilizar diferentes estructuras de red. Los exploraremos en la próxima publicación.

Código fuente

1) El código fuente de esta publicación es lstm_ai_coder_tokens.py que se encuentra en https://github.com/ryanlr/RNN-AI-Programmer

Categorías
Deep Learning

Cree un programador de inteligencia artificial utilizando una red neuronal recurrente (3)

Las redes neuronales recurrentes (RNN) están ganando mucha atención en los últimos años porque se han mostrado muy prometedoras en muchas tareas de procesamiento del lenguaje natural. A pesar de su popularidad, hay un número limitado de tutoriales que explican cómo implementar una aplicación sencilla e interesante utilizando herramientas de última generación. En esta serie, utilizaremos una red neuronal recurrente para entrenar a un programador de IA, que puede escribir código Java como un programador real (con suerte). Se cubrirá lo siguiente:

1. Construyendo un programador de IA simple
2. Mejora del programador de IA: uso de tokens
3. Mejora del programador de IA: uso de diferentes estructuras de red (esta publicación)

En las publicaciones anteriores, creamos un programador de IA básico usando personajes y tokens como datos de entrenamiento, respectivamente. Ambos enfoques utilizan una red neuronal LSTM simple de 1 capa. Más específicamente, la red utiliza una estructura de muchos a uno, como se muestra en el siguiente diagrama:

Para las predicciones de secuencia a secuencia, existen otras estructuras como uno a muchos y muchos a muchos. En esta publicación, implementaremos una estructura de red simple de muchos a muchos como la siguiente. El código se envía al mismo repositorio en GitHub (el enlace se proporciona al final de esta publicación).

Dado que la mayor parte del código es el mismo que en la publicación anterior, solo resalto las diferencias aquí.

1. Prepara los datos de entrenamiento

Dado que esta vez predeciremos una secuencia en lugar del siguiente token, la y también debería ser una secuencia. y es la secuencia desplazada a la izquierda en uno desde X.

NUM_INPUT_TOKENS = 10
step = 3
sequences = []
 
for i in range(0, len(tokenized) - NUM_INPUT_TOKENS-1, step):
    sequences.append(tokenized[i: i + NUM_INPUT_TOKENS+1])
 
print('# of training sequences:', len(sequences))
 
X_temp = np.zeros((len(sequences), NUM_INPUT_TOKENS + 1, len(uniqueTokens)), dtype=np.bool)
X = np.zeros((len(sequences), NUM_INPUT_TOKENS, len(uniqueTokens)), dtype=np.bool)
y = np.zeros((len(sequences), NUM_INPUT_TOKENS, len(uniqueTokens)), dtype=np.bool)
 
for i, sequence in enumerate(sequences):
    for t, char in enumerate(sequence):
        X_temp[i, t, token_indices[char]] = 1
 
num_sequences = len(X_temp)
for i, vec in enumerate(X_temp):
    y[i] = vec[1:]
    X[i]= vec[:-1]

2. Construya una red neuronal recurrente de muchos a muchos

Aquí está el código para construir una red recurrente de muchos a muchos.

model = Sequential()
model.add(LSTM(128, input_shape=(NUM_INPUT_TOKENS, len(uniqueTokens)), return_sequences=True))
model.add(TimeDistributed(Dense(len(uniqueTokens))))
model.add(Activation('softmax'))
optimizer = RMSprop(lr=0.01)
model.compile(loss='categorical_crossentropy', optimizer=optimizer)
print(model.summary())

Puede imprimir la estructura de la red:

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
lstm_1 (LSTM)                (None, 10, 128)           670208    
_________________________________________________________________
time_distributed_1 (TimeDist (None, 10, 1180)          152220    
_________________________________________________________________
activation_1 (Activation)    (None, 10, 1180)          0         
=================================================================

Al igual que hicimos con la estructura de muchos a uno, también podemos apilar fácilmente una capa más de LSTM como se muestra a continuación:

model = Sequential()
model.add(LSTM(128, return_sequences=True, input_shape=(NUM_INPUT_TOKENS, len(uniqueTokens))))
model.add(LSTM(128, return_sequences=True))
model.add(TimeDistributed(Dense(len(uniqueTokens))))
model.add(Activation('softmax'))
optimizer = RMSprop(lr=0.01)
model.compile(loss='categorical_crossentropy', optimizer=optimizer)
print(model.summary())

La estructura de la red es así:

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
lstm_1 (LSTM)                (None, 10, 128)           670208    
_________________________________________________________________
lstm_2 (LSTM)                (None, 10, 128)           131584    
_________________________________________________________________
time_distributed_1 (TimeDist (None, 10, 1180)          152220    
_________________________________________________________________
activation_1 (Activation)    (None, 10, 1180)          0         
=================================================================

3. Resultados

Los resultados se ven mejor que la red anterior de varios a uno después de solo unas pocas iteraciones. Le recomiendo encarecidamente que ejecute el código y tenga sus propias observaciones y piense en la razón. Sería un buen ejercicio.

runattributes = numberelements [ i ] . offsets [ currindex ] ; 
patternentry ucompactintarray ; 
import sun . util . oldstart ; 

4. ¿Qué sigue?

En esta publicación, utilicé una red de estructura de muchos a muchos para entrenar el modelo y el modelo predice secuencias de tokens. Quizás por diversión, también puede probar la red uno a varios. Consulte esta tabla para ver otras estructuras de red. Además, hay muchos otros parámetros que podemos ajustar para hacer que el entrenamiento sea más rápido y mejorar el Programador de IA.

Código fuente

1) El código fuente de esta publicación es lstm_ai_coder_tokens_many2many.py que se encuentra en https://github.com/ryanlr/RNN-AI-Programmer