Una de las aplicaciones principales del aprendizaje automático es el análisis de sentimientos. El análisis de sentimientos en aprendizaje automático se trata de juzgar el tono de un documento.
La salida de un análisis de sentimiento en aprendizaje automático suele ser una puntuación entre cero y uno, donde uno significa que el tono es muy positivo y cero significa que es muy negativo. El análisis de sentimientos se utiliza con frecuencia para el comercio.
Por ejemplo, el análisis de sentimientos en aprendizaje automático se aplica a los tweets de los comerciantes para estimar el estado de ánimo general del mercado.
Como podría esperarse, el análisis de sentimientos en aprendizaje automático es un problema de procesamiento del lenguaje natural (PNL).
La PNL es un campo de inteligencia artificial relacionado con la comprensión y el procesamiento del lenguaje. El objetivo de este artículo será construir un modelo para derivar el significado semántico de las palabras a partir de documentos en el corpus.
En un nivel alto, uno puede imaginarnos clasificando los documentos con la palabra buena en ellos como positiva y la palabra mala como negativa. Desafortunadamente, el problema no es tan sencillo, ya que las palabras pueden ir precedidas de no como en no es bueno.
Código
Es suficiente para adentrarnos en algún código.
import número by np desde matplotlib importar pyplot como plt plt.style.use ('dark_background') from keras.datasets import imdb from keras.models import Sequential from keras.preprocessing.sequence import pad_sequences from keras.layers import Embedding, GlobalAveragePooling1D, Dense
El argumento num_words = 10000 garantiza que solo mantendremos las 100 palabras más frecuentes en el conjunto de entrenamiento. Las palabras raras se descartan para mantener el tamaño de los datos manejables.
num_words = 10000
Usaremos el conjunto de datos IMDB que contiene el texto de 50,000 reseñas de películas de Internet Movie Database. Los últimos se dividen en 25,000 revisiones para entrenamiento y 25,000 revisiones para pruebas. Los conjuntos de entrenamiento y prueba son balanceados lo que significa que contienen un número igual de críticas positivas y negativas.
old = np.load np.load = lambda * a, ** k: old (* a, ** k, allow_pickle = True) (X_train, y_train), (X_test, y_test) = imdb.load_data (num_words = num_words) np.load = old del (old)
print ("Entrenamientos: {}, etiquetas: {}". Formato (len (X_train), len (y_train)))
Cuando usamos keras.datasets.imdb para importar el conjunto de datos a nuestro programa, ya viene preprocesado.
En otras palabras, cada ejemplo es una lista de enteros donde cada entero representa una palabra específica en un diccionario y cada etiqueta es un valor entero de 0 o 1, donde 0 es una revisión negativa y 1 es una revisión positiva.
Tomemos un pico en la primera revisión.
print (X_train [0])
Para obtener un mayor conocimiento de lo que estamos trabajando, crearemos una función de ayuda para asignar los enteros en cada ejemplo de entrenamiento a las palabras en el índice.
word_index = imdb.get_word_index ()
# Los primeros índices están reservados word_index = {k: (v + 3) para k, v en word_index.items ()) word_index [""] = 0 word_index [""] = 1 word_index [""] = 2 # unknown word_index [" "] = 3
reverse_word_index = dict ([(value, key) for (key, value) in word_index.items()])
def decode_review (text): return ''.join ([reverse_word_index.get(i, '?') for i in text])
Ahora, podemos usar la función decode_review para mostrar el texto de la primera revisión.
decode_review (X_train [0])
Dado que cada palabra en un documento se interpretará como una característica, debemos asegurarnos de que las reseñas de películas tengan la misma duración antes de intentar introducirlas en una red neuronal.
len (X_train [0]), len (X_train [1])
Nosotros utilizará la función pad_sequence para estandarizar las longitudes.
X_train = pad_sequences ( X_train, value = word_index [""] padding = 'post', maxlen = 256 )
X_test = pad_sequences ( X_test, value = word_index [""] padding = 'post', maxlen = 256 )
Veamos la longitud del primer par de muestras.
len (X_train [0]), len (X_train [19459050))
Como el lector en sintonía podría haberlo leído Y adivinado, las palabras son características categóricas. Como tal, no podemos introducirlos directamente en la red neuronal.
Aunque ya están codificados como enteros, si los dejamos como están, el modelo interpretaría que los enteros con valores más altos tienen una prioridad más alta que los que tienen valores más bajos.
Normalmente, evitará este problema convirtiendo los arreglos en vectores de 0s y 1s que indican la aparición de palabras, similar a una codificación activa, pero para palabras, esto requiere mucha memoria.
Dado un vocabulario de 10,000 palabras, tendríamos que almacenar num_words * matriz de tamaño de identificación media en la RAM.
Incrustaciones
Aquí es donde entran las incrustaciones para jugar. Las incrustaciones resuelven los problemas centrales de los datos de entrada dispersos (vectores muy grandes con relativamente pocos valores distintos de cero).
Mediante el mapeo de nuestros datos de alta dimensión en un espacio de dimensión inferior (similar a PCA).
corpus compuesto por las siguientes dos oraciones.
- Espero verte pronto
- Es bueno verte de nuevo
Al igual que el conjunto de datos de IMDB, podemos asignar a cada palabra un número entero único.
[0, 1, 2, 3, 4] [5, 1, 2, 3, 6]
A continuación, podemos definir una capa de incrustación.
Incrustar (input_dim = 7, output_dim = 2, input_length = 5)
- input_dim El tamaño del vocabulario ( es decir, número de palabras distintas) en el conjunto de entrenamiento
- output_dim : El tamaño de los vectores de inserción
- input_length : El número de características en una muestra (es decir, el número de palabras en cada documento). Por ejemplo, si todos nuestros documentos constan de 1000 palabras, la longitud de entrada sería 1000.
Las incrustaciones funcionan como una tabla de consulta. Cada token (es decir, palabra) actúa como un índice que almacena un vector.
Cuando se le da un token a la capa de incrustación, devuelve el vector asociado a ese token y lo pasa a través de la red neuronal. A medida que la red se entrena, las incrustaciones también se optimizan.
+ ------------ + ------------ + | índice | Incrustación | + ------------ + ------------ + | 0 | [1.2, 3.1] | | 1 | [0.1, 4.2] | | 2 | [1.0, 3.1] | | 3 | [0.3, 2.1] | | 4 | [2.2, 1.4] | | 5 | [0.7, 1.7] | | 6 | [4.1, 2.0] | + ------------ + ------------ +
Supongamos que tenemos el siguiente vector de incrustación bidimensional para la palabra Profesor .
Podemos imaginar un espacio bidimensional donde se agrupan palabras similares (es decir, escuela, tutor).
En nuestro ejemplo, usamos vectores de incrustación con 16 dimensiones. Por lo tanto, podemos encontrar que las palabras disfrutadas, gustadas y fantásticas están muy cerca unas de otras. Nuestro modelo puede luego aprender a clasificar las revisiones cuyas palabras se corresponden con vectores incrustados que están cerca uno del otro en el espacio de 16 dimensiones como positivo.
model = Sequential () model.add (Embedding (input_dim == num_words) , output_dim = 16, input_length = 256)) model.add (GlobalAveragePooling1D ()) model.add (Dense (16, activation = 'relu')) model.add (Denso (1, activación = 'sigmoide' ))
model.summary ()
Utilizamos adam como nuestro optimizador y binario crossentropy como nuestra función de pérdida, ya que estamos tratando de elegir entre dos clases.
model.compile ( optimizer = 'adam', loss = 'binary_crossentropy', métricas = ['accuracy'] )
Apartamos el diez por ciento de nuestros datos para validación. Cada época, 512 revisiones pasan por la red neuronal antes de actualizar las ponderaciones.
history = model.fit ( X_train, y_train, epochs = 20, batch_size = 512, validation_split = 0.1, shuffle = True )
Podemos graficar la precisión y pérdida de entrenamiento y validación en cada época mediante el uso de la variable de historial devuelta por la función ajuste .
pérdida = historia.historia [‘loss’]
val_loss = historia.historia [‘val_loss’]
épocas = rango (1, len (pérdida) + 1)
plt.plot (épocas, pérdida, ‘ y’, label =’Pérdida de entrenamiento’)
plt.plot (epochs, val_loss, ‘r’, label = ‘Pérdida de validación’)
plt.title (‘Pérdida de entrenamiento y validación’)
plt.xlabel (‘Épocas’)
plt.ylabel (‘Pérdida’)
plt. legend ()
plt.show ()
acc = history.history ['acc'] val_acc = history.history ['val_acc'] plt.plot (epochs, acc, 'y', label = 'Training acc') plt.plot (epochs, val_acc, 'r', label = 'Validation acc') plt.title ('Exactitud de validación y entrenamiento') plt.xlabel ('Epochs') plt.ylabel ('Accuracy') plt.legend () plt.show ()
Finalmente, veamos qué tan bien funciona nuestro modelo en el conjunto de pruebas.
test_loss, test_acc = model.evaluate (X_test, y_test) print (test_acc)
Pensamientos finales
Cuando trabajamos con características categóricas con muchas categorías (es decir, palabras), queremos evitar el uso de una codificación activa, ya que nos exige almacenar una matriz grande en la memoria y entrenar muchos parámetros.
En su lugar, podemos mapear cada categoría a un vector de incrustación de dimensión n y entrenar nuestro modelo de aprendizaje automático utilizando los vectores de inserción como entrada.
Análisis del sentimiento de aprendizaje automático e incrustaciones de palabras Ejemplo original de Python Keras en Hacia la ciencia de datos en Medium, donde las personas continúan la conversación resaltando y respondiendo a esta historia.