Python para NLP: An谩lisis de Sentimientos de Pel铆culas usando Deep Learning en Keras

    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

    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_tagsfunci贸n simplemente reemplaza cualquier cosa entre abrir y cerrar <>con un espacio vac铆o.

    A continuaci贸n, en la preprocess_textfunci贸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_splitm茅todo del sklearn.model.selectionm贸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 Tokenizerclase del keras.preprocessing.textm贸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_trainvariable 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_traino X_test, ver谩 que todas las listas tienen la misma longitud, es decir, 100. Adem谩s, la vocabulary_sizevariable 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_matrixcontendr谩 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 trainablea Falsey en el weightsatributo 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 sigmoidfunci贸n de activaci贸n.

    Para compilar nuestro modelo, usaremos el adamoptimizador, binary_crossentropycomo nuestra funci贸n de p茅rdida y accuracycomo 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谩 92547x100en 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 fitm茅todo para entrenar nuestra red neuronal. Tenga en cuenta que estamos entrenando solo en nuestro tren. El validation_splitde 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 evaluatem茅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 fity 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 tokenizerque creamos en la secci贸n de incrustaci贸n de palabras. El text_to_sequencesm茅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 predictm茅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.

     

    Etiquetas:

    Deja una respuesta

    Tu direcci贸n de correo electr贸nico no ser谩 publicada. Los campos obligatorios est谩n marcados con *