Python para PNL: incrustaciones de palabras para aprendizaje profundo en Keras

Este es el artículo número 16 de mi serie de artículos sobre Python para PNL. En mi artículo anterior, expliqué cómo se puede usar la técnica de N-Grams para desarrollar un aut...

Este es el artículo número 16 de mi serie de artículos sobre Python para PNL. En mi Artículo anterior expliqué cómo se puede usar la técnica de N-Grams para desarrollar un relleno de texto automático simple en Python. El modelo N-Gram es básicamente una forma de convertir datos de texto en forma numérica para que puedan ser utilizados por algoritmos estadísticos.

Antes de N-Grams, expliqué la bolsa de palabras y [TF-FDI](/python- para-nlp-creando-un-modelo-tf-idf-desde-cero/), que también se pueden utilizar para generar vectores de características numéricas a partir de datos de texto. Hasta ahora, hemos estado utilizando enfoques de aprendizaje automático para realizar diferentes tareas de PNL, como clasificación de texto, modelado de temas, análisis sentimental, resumen de texto, etc. En este artículo, comenzaremos nuestra discusión sobre técnicas de aprendizaje profundo para PNL.

Los enfoques de aprendizaje profundo consisten en diferentes tipos de redes neuronales densamente conectadas. Se ha demostrado que estos enfoques son eficientes para resolver varias tareas complejas, como automóviles autónomos, generación de imágenes, segmentación de imágenes, etc. Los enfoques de aprendizaje profundo también han demostrado ser bastante eficientes para tareas de PNL.

En este artículo, estudiaremos incrustaciones de palabras para tareas de PNL que involucran aprendizaje profundo. Veremos cómo se pueden usar incrustaciones de palabras para realizar una tarea de clasificación simple usando una red neuronal profunda en la [Biblioteca Keras] de Python (https://keras.io/).

Problemas con enfoques de vectores de funciones codificadas en caliente {#problemas con enfoques de vectores de funciones codificadas en caliente}

Un inconveniente potencial con los enfoques de vector de características codificados en caliente, como N-Grams, bolsa de palabras y enfoque TF-IDF, es que el vector de características para cada documento puede ser enorme. Por ejemplo, si tiene medio millón de palabras únicas en su corpus y desea representar una oración que contiene 10 palabras, su vector de características será un vector codificado en caliente de medio millón de dimensiones donde solo 10 índices tendrán 1. Esto es un desperdicio de espacio y aumenta exponencialmente la complejidad del algoritmo dando como resultado la maldición de la dimensionalidad.

Incrustaciones de palabras {#incrustaciones de palabras}

En las incrustaciones de palabras, cada palabra se representa como un vector denso de n dimensiones. Las palabras que son similares tendrán un vector similar. Las técnicas de incorporación de palabras como Guante y Word2Vec han demostrado ser extremadamente eficiente para convertir palabras en vectores densos correspondientes. El tamaño del vector es pequeño y ninguno de los índices del vector está realmente vacío.

Implementación de incrustaciones de palabras con modelos secuenciales de Keras {#implementación de incrustaciones de palabras con modelos secuenciales de Keras}

La biblioteca de Keras es una de las bibliotecas de aprendizaje profundo más famosas y comúnmente utilizadas para Python que se basa en [TensorFlow] (https://www.tensorflow.org/).

Keras admite dos tipos de API: secuencial y funcional. En esta sección, veremos cómo se utilizan las incrustaciones de palabras con la API secuencial de Keras. En la siguiente sección, explicaré cómo implementar el mismo modelo a través de la API funcional de Keras.

Para implementar incrustaciones de palabras, la biblioteca de Keras contiene una capa llamada Embedding(). La capa de incrustación se implementa en forma de clase en Keras y normalmente se usa como una primera capa en el modelo secuencial para tareas de PNL.

La capa de incrustación se puede utilizar para realizar tres tareas en Keras:

  • Se puede usar para aprender incrustaciones de palabras y guardar el modelo resultante
  • Se puede usar para aprender las incrustaciones de palabras además de realizar tareas de PNL como clasificación de texto, análisis de sentimientos, etc.
  • Se puede usar para cargar incrustaciones de palabras previamente entrenadas y usarlas en un nuevo modelo

En este artículo, veremos el segundo y tercer caso de uso de la capa de incrustación. El primer caso de uso es un subconjunto del segundo caso de uso.

Veamos cómo se ve la capa de incrustación:

1
embedding_layer = Embedding(200, 32, input_length=50)

El primer parámetro en la capa de incrustación es el tamaño del vocabulario o el número total de palabras únicas en un corpus. El segundo parámetro es el número de dimensiones para cada vector de palabra. Por ejemplo, si desea que cada vector de palabra tenga 32 dimensiones, especificará 32 como segundo parámetro. Y finalmente, el tercer parámetro es la longitud de la oración de entrada.

La salida de la incrustación de palabras es un vector 2D donde las palabras se representan en filas, mientras que sus dimensiones correspondientes se presentan en columnas. Finalmente, si desea conectar directamente su capa de incrustación de palabras con una capa densamente conectada, primero debe aplanar sus incrustaciones de palabras 2D en 1D. Estos conceptos serán más comprensibles una vez que veamos la incrustación de palabras en acción.

Incrustaciones de palabras personalizadas

Como dije antes, Keras se puede usar para aprender incrustaciones de palabras personalizadas o para cargar incrustaciones de palabras preentrenadas. En esta sección, veremos cómo se puede usar la capa de incrustación de Keras para aprender incrustaciones de palabras personalizadas.

Realizaremos tareas simples de clasificación de texto que utilizarán incrustaciones de palabras. Ejecute el siguiente script para descargar las bibliotecas necesarias:

1
2
3
4
5
6
7
from numpy import array
from keras.preprocessing.text import one_hot
from keras.preprocessing.sequence import pad_sequences
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Flatten
from keras.layers.embeddings import Embedding

A continuación, necesitamos definir nuestro conjunto de datos. Usaremos un conjunto de datos personalizado muy simple que contendrá reseñas sobre películas. El siguiente script crea nuestro conjunto de datos:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
corpus = [
    # Positive Reviews

    'This is an excellent movie',
    'The move was fantastic I like it',
    'You should watch it is brilliant',
    'Exceptionally good',
    'Wonderfully directed and executed I like it',
    'Its a fantastic series',
    'Never watched such a brillent movie',
    'It is a Wonderful movie',

    # Negtive Reviews

    "horrible acting",
    'waste of money',
    'pathetic picture',
    'It was very boring',
    'I did not like the movie',
    'The movie was horrible',
    'I will not recommend',
    'The acting is pathetic'
]

Nuestro corpus cuenta con 8 críticas positivas y 8 críticas negativas. El siguiente paso es crear un conjunto de etiquetas para nuestros datos.

1
sentiments = array([1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0])

Puede ver que los primeros 8 elementos de la matriz de opinión contienen 1, que corresponde a una opinión positiva. Los últimos 8 elementos son cero que corresponden a sentimiento negativo.

Anteriormente dijimos que el primer parámetro de la capa Embedding() es el vocabulario, o el número de palabras únicas en el corpus. Primero encontremos el número total de palabras en nuestro corpus:

1
2
3
4
5
6
7
from nltk.tokenize import word_tokenize

all_words = []
for sent in corpus:
    tokenize_word = word_tokenize(sent)
    for word in tokenize_word:
        all_words.append(word)

En el script anterior, simplemente iteramos a través de cada oración en nuestro corpus y luego convertimos la oración en palabras. A continuación, iteramos a través de la lista de todas las palabras y agregamos las palabras a la lista all_words. Una vez que ejecute el script anterior, debería ver todas las palabras en el diccionario all_words. Sin embargo, no queremos las palabras duplicadas.

Podemos recuperar todas las palabras únicas de una lista pasando la lista a la función set, como se muestra a continuación.

1
2
unique_words = set(all_words)
print(len(unique_words))

En la salida verá "45", que es el número de palabras únicas en nuestro corpus. Agregaremos un búfer de 5 a nuestro tamaño de vocabulario y estableceremos el valor de vocab_length en 50.

La capa de incrustación espera que las palabras estén en formato numérico. Por lo tanto, necesitamos convertir las oraciones de nuestro corpus en números. Una forma de convertir texto en números es usando la función one_hot de la biblioteca keras.preprocessing.text. La función toma la oración y la longitud total del vocabulario y devuelve la oración en forma numérica.

1
2
embedded_sentences = [one_hot(sent, vocab_length) for sent in corpus]
print(embedded_sentences )

En el script anterior, convertimos todas las oraciones en nuestro corpus a su forma numérica y las mostramos en la consola. La salida se ve así:

1
[[31, 12, 31, 14, 9], [20, 3, 20, 16, 18, 45, 14], [16, 26, 29, 14, 12, 1], [16, 23], [32, 41, 13, 20, 18, 45, 14], [15, 28, 16, 43], [7, 9, 31, 28, 31, 9], [14, 12, 28, 46, 9], [4, 22], [5, 4, 9], [23, 46], [14, 20, 32, 14], [18, 1, 26, 45, 20, 9], [20, 9, 20, 4], [18, 8, 26, 34], [20, 22, 12, 23]]

Puede ver que nuestra primera oración contenía cinco palabras, por lo tanto, tenemos cinco números enteros en el primer elemento de la lista. Además, observe que la última palabra de la primera oración era "película" en el primer elemento de la lista, y tenemos el dígito 9 en el quinto lugar de la matriz 2D resultante, lo que significa que "película" se ha codificado como 9 y así sucesivamente.

La capa de incrustación espera que las oraciones sean del mismo tamaño. Sin embargo, nuestras oraciones codificadas son de diferentes tamaños. Una forma de hacer que todas las oraciones tengan un tamaño uniforme es aumentar la longitud de todas las oraciones y hacerla igual a la longitud de la oración más grande. Primero encontremos la oración más grande en nuestro corpus y luego aumentaremos la longitud de todas las oraciones a la longitud de la oración más grande. Para hacerlo, ejecute el siguiente script:

1
2
3
word_count = lambda sentence: len(word_tokenize(sentence))
longest_sentence = max(corpus, key=word_count)
length_long_sentence = len(word_tokenize(longest_sentence))

En la oración anterior, usamos una expresión lambda para encontrar la longitud de todas las oraciones. Luego usamos la función max para devolver la oración más larga. Finalmente, la oración más larga se convierte en palabras y el número de palabras se cuenta usando la función len.

Luego de hacer que todas las oraciones tengan el mismo tamaño, agregaremos ceros a los índices vacíos que se crearán como resultado de aumentar la longitud de la oración. Para agregar los ceros al final de las oraciones, podemos usar el método pad_sequences. El primer parámetro es la lista de oraciones codificadas de tamaños desiguales, el segundo parámetro es el tamaño de la oración más larga o el índice de relleno, mientras que el último parámetro es relleno donde especifica post para agregar relleno al final de las oraciones .

Ejecute el siguiente script:

1
2
padded_sentences = pad_sequences(embedded_sentences, length_long_sentence, padding='post')
print(padded_sentences)

En la salida, debería ver oraciones con relleno.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
[[31 12 31 14  9  0  0]
 [20  3 20 16 18 45 14]
 [16 26 29 14 12  1  0]
 [16 23  0  0  0  0  0]
 [32 41 13 20 18 45 14]
 [15 28 16 43  0  0  0]
 [ 7  9 31 28 31  9  0]
 [14 12 28 46  9  0  0]
 [ 4 22  0  0  0  0  0]
 [ 5  4  9  0  0  0  0]
 [23 46  0  0  0  0  0]
 [14 20 32 14  0  0  0]
 [18  1 26 45 20  9  0]
 [20  9 20  4  0  0  0]
 [18  8 26 34  0  0  0]
 [20 22 12 23  0  0  0]]

Puede ver ceros al final de las oraciones rellenadas.

Ahora tenemos todo lo que necesitamos para crear un modelo de clasificación de sentimientos utilizando incrustaciones de palabras.

Crearemos un modelo de clasificación de texto muy simple con una capa incrustada y sin capas ocultas. Mira el siguiente guión:

1
2
3
4
model = Sequential()
model.add(Embedding(vocab_length, 20, input_length=length_long_sentence))
model.add(Flatten())
model.add(Dense(1, activation='sigmoid'))

En el script anterior, creamos un modelo ‘Secuencial’ y agregamos la capa ‘Incrustación’ como la primera capa del modelo. La longitud del vocabulario se especifica mediante el parámetro vocab_length. La dimensión de cada vector de palabra será 20 y input_length será la longitud de la oración más larga, que es 7. A continuación, la capa Embedding se aplana para que pueda usarse directamente con la capa densamente conectada. Dado que es un problema de clasificación binaria, usamos la función ‘sigmoide’ como función de pérdida en la capa densa.

A continuación, compilaremos el modelo e imprimiremos el resumen de nuestro modelo, como se muestra a continuación:

1
2
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['acc'])
print(model.summary())

El resumen del modelo es el siguiente:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Layer (type)                 Output Shape              Param #
=================================================================
embedding_1 (Embedding)      (None, 7, 20)             1000
_________________________________________________________________
flatten_1 (Flatten)          (None, 140)               0
_________________________________________________________________
dense_1 (Dense)              (None, 1)                 141
=================================================================
Total params: 1,141
Trainable params: 1,141
Non-trainable params: 0

Puede ver que la primera capa tiene 1000 parámetros entrenables. Esto se debe a que nuestro tamaño de vocabulario es de 50 y cada palabra se presentará como un vector de 20 dimensiones. Por lo tanto, el número total de parámetros entrenables será 1000. De manera similar, la salida de la capa de incrustación será una oración con 7 palabras donde cada palabra está representada por un vector de 20 dimensiones. Sin embargo, cuando la salida 2D se aplana, obtenemos un vector de 140 dimensiones (7 x 20). El vector aplanado está conectado directamente a la capa densa que contiene 1 neurano.

Ahora entrenemos el modelo en nuestros datos usando el método fit, como se muestra a continuación:

1
model.fit(padded_sentences, sentiments, epochs=100, verbose=1)

El modelo será entrenado durante 100 épocas.

Entrenaremos y probaremos el modelo utilizando el mismo corpus. Ejecute el siguiente script para evaluar el rendimiento del modelo en nuestro corpus:

1
2
loss, accuracy = model.evaluate(padded_sentences, sentiments, verbose=0)
print('Accuracy: %f' % (accuracy*100))

En el resultado, verá que la precisión del modelo es 1,00, es decir, 100 por ciento.

Nota: En las aplicaciones del mundo real, los conjuntos de entrenamiento y prueba deben ser diferentes. Veremos un ejemplo de eso cuando realicemos la clasificación de texto en algunos datos del mundo real en un próximo artículo.

Carga de incrustaciones de palabras previamente entrenadas

En la sección anterior, entrenamos incrustaciones de palabras personalizadas. Sin embargo, también podemos usar incrustaciones de palabras preentrenadas.

Existen varios tipos de incrustaciones de palabras preentrenadas, sin embargo, usaremos las incrustaciones de palabras GloVe de Stanford NLP, ya que es la más famosa y la más utilizada. La palabra incrustaciones se puede descargar de este enlace.

El archivo más pequeño se llama "Glove.6B.zip". El tamaño del archivo es de 822 MB. El archivo contiene 50, 100, 200 y 300 vectores de palabras dimensionales para 400k palabras. Usaremos el vector de 100 dimensiones.

El proceso es bastante similar. Primero tenemos que importar las bibliotecas requeridas:

1
2
3
4
5
6
7
from numpy import array
from keras.preprocessing.text import one_hot
from keras.preprocessing.sequence import pad_sequences
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Flatten
from keras.layers.embeddings import Embedding

A continuación, tenemos que crear nuestro corpus seguido de las etiquetas.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
corpus = [
    # Positive Reviews

    'This is an excellent movie',
    'The move was fantastic I like it',
    'You should watch it is brilliant',
    'Exceptionally good',
    'Wonderfully directed and executed I like it',
    'Its a fantastic series',
    'Never watched such a brillent movie',
    'It is a Wonderful movie',

    # Negtive Reviews

    "horrible acting",
    'waste of money',
    'pathetic picture',
    'It was very boring',
    'I did not like the movie',
    'The movie was horrible',
    'I will not recommend',
    'The acting is pathetic'
]
1
sentiments = array([1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0])

En la última sección, usamos la función one_hot para convertir texto en vectores. Otro enfoque es usar la función Tokenizer de la biblioteca keras.preprocessing.text.

Simplemente tienes que pasar tu corpus al método fit_on_text del Tokenizer.

1
2
word_tokenizer = Tokenizer()
word_tokenizer.fit_on_texts(corpus)

Para obtener el número de palabras únicas en el texto, simplemente puede contar la longitud del diccionario word_index del objeto word_tokenizer. Recuerda sumar 1 con el tamaño del vocabulario. Esto es para almacenar las dimensiones de las palabras para las que no existen incrustaciones de palabras previamente entrenadas.

1
vocab_length = len(word_tokenizer.word_index) + 1

Finalmente, para convertir oraciones a su contraparte numérica, llame a la función texts_to_sequences y pásele todo el corpus.

1
2
embedded_sentences = word_tokenizer.texts_to_sequences(corpus)
print(embedded_sentences)

En la salida, verá las oraciones en su forma numérica:

1
[[14, 3, 15, 16, 1], [4, 17, 6, 9, 5, 7, 2], [18, 19, 20, 2, 3, 21], [22, 23], [24, 25, 26, 27, 5, 7, 2], [28, 8, 9, 29], [30, 31, 32, 8, 33, 1], [2, 3, 8, 34, 1], [10, 11], [35, 36, 37], [12, 38], [2, 6, 39, 40], [5, 41, 13, 7, 4, 1], [4, 1, 6, 10], [5, 42, 13, 43], [4, 11, 3, 12]]

El siguiente paso es encontrar el número de palabras en la oración más larga y luego aplicar relleno a las oraciones que tienen una longitud más corta que la oración más larga.

1
2
3
4
5
6
7
8
9
from nltk.tokenize import word_tokenize

word_count = lambda sentence: len(word_tokenize(sentence))
longest_sentence = max(corpus, key=word_count)
length_long_sentence = len(word_tokenize(longest_sentence))

padded_sentences = pad_sequences(embedded_sentences, length_long_sentence, padding='post')

print(padded_sentences)

Las oraciones rellenas se ven así:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
[[14  3 15 16  1  0  0]
 [ 4 17  6  9  5  7  2]
 [18 19 20  2  3 21  0]
 [22 23  0  0  0  0  0]
 [24 25 26 27  5  7  2]
 [28  8  9 29  0  0  0]
 [30 31 32  8 33  1  0]
 [ 2  3  8 34  1  0  0]
 [10 11  0  0  0  0  0]
 [35 36 37  0  0  0  0]
 [12 38  0  0  0  0  0]
 [ 2  6 39 40  0  0  0]
 [ 5 41 13  7  4  1  0]
 [ 4  1  6 10  0  0  0]
 [ 5 42 13 43  0  0  0]
 [ 4 11  3 12  0  0  0]]

Hemos convertido nuestras oraciones en una secuencia de números rellena. El siguiente paso es cargar las incrustaciones de palabras de GloVe y luego crear nuestra matriz de incrustaciones que contiene las palabras en nuestro corpus y sus valores correspondientes de las incrustaciones de GloVe. Ejecute el siguiente script:

1
2
3
4
5
6
from numpy import array
from numpy import asarray
from numpy import zeros

embeddings_dictionary = dict()
glove_file = open('E:/Datasets/Word Embeddings/glove.6B.100d.txt', encoding="utf8")

En el script anterior, además de cargar las incrustaciones de GloVe, también importamos algunas bibliotecas. Veremos el uso de estas bibliotecas en la próxima sección. Aquí observe que cargamos el archivo glove.6B.100d.txt. Este archivo contiene 100 incrustaciones de palabras dimensionales. También creamos un diccionario vacío que almacenará nuestras incrustaciones de palabras.

Si abre el archivo, verá una palabra al comienzo de cada línea seguida de un conjunto de 100 números. Los números forman el vector de 100 dimensiones para la palabra al comienzo de cada línea.

Crearemos un diccionario que contendrá palabras como claves y los 100 vectores dimensionales correspondientes como valores, en forma de matriz. Ejecute el siguiente script:

1
2
3
4
5
6
7
for line in glove_file:
    records = line.split()
    word = records[0]
    vector_dimensions = asarray(records[1:], dtype='float32')
    embeddings_dictionary [word] = vector_dimensions

glove_file.close()

El diccionario embeddings_dictionary ahora contiene palabras y las correspondientes incrustaciones de GloVe para todas las palabras.

Queremos las incrustaciones de palabras solo para aquellas palabras que están presentes en nuestro corpus. Crearemos una matriz numpy bidimensional de 44 (tamaño del vocabulario) filas y 100 columnas. La matriz contendrá inicialmente ceros. La matriz se llamará embedding_matrix

A continuación, iteramos a través de cada palabra en nuestro corpus recorriendo el diccionario word_tokenizer.word_index que contiene nuestras palabras y su índice correspondiente.

Cada palabra se pasará como clave al embedding_dictionary para recuperar el vector de 100 dimensiones correspondiente a la palabra. El vector de 100 dimensiones se almacenará en el índice correspondiente de la palabra en embedding_matrix. Mira el siguiente guión:

1
2
3
4
5
embedding_matrix = zeros((vocab_length, 100))
for word, index in word_tokenizer.word_index.items():
    embedding_vector = embeddings_dictionary.get(word)
    if embedding_vector is not None:
        embedding_matrix[index] = embedding_vector

Nuestra embedding_matrix ahora contiene incrustaciones de palabras preentrenadas para las palabras en nuestro corpus.

Ahora estamos listos para crear nuestro modelo secuencial. Mira el siguiente guión:

1
2
3
4
5
model = Sequential()
embedding_layer = Embedding(vocab_length, 100, weights=[embedding_matrix], input_length=length_long_sentence, trainable=False)
model.add(embedding_layer)
model.add(Flatten())
model.add(Dense(1, activation='sigmoid'))

El guión sigue siendo el mismo, excepto por la capa de incrustación. Aquí, en la capa de incrustación, el primer parámetro es el tamaño del vacabulary. El segundo parámetro es la dimensión del vector del vector de salida. Dado que estamos utilizando incrustaciones de palabras previamente entrenadas que contienen un vector de 100 dimensiones, establecemos la dimensión del vector en 100.

Otro atributo muy importante de la capa Embedding() que no usamos en la última sección son los pesos. Puede pasar su matriz de incrustación preentrenada como pesos predeterminados al parámetro pesos. Y dado que no estamos entrenando la capa de incrustación, el atributo entrenable se ha establecido en Falso.

Vamos a compilar nuestro modelo y ver el resumen de nuestro modelo:

1
2
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['acc'])
print(model.summary())

Nuevamente estamos usando adam como optimizador para minimizar la pérdida. La función de pérdida que se utiliza es binary_crossentropy. Y queremos ver los resultados en forma de precisión, por lo que acc se ha pasado como valor para el atributo metrics.

El resumen del modelo es el siguiente:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Layer (type)                 Output Shape              Param #
=================================================================
embedding_1 (Embedding)      (None, 7, 100)            4400
_________________________________________________________________
flatten_1 (Flatten)          (None, 700)               0
_________________________________________________________________
dense_1 (Dense)              (None, 1)                 701
=================================================================
Total params: 5,101
Trainable params: 701
Non-trainable params: 4,400
_________________________________________________________________

Puede ver que dado que tenemos 44 palabras en nuestro vocabulario y cada palabra se representará como un vector de 100 dimensiones, la cantidad de parámetros para la capa de incrustación será 44 x 100 = 4400. La salida de la capa de incrustación será un vector 2D con 7 filas (1 para cada palabra en la oración) y 100 columnas. La salida de la capa de incrustación se aplanará para que pueda usarse con la capa densa. Finalmente, la capa densa se usa para hacer predicciones.

Ejecute el siguiente script para entrenar los algoritmos:

1
model.fit(padded_sentences, sentiments, epochs=100, verbose=1)

Una vez que se entrena el algoritmo, ejecute el siguiente script para evaluar el rendimiento del algoritmo.

1
2
loss, accuracy = model.evaluate(padded_sentences, sentiments, verbose=0)
print('Accuracy: %f' % (accuracy*100))

En la salida, debería ver que la precisión es 1.000, es decir, 100%.

Incrustaciones de palabras con la API funcional de Keras

En la última sección, vimos cómo se pueden usar incrustaciones de palabras con la API secuencial de Keras. Si bien la API secuencial es un buen punto de partida para los principiantes, ya que le permite crear rápidamente modelos de aprendizaje profundo, es extremadamente importante saber cómo funciona la API funcional de Keras. La mayoría de los modelos avanzados de aprendizaje profundo que involucran múltiples entradas y salidas utilizan la API funcional.

En esta sección, veremos cómo podemos implementar la capa de incrustación con la API funcional de Keras.

El resto del guión sigue siendo similar a como estaba en la última sección. El único cambio será en el desarrollo de un modelo de aprendizaje profundo. Implementemos el mismo modelo de aprendizaje profundo que implementamos en la última sección con la API funcional de Keras.

1
2
3
4
5
6
7
8
from keras.models import Model
from keras.layers import Input

deep_inputs = Input(shape=(length_long_sentence,))
embedding = Embedding(vocab_length, 100, weights=[embedding_matrix], input_length=length_long_sentence, trainable=False)(deep_inputs) # line A
flatten = Flatten()(embedding)
hidden = Dense(1, activation='sigmoid')(flatten)
model = Model(inputs=deep_inputs, outputs=hidden)

En la API funcional de Keras, debe definir la capa de entrada por separado antes de la capa de incrustación. En la capa de entrada, simplemente debe pasar la longitud del vector de entrada. Para especificar esa capa anterior como entrada para la siguiente capa, la capa anterior se pasa como un parámetro dentro del paréntesis, al final de la siguiente capa.

Por ejemplo, en el script anterior, puede ver que deep_inputs se pasa como parámetro al final de la capa de incrustación. De manera similar, embedding se pasa como entrada al final de la capa Flatten() y así sucesivamente.

Finalmente, en Model(), debe pasar la capa de entrada y la capa de salida final.

Compilemos ahora el modelo y echemos un vistazo al resumen del modelo.

1
2
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['acc'])
print(model.summary())

La salida se ve así:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Layer (type)                 Output Shape              Param #
=================================================================
input_1 (InputLayer)         (None, 7)                 0
_________________________________________________________________
embedding_1 (Embedding)      (None, 7, 100)            4400
_________________________________________________________________
flatten_1 (Flatten)          (None, 700)               0
_________________________________________________________________
dense_1 (Dense)              (None, 1)                 701
=================================================================
Total params: 5,101
Trainable params: 701
Non-trainable params: 4,400

En el resumen del modelo, puede ver la capa de entrada como una capa separada antes de la capa incrustada. El resto del modelo sigue siendo el mismo.

Finalmente, el proceso para ajustar y evaluar el modelo es el mismo que el utilizado en Sequential API:

1
2
3
4
model.fit(padded_sentences, sentiments, epochs=100, verbose=1)
loss, accuracy = model.evaluate(padded_sentences, sentiments, verbose=0)

print('Accuracy: %f' % (accuracy*100))

En la salida, verá una precisión de 1.000, es decir, 100 por ciento.

Yendo más lejos: proyecto de extremo a extremo portátil

¿Tu naturaleza inquisitiva te hace querer ir más allá? Recomendamos consultar nuestro Proyecto guiado: ["Subtítulos de imágenes con CNN y Transformers con Keras"](https://wikihtp.com/courses/image-captioning-with-cnns-and -transformadores-con-keras/#cta){target="_blank"}.

En este proyecto guiado, aprenderá a crear un modelo de subtítulos de imágenes, que acepta una imagen como entrada y produce un subtítulo de texto como salida.

Aprenderás a:

  • Preprocesar texto
  • Vectorizar la entrada de texto fácilmente
  • Trabaje con la API tf.data y cree conjuntos de datos de alto rendimiento
  • Cree Transformers desde cero con TensorFlow/Keras y KerasNLP: la adición horizontal oficial a Keras para crear modelos NLP de última generación
  • Cree arquitecturas híbridas donde la salida de una red se codifica para otra

¿Cómo enmarcamos los subtítulos de las imágenes? La mayoría lo considera un ejemplo de aprendizaje profundo generativo, porque estamos enseñando a una red a generar descripciones. Sin embargo, me gusta verlo como una instancia de traducción automática neuronal: estamos traduciendo las características visuales de una imagen en palabras. A través de la traducción, estamos generando una nueva representación de esa imagen, en lugar de simplemente generar un nuevo significado. Verlo como traducción, y solo por generación de extensión, enfoca la tarea bajo una luz diferente y la hace un poco más intuitiva.

Enmarcar el problema como uno de traducción hace que sea más fácil averiguar qué arquitectura querremos usar. Los transformadores solo de codificador son excelentes para comprender el texto (análisis de opinión, clasificación, etc.) porque los codificadores codifican representaciones significativas. Los modelos de solo decodificador son excelentes para la generación (como GPT-3), ya que los decodificadores pueden inferir representaciones significativas en otra secuencia con el mismo significado. La traducción generalmente se realiza mediante una arquitectura de codificador-decodificador, donde los codificadores codifican una representación significativa de una oración (o imagen, en nuestro caso) y los decodificadores aprenden a convertir esta secuencia en otra representación significativa que es más interpretable para nosotros (como una oración).

Conclusión

Para usar datos de texto como entrada para el modelo de aprendizaje profundo, necesitamos convertir texto en números. Sin embargo, a diferencia de los modelos de aprendizaje automático, pasar un vector disperso de gran tamaño puede afectar en gran medida a los modelos de aprendizaje profundo. Por lo tanto, necesitamos convertir nuestro texto en pequeños vectores densos. Las incrustaciones de palabras nos ayudan a convertir texto en vectores densos.

En este artículo, vimos cómo se pueden implementar incrustaciones de palabras con la biblioteca de aprendizaje profundo de Keras. Implementamos las incrustaciones de palabras personalizadas y utilizamos incrustaciones de palabras preentrenadas para resolver una tarea de clasificación simple. Finalmente, también vimos cómo implementar incrustaciones de palabras con Keras Functional API.