Este es el art铆culo n煤mero 17 de mi serie de art铆culos sobre Python para PNL. En el 煤ltimo art铆culo, comenzamos nuestra discusi贸n sobre el aprendizaje profundo para el procesamiento del lenguaje natural.
El art铆culo anterior se centr贸 principalmente en las incrustaciones de palabras, donde vimos c贸mo las incrustaciones de palabras se pueden usar para convertir texto en un vector denso correspondiente, que posteriormente se puede usar como entrada para cualquier modelo de aprendizaje profundo. Realizamos tareas de clasificaci贸n b谩sica mediante incrustaciones de palabras. Usamos un conjunto de datos personalizado que conten铆a 16 rese帽as imaginarias sobre pel铆culas. Adem谩s, los algoritmos de clasificaci贸n se entrenaron y probaron con los mismos datos. Finalmente, solo usamos una red neuronal densamente conectada para probar nuestro algoritmo.
En este art铆culo, nos basaremos en los conceptos que estudiamos en el art铆culo anterior y veremos la clasificaci贸n con m谩s detalle utilizando un conjunto de datos del mundo real. Utilizaremos tres tipos diferentes de redes neuronales profundas: red neuronal densamente conectada (red neuronal b谩sica), red neuronal convolucional (CNN) y red de memoria a largo plazo a corto plazo (LSTM), que es una variante de las redes neuronales recurrentes . Adem谩s, veremos c贸mo evaluar el modelo de aprendizaje profundo sobre un dato totalmente invisible.
Nota : Este art铆culo utiliza la capa de incrustaci贸n de Keras y las incrustaciones de palabras GloVe para convertir texto a forma num茅rica. Es importante que ya comprenda estos conceptos. De lo contrario, deber铆a leer mi art铆culo anterior y luego puede volver y continuar con este art铆culo.
El conjunto de datos
Contenido
- 1 El conjunto de datos
- 2 Importaci贸n de bibliotecas necesarias
- 3 Importar y analizar el conjunto de datos
- 4 Preprocesamiento de datos
- 5 Preparaci贸n de la capa de incrustaci贸n
- 6 Clasificaci贸n de texto con una red neuronal simple
- 7 Clasificaci贸n de texto con una red neuronal convolucional
- 8 Clasificaci贸n de texto con red neuronal recurrente (LSTM)
- 9 Hacer predicciones en una sola instancia
- 10 Conclusi贸n
El conjunto de datos que se puede descargar desde este enlace de Kaggle .
Si descarga el conjunto de datos y extrae el archivo comprimido, ver谩 un archivo CSV. El archivo contiene 50.000 registros y dos columnas: revisi贸n y opini贸n. La columna de opini贸n contiene texto para la opini贸n y la columna de opini贸n contiene la opini贸n de la opini贸n. La columna de sentimiento puede tener dos valores, es decir, “positivo” y “negativo”, lo que hace que nuestro problema sea un problema de clasificaci贸n binaria.
Importaci贸n de bibliotecas necesarias
El siguiente script importa las bibliotecas necesarias:
import pandas as pd
import numpy as np
import re
import nltk
from nltk.corpus import stopwords
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.core import Activation, Dropout, Dense
from keras.layers import Flatten
from keras.layers import GlobalMaxPooling1D
from keras.layers.embeddings import Embedding
from sklearn.model_selection import train_test_split
from keras.preprocessing.text import Tokenizer
Importar y analizar el conjunto de datos
Ahora importemos y analicemos nuestro conjunto de datos. Ejecute el siguiente script:
movie_reviews = pd.read_csv("E:DatasetsIMDB Dataset.csv")
movie_reviews.isnull().values.any()
movie_reviews.shape
En el script anterior, usamos el read_csv()
m茅todo de la biblioteca de pandas para leer el archivo CSV que contiene nuestro conjunto de datos. En la siguiente l铆nea, verificamos si el conjunto de datos contiene alg煤n valor NULL o no. Finalmente, imprimimos la forma de nuestro conjunto de datos.
Imprimamos ahora las primeras 5 filas del conjunto de datos usando el head()
m茅todo.
movie_reviews.head()
En la salida, ver谩 el siguiente marco de datos:
Echemos ahora un vistazo a cualquiera de las revisiones para que tengamos una idea sobre el texto que vamos a procesar. Mira el siguiente gui贸n.
movie_reviews["review"][3]
Deber铆a ver la siguiente rese帽a:
"Basically there's a family where a little boy (Jake) thinks there's a zombie in his closet & his parents are fighting all the time.<br /><br />This movie is slower than a soap opera... and suddenly, Jake decides to become Rambo and kill the zombie.<br /><br />OK, first of all when you're going to make a film you must Decide if its a thriller or a drama! As a drama the movie is watchable. Parents are divorcing & arguing like in real life. And then we have Jake with his closet which totally ruins all the film! I expected to see a BOOGEYMAN similar movie, and instead i watched a drama with some meaningless thriller spots.<br /><br />3 out of 10 just for the well playing parents & descent dialogs. As for the shots with Jake: just ignore them."
Puede ver que nuestro texto contiene signos de puntuaci贸n, corchetes y tambi茅n algunas etiquetas HTML. Preprocesaremos este texto en la siguiente secci贸n.
Finalmente, veamos la distribuci贸n de sentimientos positivos y negativos en nuestro conjunto de datos.
import seaborn as sns
sns.countplot(x='sentiment', data=movie_reviews)
Salida:
A partir del resultado, est谩 claro que el conjunto de datos contiene el mismo n煤mero de rese帽as positivas y negativas
Preprocesamiento de datos
Vimos que nuestro conjunto de datos conten铆a signos de puntuaci贸n y etiquetas HTML. En esta secci贸n definiremos una funci贸n que toma una cadena de texto como par谩metro y luego realiza un preprocesamiento en la cadena para eliminar caracteres especiales y etiquetas HTML de la cadena. Finalmente, la cadena se devuelve a la funci贸n que llama. Mira el siguiente gui贸n:
def preprocess_text(sen):
# Removing html tags
sentence = remove_tags(sen)
# Remove punctuations and numbers
sentence = re.sub('[^a-zA-Z]', ' ', sentence)
# Single character removal
sentence = re.sub(r"s+[a-zA-Z]s+", ' ', sentence)
# Removing multiple spaces
sentence = re.sub(r's+', ' ', sentence)
return sentence
TAG_RE = re.compile(r'<[^>]+>')
def remove_tags(text):
return TAG_RE.sub('', text)
En el preprocess_text()
m茅todo, el primer paso es eliminar las etiquetas HTML. Para eliminar las etiquetas HTML, remove_tags()
se ha definido la funci贸n. La remove_tags
funci贸n simplemente reemplaza cualquier cosa entre abrir y cerrar <>
con un espacio vac铆o.
A continuaci贸n, en la preprocess_text
funci贸n, se elimina todo excepto las letras may煤sculas y min煤sculas en ingl茅s, lo que da como resultado caracteres 煤nicos que no tienen sentido. Por ejemplo, cuando quita el ap贸strofo de la palabra “Mark’s”, el ap贸strofe se reemplaza por un espacio vac铆o. Por lo tanto, nos quedamos con un solo car谩cter “s”.
A continuaci贸n, eliminamos todos los caracteres individuales y los reemplazamos por un espacio que crea m煤ltiples espacios en nuestro texto. Finalmente, tambi茅n eliminamos los m煤ltiples espacios de nuestro texto.
A continuaci贸n, procesaremos previamente nuestras rese帽as y las almacenaremos en una nueva lista como se muestra a continuaci贸n:
X = []
sentences = list(movie_reviews['review'])
for sen in sentences:
X.append(preprocess_text(sen))
Veamos nuevamente la cuarta revisi贸n:
X[3]
La salida se ve as铆:
'Basically there a family where little boy Jake thinks there a zombie in his closet his parents are fighting all the time This movie is slower than soap opera and suddenly Jake decides to become Rambo and kill the zombie OK first of all when you re going to make film you must Decide if its thriller or drama As drama the movie is watchable Parents are divorcing arguing like in real life And then we have Jake with his closet which totally ruins all the film expected to see BOOGEYMAN similar movie and instead watched drama with some meaningless thriller spots out of just for the well playing parents descent dialogs As for the shots with Jake just ignore them '
En el resultado, puede ver que se han eliminado las etiquetas HTML, los signos de puntuaci贸n y los n煤meros. Solo nos quedan los alfabetos.
A continuaci贸n, necesitamos convertir nuestras etiquetas en d铆gitos. Dado que solo tenemos dos etiquetas en la salida, es decir, “positivo” y “negativo”. Podemos simplemente convertirlos en n煤meros enteros reemplazando “positivo” con el d铆gito 1 y negativo con el d铆gito 0 como se muestra a continuaci贸n:
y = movie_reviews['sentiment']
y = np.array(list(map(lambda x: 1 if x=="positive" else 0, y)))
Finalmente, necesitamos dividir nuestro conjunto de datos en conjuntos de prueba y de tren. El conjunto de trenes se utilizar谩 para entrenar nuestros modelos de aprendizaje profundo, mientras que el conjunto de pruebas se utilizar谩 para evaluar qu茅 tan bien funciona nuestro modelo.
Podemos usar el train_test_split
m茅todo del sklearn.model.selection
m贸dulo, como se muestra a continuaci贸n:
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=42)
El script anterior divide nuestros datos en un 80% para el conjunto de entrenamiento y un 20% para el conjunto de prueba.
Ahora escribamos el script para nuestra capa de incrustaci贸n. La capa de incrustaci贸n convierte nuestros datos textuales en datos num茅ricos y se utiliza como la primera capa para los modelos de aprendizaje profundo en Keras.
Preparaci贸n de la capa de incrustaci贸n
Como primer paso, usaremos la Tokenizer
clase del keras.preprocessing.text
m贸dulo para crear un diccionario de palabra a 铆ndice. En el diccionario de palabra a 铆ndice, cada palabra del corpus se usa como clave, mientras que el 铆ndice 煤nico correspondiente se usa como valor para la clave. Ejecute el siguiente script:
tokenizer = Tokenizer(num_words=5000)
tokenizer.fit_on_texts(X_train)
X_train = tokenizer.texts_to_sequences(X_train)
X_test = tokenizer.texts_to_sequences(X_test)
Si ve la X_train
variable en el explorador de variables, ver谩 que contiene 40.000 listas donde cada lista contiene n煤meros enteros. Cada lista corresponde realmente a cada oraci贸n del conjunto de entrenamiento. Tambi茅n notar谩 que el tama帽o de cada lista es diferente. Esto se debe a que las oraciones tienen diferentes longitudes.
Establecemos el tama帽o m谩ximo de cada lista en 100. Puede probar con un tama帽o diferente. Las listas con un tama帽o superior a 100 se truncar谩n a 100. Para las listas que tengan una longitud inferior a 100, agregaremos 0 al final de la lista hasta que alcance la longitud m谩xima. Este proceso se llama relleno.
El siguiente script encuentra el tama帽o del vocabulario y luego realiza el relleno tanto en el tren como en el conjunto de prueba.
# Adding 1 because of reserved 0 index
vocab_size = len(tokenizer.word_index) + 1
maxlen = 100
X_train = pad_sequences(X_train, padding='post', maxlen=maxlen)
X_test = pad_sequences(X_test, padding='post', maxlen=maxlen)
Ahora, si ve el X_train
o X_test
, ver谩 que todas las listas tienen la misma longitud, es decir, 100. Adem谩s, la vocabulary_size
variable ahora contiene un valor 92547 lo que significa que nuestro corpus tiene 92547 palabras 煤nicas.
Usaremos incrustaciones de GloVe para crear nuestra matriz de caracter铆sticas. En el siguiente script cargamos las incrustaciones de palabras GloVe y creamos un diccionario que contendr谩 palabras como claves y su correspondiente lista incrustada como valores.
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")
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()
Finalmente, crearemos una matriz de incrustaci贸n donde cada n煤mero de fila corresponder谩 al 铆ndice de la palabra en el corpus. La matriz tendr谩 100 columnas donde cada columna contendr谩 las incrustaciones de palabras GloVe para las palabras de nuestro corpus.
embedding_matrix = zeros((vocab_size, 100))
for word, index in tokenizer.word_index.items():
embedding_vector = embeddings_dictionary.get(word)
if embedding_vector is not None:
embedding_matrix[index] = embedding_vector
Una vez que ejecute el script anterior, ver谩 que embedding_matrix
contendr谩 92547 filas (una para cada palabra en el corpus). Ahora estamos listos para crear nuestros modelos de aprendizaje profundo.
Clasificaci贸n de texto con una red neuronal simple
El primer modelo de aprendizaje profundo que vamos a desarrollar es una simple red neuronal profunda. Mira el siguiente gui贸n:
model = Sequential()
embedding_layer = Embedding(vocab_size, 100, weights=[embedding_matrix], input_length=maxlen , trainable=False)
model.add(embedding_layer)
model.add(Flatten())
model.add(Dense(1, activation='sigmoid'))
En el script de arriba, creamos un Sequential()
modelo. A continuaci贸n, creamos nuestra capa de incrustaci贸n. La capa de incrustaci贸n tendr谩 una longitud de entrada de 100, la dimensi贸n del vector de salida tambi茅n ser谩 de 100. El tama帽o del vocabulario ser谩 de 92547 palabras. Puesto que no estamos entrenando a nuestros propios incrustaciones y el uso de la incrustaci贸n de guante, nos propusimos trainable
a False
y en el weights
atributo pasamos nuestra propia matriz de incrustaci贸n.
Luego, la capa de incrustaci贸n se agrega a nuestro modelo. A continuaci贸n, dado que estamos conectando directamente nuestra capa de incrustaci贸n a la capa densamente conectada, aplanamos la capa de incrustaci贸n. Finalmente, agregamos una capa densa con sigmoid
funci贸n de activaci贸n.
Para compilar nuestro modelo, usaremos el adam
optimizador, binary_crossentropy
como nuestra funci贸n de p茅rdida y accuracy
como m茅tricas y luego imprimiremos el resumen de nuestro modelo:
model.compile(optimizer="adam", loss="binary_crossentropy", metrics=['acc'])
print(model.summary())
La salida se ve as铆:
Layer (type) Output Shape Param #
=================================================================
embedding_1 (Embedding) (None, 100, 100) 9254700
_________________________________________________________________
flatten_1 (Flatten) (None, 10000) 0
_________________________________________________________________
dense_1 (Dense) (None, 1) 10001
=================================================================
Total params: 9,264,701
Trainable params: 10,001
Non-trainable params: 9,254,700
Dado que hay 92547 palabras en nuestro corpus y cada palabra se representa como un vector de 100 dimensiones, el n煤mero de par谩metros entrenables estar谩 92547x100
en la capa de incrustaci贸n. En la capa de aplanamiento, simplemente multiplicamos filas y columnas. Finalmente, en la capa densa el n煤mero de par谩metros es 10000 (de la capa de aplanamiento) y 1 para el par谩metro de polarizaci贸n, para un total de 10001.
Entrenemos ahora nuestro modelo:
history = model.fit(X_train, y_train, batch_size=128, epochs=6, verbose=1, validation_split=0.2)
En el scipt anterior, usamos el fit
m茅todo para entrenar nuestra red neuronal. Tenga en cuenta que estamos entrenando solo en nuestro tren. El validation_split
de 0,2 significa que el 20% de los datos de entrenamiento se utiliza para encontrar la precisi贸n de entrenamiento del algoritmo.
Al final del entrenamiento, ver谩 que la precisi贸n del entrenamiento es de alrededor del 85,52%.
Para evaluar el rendimiento del modelo, simplemente podemos pasar el conjunto de prueba al evaluate
m茅todo de nuestro modelo.
score = model.evaluate(X_test, y_test, verbose=1)
Para comprobar la precisi贸n y la p茅rdida de la prueba, ejecute el siguiente script:
print("Test Score:", score[0])
print("Test Accuracy:", score[1])
Una vez que ejecute el script anterior, ver谩 que obtenemos una precisi贸n de prueba del 74,68%. Nuestra precisi贸n de entrenamiento fue del 85,52%. Esto significa que nuestro modelo se adapta demasiado al conjunto de entrenamiento. El sobreajuste ocurre cuando su modelo se desempe帽a mejor en el conjunto de entrenamiento que en el conjunto de prueba. Idealmente, la diferencia de rendimiento entre el entrenamiento y los conjuntos de prueba deber铆a ser m铆nima.
Intentemos trazar las diferencias de p茅rdida y precisi贸n para conjuntos de entrenamiento y prueba. Ejecute el siguiente script:
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train','test'], loc="upper left")
plt.show()
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train','test'], loc="upper left")
plt.show()
Salida:
Puede ver claramente las diferencias de p茅rdida y precisi贸n entre los conjuntos de entrenamiento y prueba.
Clasificaci贸n de texto con una red neuronal convolucional
La red neuronal convolucional es un tipo de red que se utiliza principalmente para la clasificaci贸n de datos 2D, como im谩genes. Una red convolucional intenta encontrar caracter铆sticas espec铆ficas en una imagen en la primera capa. En las siguientes capas, las caracter铆sticas detectadas inicialmente se unen para formar caracter铆sticas m谩s grandes. De esta forma, se detecta toda la imagen.
Se ha descubierto que las redes neuronales convolucionales tambi茅n funcionan bien con datos de texto. Aunque los datos de texto son unidimensionales, podemos usar redes neuronales convolucionales 1D para extraer caracter铆sticas de nuestros datos. Para obtener m谩s informaci贸n sobre las redes neuronales convolucionales, consulte este art铆culo .
Creemos una red neuronal convolucional simple con 1 capa convolucional y 1 capa de agrupaci贸n. Recuerde, el c贸digo hasta la creaci贸n de la capa de incrustaci贸n seguir谩 siendo el mismo, ejecute el siguiente fragmento de c贸digo despu茅s de crear la capa de incrustaci贸n:
model = Sequential()
embedding_layer = Embedding(vocab_size, 100, weights=[embedding_matrix], input_length=maxlen , trainable=False)
model.add(embedding_layer)
model.add(Conv1D(128, 5, activation='relu'))
model.add(GlobalMaxPooling1D())
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer="adam", loss="binary_crossentropy", metrics=['acc'])
En el script anterior creamos un modelo secuencial, seguido de una capa de incrustaci贸n. Este paso es similar al que hab铆amos hecho antes. A continuaci贸n, creamos una capa convolucional unidimensional con 128 caracter铆sticas o n煤cleos. El tama帽o del kernel es 5 y la funci贸n de activaci贸n utilizada es sigmoid
. A continuaci贸n, agregamos una capa de agrupaci贸n m谩xima global para reducir el tama帽o de la entidad. Finalmente agregamos una capa densa con activaci贸n sigmoidea. El proceso de compilaci贸n es el mismo que en la secci贸n anterior.
Veamos ahora el resumen de nuestro modelo:
print(model.summary())
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
embedding_2 (Embedding) (None, 100, 100) 9254700
_________________________________________________________________
conv1d_1 (Conv1D) (None, 96, 128) 64128
_________________________________________________________________
global_max_pooling1d_1 (Glob (None, 128) 0
_________________________________________________________________
dense_2 (Dense) (None, 1) 129
=================================================================
Total params: 9,318,957
Trainable params: 64,257
Non-trainable params: 9,254,700
Puede ver que en el caso anterior no necesitamos aplanar nuestra capa de incrustaci贸n. Tambi茅n puede notar que el tama帽o de la entidad ahora se reduce usando la capa de agrupaci贸n.
Entrenemos ahora nuestro modelo y evalu茅moslo en el conjunto de entrenamiento. El proceso para entrenar y probar nuestro modelo sigue siendo el mismo. Para hacerlo, podemos usar los m茅todos fit
y evaluate
, respectivamente.
history = model.fit(X_train, y_train, batch_size=128, epochs=6, verbose=1, validation_split=0.2)
score = model.evaluate(X_test, y_test, verbose=1)
El siguiente script imprime los resultados:
print("Test Score:", score[0])
print("Test Accuracy:", score[1])
Si compara la precisi贸n del entrenamiento y la prueba, ver谩 que la precisi贸n del entrenamiento para CNN ser谩 de alrededor del 92%, que es mayor que la precisi贸n del entrenamiento de la red neuronal simple. La precisi贸n de la prueba es de alrededor del 82% para la CNN, que tambi茅n es mayor que la precisi贸n de la prueba para la red neuronal simple, que fue de alrededor del 74%.
Sin embargo, nuestro modelo de CNN todav铆a est谩 sobreajustado, ya que existe una gran diferencia entre la precisi贸n del entrenamiento y la prueba. Tracemos la p茅rdida y la diferencia de precisi贸n entre el entrenamiento y el conjunto de prueba.
import matplotlib.pyplot as plt
plt.plot(history.history['acc'])
plt.plot(history.history['val_acc'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train','test'], loc="upper left")
plt.show()
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train','test'], loc="upper left")
plt.show()
Salida:
Puede ver claramente las diferencias de p茅rdida y precisi贸n entre el tren y los equipos de prueba.
Entrenemos ahora nuestro tercer modelo de aprendizaje profundo, que es una red neuronal recurrente, y veamos si podemos deshacernos del sobreajuste.
Clasificaci贸n de texto con red neuronal recurrente (LSTM)
La red neuronal recurrente es un tipo de red neuronal que se ha demostrado que funciona bien con datos de secuencia. Dado que el texto es en realidad una secuencia de palabras, una red neuronal recurrente es una opci贸n autom谩tica para resolver problemas relacionados con el texto. En esta secci贸n, utilizaremos una LSTM (Red de memoria a largo plazo a corto plazo), que es una variante de RNN, para resolver el problema de clasificaci贸n de sentimientos.
Una vez m谩s, ejecute el c贸digo hasta la secci贸n de incrustaci贸n de palabras y luego ejecute el siguiente fragmento de c贸digo.
model = Sequential()
embedding_layer = Embedding(vocab_size, 100, weights=[embedding_matrix], input_length=maxlen , trainable=False)
model.add(embedding_layer)
model.add(LSTM(128))
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer="adam", loss="binary_crossentropy", metrics=['acc'])
En el script anterior, comenzamos inicializando un modelo secuencial seguido de la creaci贸n de la capa de incrustaci贸n. A continuaci贸n, creamos una capa LSTM con 128 neuronas (puedes jugar con la cantidad de neuronas). El resto del c贸digo es el mismo que para la CNN.
Tracemos el resumen de nuestro modelo.
print(model.summary())
El resumen del modelo se ve as铆:
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
embedding_3 (Embedding) (None, 100, 100) 9254700
_________________________________________________________________
lstm_1 (LSTM) (None, 128) 117248
_________________________________________________________________
dense_3 (Dense) (None, 1) 129
=================================================================
Total params: 9,372,077
Trainable params: 117,377
Non-trainable params: 9,254,700
Nuestro siguiente paso es entrenar el modelo en el conjunto de entrenamiento y evaluar su desempe帽o en el conjunto de prueba.
history = model.fit(X_train, y_train, batch_size=128, epochs=6, verbose=1, validation_split=0.2)
score = model.evaluate(X_test, y_test, verbose=1)
El script anterior entrena el modelo en el conjunto de prueba. El tama帽o del lote es 128, mientras que el n煤mero de 茅pocas es 6. Al final del entrenamiento, ver谩 que la precisi贸n del entrenamiento es de alrededor del 85,40%.
Una vez que se entrena el modelo, podemos ver los resultados del modelo en el conjunto de prueba con el siguiente script:
print("Test Score:", score[0])
print("Test Accuracy:", score[1])
En el resultado, ver谩 que la precisi贸n de nuestra prueba es de alrededor del 85,04%. La precisi贸n de la prueba es mejor que la CNN y la red neuronal densamente conectada. Adem谩s, podemos ver que hay una diferencia muy peque帽a entre la precisi贸n del entrenamiento y la precisi贸n de la prueba, lo que significa que nuestro modelo no est谩 sobreajustado.
Tracemos las diferencias de p茅rdida y precisi贸n entre los conjuntos de entrenamiento y de prueba.
import matplotlib.pyplot as plt
plt.plot(history.history['acc'])
plt.plot(history.history['val_acc'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train','test'], loc="upper left")
plt.show()
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train','test'], loc="upper left")
plt.show()
Salida:
El resultado muestra que la diferencia entre los valores de precisi贸n para los conjuntos de entrenamiento y prueba es mucho menor en comparaci贸n con la red neuronal simple y la CNN. Del mismo modo, la diferencia entre los valores de p茅rdida tambi茅n es insignificante, lo que demuestra que nuestro modelo no est谩 sobreajustado. Podemos concluir que para nuestro problema, RNN es el mejor algoritmo.
En este art铆culo, elegimos aleatoriamente el n煤mero de capas, neuronas, hiperpar谩metros, etc. Le sugiero que intente cambiar el n煤mero de capas, el n煤mero de neuronas y las funciones de activaci贸n para las tres redes neuronales discutidas en este art铆culo y ver cu谩l La red neuronal funciona mejor para ti.
Hacer predicciones en una sola instancia
Esta es la secci贸n final del art铆culo y aqu铆 veremos c贸mo hacer predicciones en una sola instancia o sentimiento. Recuperemos cualquier rese帽a de nuestro corpus y luego intentemos predecir su opini贸n.
Primero seleccionemos aleatoriamente cualquier revisi贸n de nuestro corpus:
instance = X[57]
print(instance)
Salida:
I laughed all the way through this rotten movie It so unbelievable woman leaves her husband after many years of marriage has breakdown in front of real estate office What happens The office manager comes outside and offers her job Hilarious Next thing you know the two women are going at it Yep they re lesbians Nothing rings true in this Lifetime for Women with nothing better to do movie Clunky dialogue like don want to spend the rest of my life feeling like had chance to be happy and didn take it doesn help There a wealthy distant mother who disapproves of her daughter new relationship sassy black maid unbelievable that in the year film gets made in which there a sassy black maid Hattie McDaniel must be turning in her grave The woman has husband who freaks out and wants custody of the snotty teenage kids Sheesh No cliche is left unturned
Puede ver claramente que esta es una revisi贸n negativa. Para predecir el sentimiento de esta revisi贸n, tenemos que convertir esta revisi贸n en forma num茅rica. Podemos hacerlo usando el tokenizer
que creamos en la secci贸n de incrustaci贸n de palabras. El text_to_sequences
m茅todo convertir谩 la oraci贸n en su contraparte num茅rica.
A continuaci贸n, necesitamos rellenar nuestra secuencia de entrada como hicimos con nuestro corpus. Finalmente, podemos usar el predict
m茅todo de nuestro modelo y pasarle nuestra secuencia de entrada procesada. Mira el siguiente c贸digo:
instance = tokenizer.texts_to_sequences(instance)
flat_list = []
for sublist in instance:
for item in sublist:
flat_list.append(item)
flat_list = [flat_list]
instance = pad_sequences(flat_list, padding='post', maxlen=maxlen)
model.predict(instance)
La salida se ve as铆:
array([[0.3304276]], dtype=float32)
Recuerde, asignamos las salidas positivas a 1 y las salidas negativas a 0. Sin embargo, la funci贸n sigmoidea predice un valor flotante entre 0 y 1. Si el valor es menor que 0.5, el sentimiento se considera negativo donde como si el valor fuera mayor que 0,5, el sentimiento se considera positivo. El valor de sentimiento para nuestra instancia 煤nica es 0.33, lo que significa que nuestro sentimiento se predice como negativo, que en realidad es el caso.
Conclusi贸n
La clasificaci贸n de texto es una de las tareas de procesamiento del lenguaje natural m谩s comunes. En este art铆culo vimos c贸mo realizar un an谩lisis de sentimientos, que es un tipo de clasificaci贸n de texto que utiliza la biblioteca de aprendizaje profundo de Keras. Usamos tres tipos diferentes de redes neuronales para clasificar la opini贸n p煤blica sobre diferentes pel铆culas. Los resultados muestran que LSTM, que es una variante de RNN, supera tanto a la CNN como a la red neuronal simple.