Logotipo de Zephyrnet

Análisis de sentimiento con LSTM

Fecha:

Este artículo fue publicado como parte del Blogatón de ciencia de datos.

Introducción

Sentiment Analysis es una aplicación de PNL que identifica el tono u opinión emocional o sentimental de un corpus de texto. Por lo general, las emociones o actitudes hacia un tema pueden ser positivas, negativas o neutrales. Esto hace que el análisis de sentimientos sea una tarea de clasificación de texto. Ejemplos de expresiones positivas, negativas y neutras son:

“¡Disfruté la película!” - Positivo

“No estoy seguro de si me gustó la película”. - Neutral

“Fue la película más terrible que he visto”. - Negativo

El análisis de sentimiento es una herramienta potente con diversas aplicaciones en todas las industrias. Es útil para el monitoreo de las redes sociales y la marca, la atención al cliente y el análisis de comentarios, la investigación de mercado, etc. Se puede identificar el público objetivo o los datos demográficos de un nuevo producto realizando un análisis de opinión sobre los comentarios iniciales recibidos de los clientes, y puede ayudar a evaluar el éxito de un producto. CAMPAÑA de Marketing. A medida que el análisis de sentimientos se vuelve cada vez más útil en la industria, se vuelve esencial para nosotros aprender a realizarlo. Este artículo sabrá cómo hacer un análisis de opinión sobre reseñas de películas utilizando LSTM.

 

¿Qué es el LSTM? 

Las redes neuronales recurrentes (RNN) son una forma de redes neuronales artificiales que pueden memorizar secuencias de patrones de entrada de longitud arbitraria mediante la captura de conexiones entre tipos de datos secuenciales. Sin embargo, debido a la falla de los gradientes estocásticos, los RNN no pueden detectar dependencias a largo plazo en secuencias largas. Se propusieron varios modelos RNN novedosos, en particular LSTM, para abordar este problema. Las redes LSTM son extensiones de RNN diseñadas para aprender datos secuenciales (temporales) y sus conexiones a largo plazo con mayor precisión que las RNN estándar. Se usan comúnmente en aplicaciones de aprendizaje profundo, como pronóstico de acciones, reconocimiento de voz, procesamiento de lenguaje natural, etc.

 

Cargando el conjunto de datos 

Realizaremos un análisis de sentimientos en 50 25 reseñas de películas de IMDB, y el conjunto de datos se equilibra con 25 XNUMX reseñas de películas positivas y XNUMX XNUMX negativas. Puede descargar el conjunto de datos de haga clic aquí Comenzamos con la importación de los paquetes necesarios para la manipulación de texto y la construcción de modelos.

importar re importar pandas como pd importar numpy como np de sklearn.preprocessing importar LabelEncoder de sklearn.model_selection importar train_test_split de keras.preprocessing.text importar Tokenizer de keras.preprocessing.sequence importar pad_sequences importar keras de sklearn.metrics importar Classification_report de sklearn.metrics importar precision_score importar matemáticas importar nltk

Cargamos el conjunto de datos en un marco de datos de pandas con la ayuda del siguiente código:

datos = pd.read_csv('IMDB Dataset.csv') datos

Los datos se ven así:

Análisis de sentimiento con LSTM

Fuente: Captura de pantalla de mi Jupyter Notebook

 

Preprocesamiento de datos

Primero, debemos eliminar las etiquetas HTML, las URL y los caracteres no alfanuméricos de las reseñas. Hacemos eso con la ayuda de la función remove_tags, y las funciones Regex se usan para una fácil manipulación de cadenas.

def eliminar_etiquetas(cadena): eliminarlista = "" resultado = re.sub('','',cadena) #eliminar etiquetas HTML resultado = re.sub('https://.*','',resultado) #eliminar URLs result = re.sub(r'[^w'+removelist+']', ' ',result) #eliminar caracteres no alfanuméricos result = result.lower() return result data['review']=data['review '].apply(lambda cw : remove_tags(cw))

También necesitamos eliminar las palabras vacías del corpus. Las palabras vacías son palabras de uso común como 'y', 'el', 'en' que no agregan ningún significado o importancia especial a una oración. Hay disponible una lista de palabras vacías con nltk, y se pueden eliminar del corpus usando el siguiente código:

nltk.download('stopwords') from nltk.corpus import stopwords stop_words = set(stopwords.words('english')) data['review'] = data['review'].apply(lambda x: ' .join ([palabra por palabra en x.split() si la palabra no está en (stop_words)]))

Ahora realizamos la lematización del texto. La lematización es una técnica útil en PNL para obtener la raíz de las palabras, conocida como lemas. Por ejemplo, el lema de las palabras leyendo, lee, lee es leído. Esto ayuda a ahorrar una sobrecarga computacional innecesaria al tratar de descifrar palabras completas, ya que los significados de la mayoría de las palabras están bien expresados ​​por sus lemas separados. Realizamos la lematización usando WordNetLemmatizer() de nltk. El texto primero se divide en palabras individuales utilizando WhitespaceTokenizer() de nltk. Escribimos una función lematizar_texto para realizar la lematización de los tokens individuales.

w_tokenizer = nltk.tokenize.WhitespaceTokenizer() lemmatizer = nltk.stem.WordNetLemmatizer() def lemmatize_text(text): st = "" for w in w_tokenizer.tokenize(text): st = st + lemmatizer.lemmatize(w) + " " return st data['review'] = data.review.apply(lemmatize_text) data

Los datos procesados ​​se ven así:

Análisis de sentimiento con LSTM
Fuente: Captura de pantalla de mi Jupyter Notebook

A continuación, imprimimos algunas estadísticas básicas sobre el conjunto de datos y verificamos si el conjunto de datos está equilibrado o no (igual número de todas las etiquetas). Idealmente, el conjunto de datos debe estar equilibrado porque un conjunto de datos severamente desequilibrado puede ser un desafío para modelar y requiere técnicas especializadas.

s = 0.0 for i in data['review']: word_list = i.split() s = s + len(word_list) print("Extensión promedio de cada revisión: ",s/data.shape[0]) pos = 0 for i in range(data.shape[0]): if data.iloc[i]['sentiment'] == 'positive': pos = pos + 1 neg = data.shape[0]-pos print(" El porcentaje de opiniones positivas es "+str(pos/data.shape[0]*100)+"%") print("El porcentaje de opiniones negativas es "+str(neg/data.shape[0]* 100)+"%") >>Promedio de duración de cada reseña: 119.57112 >>El porcentaje de reseñas con sentimiento positivo es 50.0% >>El porcentaje de reseñas con sentimiento negativo es 50.0%

Codificación de etiquetas y realización de divisiones de prueba de tren

Usamos LabelEncoder() de sklearn.preprocessing para convertir las etiquetas ('positiva', 'negativa') en 1 y 0 respectivamente.

reseñas = datos['revisión'].valores etiquetas = datos['sentimiento'].valores codificador = LabelEncoder() etiquetas_codificados = codificador.fit_transform(etiquetas)

Finalmente, dividimos el conjunto de datos en partes de entrenamiento y prueba usando train_test_split de sklearn.model_selection. Usamos el 80% del conjunto de datos para entrenamiento y el 20% para pruebas.

entrenar_frases, probar_frases, entrenar_etiquetas, probar_etiquetas = entrenar_prueba_dividir(revisiones, codificar_etiquetas, estratificar = codificar_etiquetas)

Antes de ingresar al modelo LSTM, los datos deben completarse y tokenizarse:

  • Tokenización: La API tokenizadora incorporada de Keras se ha ajustado al conjunto de datos, que divide las oraciones en palabras y crea un diccionario de todas las palabras únicas encontradas y sus números enteros asignados de forma única. Cada oración se convierte en una matriz de números enteros que representan todas las palabras individuales presentes en ella.
  • Relleno de secuencia: La matriz que representa cada oración en el conjunto de datos se llena con ceros a la izquierda para hacer que el tamaño de la matriz sea diez y que todas las colecciones tengan la misma longitud.
# Hiperparámetros del modelo vocab_size = 3000 # elegir basado en estadísticas oov_tok = '' embedding_dim = 100 max_length = 200 # elegir basado en estadísticas, por ejemplo 150 a 200 padding_type='post' trunc_type='post' # tokenizar oraciones tokenizer = Tokenizer (num_words = vocab_size, oov_token=oov_tok) tokenizer.fit_on_texts(train_sentences) word_index = tokenizer.word_index # convertir el conjunto de datos de tren en secuencia y completar secuencias train_sequences = tokenizer.texts_to_sequences(train_sentences) train_padded = pad_sequences(train_sequences, padding='post', maxlen =longitud_máxima) # convertir el conjunto de datos de prueba en secuencia y completar secuencias test_sequences = tokenizer.texts_to_sequences(test_sentences) test_padded = pad_sequences(test_sequences, padding='post', maxlen=max_length)

Construyendo el modelo

Se construye un modelo secuencial de Keras. Es una pila lineal de las siguientes capas:

  •  Una capa incrustada de dimensión 100 convierte cada palabra de la oración en un vector denso de longitud fija de tamaño 100. La dimensión de entrada se establece como el tamaño del vocabulario y la dimensión de salida es 100. Por lo tanto, cada palabra de la entrada será representada por un vector de tamaño 100.
  • Una capa LSTM bidireccional de 64 unidades.
  • Una capa densa (totalmente conectada) de 24 unidades con activación relu.
  • Una capa densa de 1 unidad y salidas de activación sigmoidea la probabilidad de que la revisión sea positiva, es decir, si la etiqueta es 1.

El código para construir el modelo:

# modelo de inicialización modelo = keras.Sequential([ keras.layers.Embedding(vocab_size, embedding_dim, input_length=max_length), keras.layers.Bidireccional(keras.layers.LSTM(64)), keras.layers.Dense(24, activación ='relu'), keras.layers.Dense(1, activación='sigmoide') ]) # compile model model.compile(loss='binary_crossentropy', Optimizer='adam', metrics=['accuracy']) # resumen del modelo model.summary()

El modelo se compila con pérdida de entropía cruzada binaria y optimizador Adam. Dado que tenemos un problema de clasificación binaria, se utiliza la pérdida de entropía cruzada binaria. El optimizador de Adam utiliza el descenso de gradiente estocástico para entrenar modelos de aprendizaje profundo y compara cada una de las probabilidades predichas con la etiqueta de clase real (0 o 1). La precisión se utiliza como la métrica de rendimiento principal. El resumen del modelo se puede ver a continuación:

Construyendo el modelo

Fuente: Captura de pantalla de mi Jupyter Notebook

 

Capacitación y evaluación de modelos

El modelo está entrenado para cinco épocas.

num_epochs = 5 history = model.fit(train_padded, train_labels, epochs=num_epochs, detallado=1, validation_split=0.1)

El modelo se evalúa calculando su precisión. La precisión de la clasificación se calcula dividiendo el número de predicciones correctas por el número total de predicciones.

predicción = model.predict(test_padded) # Obtener etiquetas basadas en probabilidad 1 si p>= 0.5 else 0 pred_labels = [] para i en predicción: if i >= 0.5: pred_labels.append(1) else: pred_labels.append(0 ) print("Precisión de la predicción en el conjunto de prueba: ", precision_score(test_labels,pred_labels))

¡La precisión de la predicción en el conjunto de prueba resulta ser del 87.27 %! Puede mejorar aún más la precisión jugando con los hiperparámetros del modelo, ajustando aún más la arquitectura del modelo o cambiando la relación de división de la prueba del tren. También debe entrenar el modelo para un número más significativo de épocas, y nos detuvimos en cinco épocas debido al tiempo computacional. Idealmente, ayudaría a preparar el modelo hasta que converjan las pérdidas del tren y de la prueba.

 

Usar el modelo para determinar el sentimiento de las reseñas de películas no vistas

Podemos usar nuestro modelo entrenado para determinar el sentimiento de nuevas reseñas de películas no vistas que no están presentes en el conjunto de datos. Cada nuevo texto debe tokenizarse y rellenarse antes de alimentarse como entrada al modelo. La función model.predict() devuelve la probabilidad de una revisión positiva. Si la probabilidad es mayor a 0.5, consideramos que el estudio es positivo, en caso contrario negativo.

# reseñas en las que necesitamos predecir la oración = ["La película fue muy conmovedora y conmovedora", "Nunca había visto una película terrible como esta", "la trama de la película es terrible pero tuvo una buena actuación"] # convert to una secuencia secuencias = tokenizer.texts_to_sequences(sentence) # rellenar la secuencia padded = pad_sequences(sequences, padding='post', maxlen=max_length) # Obtener etiquetas basadas en la probabilidad 1 si p>= 0.5 sino 0 predicción = model.predict( padded) pred_labels = [] for i en predicción: if i >= 0.5: pred_labels.append(1) else: pred_labels.append(0) for i in range(len(oración)): print(oración[i]) if pred_labels[i] == 1: s = 'Positivo' else: s = 'Negativo' print("Sentimiento previsto: ",s)

¡La salida parece muy prometedora!

Fuente: Captura de pantalla de mi Jupyter Notebook

 

Conclusión

El análisis de opinión, como cualquier otra tarea de clasificación, se puede realizar con muchos modelos diferentes de aprendizaje automático y aprendizaje profundo, como Naive Bayes, KNN, SVM o CNN, ANN, etc. Ahora que conoce sus conceptos básicos, continúe y explore otros modelos para realizar análisis de sentimientos.

Gracias por leer.

Puedes leer esta página sobre cómo usar las CNN para la clasificación de texto!

Siéntase libre de conectarse conmigo por correo electrónico: GME@dhr-rgv.com

Los medios que se muestran en este artículo no son propiedad de Analytics Vidhya y se utilizan a discreción del autor. 

Fuente: https://www.analyticsvidhya.com/blog/2022/01/sentiment-analysis-with-lstm/

punto_img

Información más reciente

punto_img