Análisis de sentimiento de frase usando redes neuronales

¡Hola a todos!

Sin embargo, todas las personas que reciben educación superior, sin ser expulsadas, alcanzan la etapa de escribir un diploma. No fui la excepción. Quería implementar algo interesante y dominar lo hasta ahora inexplorado, así que llamé la atención sobre el tema de las redes neuronales y la inteligencia artificial en general. Y la tarea que resolví con la ayuda es el análisis de la tonalidad del texto, que ya se usa ampliamente en varios sistemas de monitoreo. Intentaré describir el proceso de su solución en este artículo.

En resumen, el objetivo es comprender si una frase tiene una connotación positiva o negativa. Quiero decir de inmediato que este problema se puede resolver de varias maneras, y no solo mediante redes neuronales. Podemos hacer diccionarios en los que se marquen las posiciones de las palabras, etc. (todos los métodos están en abundancia en el centro), pero cada método puede ir más lejos de acuerdo con el artículo, por lo que dejaremos su revisión para más adelante.

Datos


La primera tarea en mi camino fue recopilar y preprocesar datos para capacitación. Un buen conjunto de datos para tal caso es el corpus de textos cortos de Y. Rubtsova, previamente divididos en oraciones negativas y positivas recopiladas en Twitter. Lo que es especialmente conveniente: todo esto existe en formato CSV.

Preparación de entrenamiento


Presta atención a la forma en que se presentan los datos: muchos emoticones, enlaces, caracteres innecesarios, aciertos. Todo esto no es información importante y solo interfiere con el aprendizaje, además, todo debe eliminarse en latín. Por lo tanto, el texto sería bueno para preprocesar.

def preprocessText(text):
    text = text.lower().replace("", "")
    text = re.sub('((www\.[^\s]+)|(https?://[^\s]+))', ' ', text)
    text = re.sub('@[^\s]+', ' ', text)
    text = re.sub('[^a-zA-Z--1-9]+', ' ', text)
    text = re.sub(' +', ' ', text)
    return text.strip()

Después de haber eliminado todas las oraciones del archivo, las llevamos a minúsculas, reemplazamos "" con "e", referencias, menciones, simplemente eliminamos las palabras en inglés por falta de significado. En resumen, los hacemos del mismo tipo, limpiando la "basura" que es superflua para el entrenamiento.

Herramientas


Por supuesto, si tiene una supercomputadora en casa, puede desplazarse más abajo en esta sección, buscando una parte interesante. Aconsejo al resto del servicio Google Colab , que le permite ejecutar Jupyter Notebooks (y que no lo han escuchado, para ayudar al motor de búsqueda) utilizando solo un navegador, y todo el trabajo se realiza en una máquina virtual en la nube.
El tamaño temporal de la sesión que se le da a trabajar está limitado a 12 horas; puede finalizar antes, después de lo cual todo se restablece.

Escribimos nuestro hermoso código


Como cualquier otro recién llegado al aprendizaje automático, elegí Python, porque es simple y las bibliotecas son una nube completa.

Primero, el administrador de paquetes ejecutará un comando importante, cuyo significado explicaré un poco más adelante.

imagen

A continuación, importamos las bibliotecas que usaremos al entrenar la cuadrícula y preparar los datos, creo que muchas de ellas le son familiares.

imagen

Finalmente al punto.

Entonces, ¿por qué descargamos e importamos la biblioteca de texto Tensorflow? El hecho es que las frases no se pueden "alimentar" a la cuadrícula en la forma en que nos sea legible. Aquí es donde entra Word Embedded, un término para el que no he encontrado una traducción adecuada y, en general, dudo de su existencia. Pero hablando en términos generales, estamos hablando de hacer coincidir un vector con una palabra. Esto está bien dicho aquí .

Necesitamos convertir oraciones completas en un vector, por lo que utilizamos una solución preparada de Google: Universal Sentence Encoder.

imagen

Puede descargarlo desde el centro aquí . Allí, por cierto, hay muchas más soluciones listas para usar que se pueden usar al aprender una red neuronal, para no molestarse.

imagen

Todos los tweets se clasifican por clase: malo / bueno. Creamos un marco de datos de pandas en el que están ordenados por clase (los malos no son visibles en la imagen, debido al hecho de que encajan).

imagen

Preparamos los datos: pasemos al modelo en sí. Para hacer esto, use el marco de Keras.

from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.models import Sequential, load_model
model = tf.keras.Sequential()

model.add(
  tf.keras.layers.Dense(
    units=256,
    input_shape=(X_train.shape[1], ),
    activation='relu'
  )
)
model.add(
  tf.keras.layers.Dropout(rate=0.5)
)

model.add(
  tf.keras.layers.Dense(
    units=128,
    activation='relu'
  )
)
model.add(
  tf.keras.layers.Dropout(rate=0.5)
)

model.add(tf.keras.layers.Dense(2, activation='softmax'))
model.compile(
    loss='categorical_crossentropy',
    optimizer=tf.keras.optimizers.Adam(0.001),
    metrics=['accuracy']
)

history = model.fit(
    X_train, y_train,
    epochs=10,
    batch_size=16,
    validation_split=0.1,
    verbose=1,
    shuffle=True
)

model.evaluate(X_test, y_test)

Un poco sobre el modelo en sí. Tiene capas de entrada, ocultas y de salida.

Cada capa tiene su propia función de activación.

Una pequeña explicación: en las redes neuronales artificiales, la función de activación neuronal determina la señal de salida, que está determinada por la señal de entrada o un conjunto de señales de entrada. Puede leer más aquí , por cierto, existen muchas para diferentes tareas, pero solo trabajaremos con 2. Asignamos la

función de activación ReLu a las 2 primeras capas . El día libre es Softmax .

Además de agregar capas, puede observar la palabra "Deserción". ¿Qué es? Por extraño que parezca, pero además del problema del subaprendizaje de una red neuronal, cuando sus predicciones no son ciertas, existe el problema del sobreentrenamiento: el modelo explica bien solo ejemplos de la muestra de entrenamiento, adaptándose a los ejemplos de entrenamiento, en lugar de aprender a clasificar ejemplos que no participaron en el entrenamiento. Eso es cursi con los nuevos datos, su hermosa modelo, que había hecho su trabajo magníficamente antes, simplemente "vuela" y comienza a sorprenderle desagradablemente. Así que Dropout está involucrado en el hecho de que con cierta probabilidad específica "desactiva" las neuronas de la red, de modo que dejan de participar en el proceso de aprendizaje. Luego se promedian los resultados de varias redes (cuando una neurona se excluye de la red, se obtiene una nueva).

Por cierto, un gran artículo para aquellos que estén interesados.

¡Puedes empezar a aprender!

Train on 53082 samples, validate on 5898 samples
Epoch 1/10
53082/53082 [==============================] - 12s 223us/sample - loss: 0.5451 - accuracy: 0.7207 - val_loss: 0.5105 - val_accuracy: 0.7397
Epoch 2/10
53082/53082 [==============================] - 11s 213us/sample - loss: 0.5129 - accuracy: 0.7452 - val_loss: 0.5000 - val_accuracy: 0.7523
Epoch 3/10
53082/53082 [==============================] - 11s 215us/sample - loss: 0.4885 - accuracy: 0.7624 - val_loss: 0.4914 - val_accuracy: 0.7538
Epoch 4/10
53082/53082 [==============================] - 11s 215us/sample - loss: 0.4686 - accuracy: 0.7739 - val_loss: 0.4865 - val_accuracy: 0.7589
Epoch 5/10
53082/53082 [==============================] - 11s 214us/sample - loss: 0.4474 - accuracy: 0.7889 - val_loss: 0.4873 - val_accuracy: 0.7616
Epoch 6/10
53082/53082 [==============================] - 11s 216us/sample - loss: 0.4272 - accuracy: 0.8004 - val_loss: 0.4878 - val_accuracy: 0.7603
Epoch 7/10
53082/53082 [==============================] - 11s 213us/sample - loss: 0.4081 - accuracy: 0.8111 - val_loss: 0.4986 - val_accuracy: 0.7594
Epoch 8/10
53082/53082 [==============================] - 11s 215us/sample - loss: 0.3899 - accuracy: 0.8241 - val_loss: 0.5101 - val_accuracy: 0.7564
Epoch 9/10
53082/53082 [==============================] - 11s 215us/sample - loss: 0.3733 - accuracy: 0.8315 - val_loss: 0.5035 - val_accuracy: 0.7633
Epoch 10/10
53082/53082 [==============================] - 11s 215us/sample - loss: 0.3596 - accuracy: 0.8400 - val_loss: 0.5239 - val_accuracy: 0.7620
6554/6554 [==============================] - 0s 53us/sample - loss: 0.5249 - accuracy: 0.7524
[0.5249265961105736, 0.752365]

Entonces, han pasado 10 eras. Para aquellos que no están familiarizados con tales conceptos, explicaré la definición de Internet: la era es una iteración en el proceso de aprendizaje, que incluye la presentación de todos los ejemplos del conjunto de entrenamiento y, posiblemente, verificar la calidad del entrenamiento en el conjunto de control. Entonces, todos nuestros datos pasaron 10 veces por completo durante todo el proceso.

Resultado


imagen

Por supuesto, la red se necesitará más de una vez y sería bueno saber cómo guardarla para la posteridad, para que no tengan que volver a entrenarla y todo eso.

La estructura se guarda en formato JSON y los pesos se escriben en un archivo h5 .

El motor de búsqueda está lleno de guías sobre cómo arrancar el proceso inverso de inicializar la red desde estos archivos, por lo que no lo describiré.

Usando el método de predicción, intentaremos encontrar la opinión de la red y el componente tonal de 2 frases obviamente diferentes a este respecto. Es cierto que aún deben reducirse primero a una forma matricial, pero ya sabemos cómo hacerlo utilizando una solución preparada.

En la salida, vemos 2 números: la probabilidad de que la frase pertenezca a las clases "negativas" / "positivas". Creo que la imagen muestra claramente que hay una diferencia) Así que al final palabras similares fueron y la red hizo un gran trabajo con su relación con sus clases.

Conclusión


Entonces, quiero decir que dominar herramientas avanzadas para desarrollar redes neuronales y resolver problemas simples, haber determinado correctamente los pasos necesarios para resolverlo y haber leído un poco la teoría, parece ser una tarea bastante fácil. Me gustaría señalar que vi varios artículos sobre el tema del análisis tonal en Habré, pero aún así fue interesante intentar algo más fácil y sin una gran cantidad de texto, aunque necesita estudiar la teoría incondicionalmente :)

Puede encontrar el código aquí si pone un asterisco en el proyecto, será genial. Si necesita archivos con pesos y estructura de red, así como datos procesados, escriba en los comentarios y agréguelos al repositorio.

All Articles