Рубрики
Без рубрики

Глубокое погружение в слов вложения для анализа настроений

Автор оригинала: Bert Carremans.

При нанесении одно горячего кодирования к словам, мы в конечном итоге с редким (содержащим многие нули) векторов высокой размерности. На больших наборах данных это может вызвать проблемы с производительностью.

Кроме того, одно горячее кодирование не учитывает семантику слов. Так такие слова, как Самолет и самолет считаются двумя разными чертами, пока мы знаем, что у них очень похожее значение. Слово встроенные вложения обращаются к этим двум вопросам.

Слово встроенные плотные векторы с гораздо более низкой размерностью. Во-вторых, семантические отношения между словами отражаются на расстоянии и направлении векторов.

Мы будем работать с Данные в TwitterlinesEntiment набор на Kaggle Отказ Этот набор данных содержит примерно 15К твиты с 3 возможными классами для настроения (положительный, отрицательный и нейтральный). В моем предыдущем посте мы пытались классифицировать твиты токенизируя слова и применяя две классификаторы. Давайте посмотрим, сможете ли слов встроенные вложения, которые могут превзойти.

После прочтения этого руководства вы будете знать, как вычислить, специфичные для задач Word Embeddings с помощью слоя встраивания Керас Отказ Во-вторых, мы рассмотрим, будет ли слов вложений, обученных на более крупном корпусе, может улучшить точность нашей модели.

Структура этого учебника:

  • Интуиция за словными вложениями
  • Настройка проекта
  • Подготовка данных
  • KERAS и его слой вложения
  • Предварительно обученные слов встраивания – перчатка
  • Учебные вложения слова с большим количеством измерений

Прежде чем мы сможем использовать слова в классификаторе, нам нужно преобразовать их в цифры. Один из способов сделать это, чтобы просто отобразить слова для целых чисел. Другой способ – это одно горячие кодировать слова. Затем каждый Tweet может быть представлен как вектор с измерением, равным (ограниченным набором) слов в корпусе. Слова, происходящие в Tweet, имеют значение 1 в векторе. Все остальные векторные значения равны нулю.

Слово вложения вычисляются по-разному. Каждое слово расположено в многомерное пространство Отказ Количество размеров в этом пространстве выбирается ученым данных. Вы можете экспериментировать с разными размерами и посмотреть, что обеспечивает лучший результат.

Векторные значения для слова представляют его позицию в этом пространстве вложения. Синонимы найдены близко друг к другу, а слова с противоположными значениями имеют большое расстояние между ними. Вы также можете применять математические операции на векторах, которые должны производить семантически правильные результаты. Типичным примером является то, что сумма слов вложений король и Женский производит слово встраивание королева Отказ

Давайте начнем, импортируя все пакеты для этого проекта.

import pandas as pd
import numpy as np
import re
import collections
import matplotlib.pyplot as plt
from pathlib import Path
from sklearn.model_selection import train_test_split
from nltk.corpus import stopwords
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences
from keras.utils.np_utils import to_categorical
from sklearn.preprocessing import LabelEncoder
from keras import models
from keras import layers

Мы определяем некоторые параметры и пути, используемые по всему проекту. Большинство из них являются самоуверенностью. Но другие будут объяснены дальше в коде.

NB_WORDS = 10000  # Parameter indicating the number of words we'll put in the dictionary
VAL_SIZE = 1000  # Size of the validation set
NB_START_EPOCHS = 10  # Number of epochs we usually start to train with
BATCH_SIZE = 512  # Size of the batches used in the mini-batch gradient descent
MAX_LEN = 24  # Maximum number of words in a sequence
GLOVE_DIM = 100  # Number of dimensions of the GloVe word embeddings
root = Path('../')
input_path = root / 'input/'
ouput_path = root / 'output/'
source_path = root / 'source/'

На протяжении всего этого кода мы также будем использовать некоторые функции помощника для приготовления данных, моделирования и визуализации. Эти определения функций не отображаются здесь, чтобы сохранить бесплатное беспорядок в блоге. Вы всегда можете обратиться к Блокнот в Github посмотреть на код.

Чтение данных и уборка

Мы читаем в файле CSV с твитами и применяем случайное перемещение на его индексы. После этого мы удаляем остановки слов и @ упоминания. Тестовый набор из 10% разделен для оценки модели на новые данные.

df = pd.read_csv(input_path / 'Tweets.csv')
df = df.reindex(np.random.permutation(df.index))
df = df[['text', 'airline_sentiment']]
df.text = df.text.apply(remove_stopwords).apply(remove_mentions)
X_train, X_test, y_train, y_test = train_test_split(df.text, df.airline_sentiment, test_size=0.1, random_state=37)

Преобразуйте слова в целые числа

С Токенизатор От кера, мы преобразуем твиты в последовательности целых чисел. Мы ограничиваем количество слов для Nb_words самые частые слова. Кроме того, твиты очищаются с некоторыми фильтрами, установлены на строчные и разделенные на пробелы.

tk = Tokenizer(num_words=NB_WORDS,
filters='!"#$%&()*+,-./:;<=>?@[\]^_`{"}~\t\n',lower=True, split=" ")
tk.fit_on_texts(X_train)
X_train_seq = tk.texts_to_sequences(X_train)
X_test_seq = tk.texts_to_sequences(X_test)

Равная длина последовательностей

Каждая партия должна обеспечивать последовательности равной длины. Мы достигаем этого с PAD_SESCENCENS метод. Указав Maxlen последовательности или дополнены нулями или усечены.

X_train_seq_trunc = pad_sequences(X_train_seq, maxlen=MAX_LEN)
X_test_seq_trunc = pad_sequences(X_test_seq, maxlen=MAX_LEN)

Кодирование целевой переменной

Целевые классы – это строки, которые необходимо преобразовать в числовые векторы. Это делается с LabelenCoder от Sklearn и to_categrical Метод от кера.

le = LabelEncoder()
y_train_le = le.fit_transform(y_train)
y_test_le = le.transform(y_test)
y_train_oh = to_categorical(y_train_le)
y_test_oh = to_categorical(y_test_le)

Разделение набора валидации

Из учебных данных мы разделили набор валидации на 10% во время обучения.

X_train_emb, X_valid_emb, y_train_emb, y_valid_emb = train_test_split(X_train_seq_trunc, y_train_oh, test_size=0.1, random_state=37)

Кера и слой вложения

KERAS предоставляет удобный способ преобразовать каждое слово в многомерный вектор. Это можно сделать с Встраивание слой. Он вычисляет слов вложения (или использовать предварительно обученные вложения) и посмотреть каждое слово в словаре, чтобы найти его векторное представление. Здесь мы будем тренировать слово вложения с 8 измерениями.

emb_model = models.Sequential()
emb_model.add(layers.Embedding(NB_WORDS, 8, input_length=MAX_LEN))
emb_model.add(layers.Flatten())
emb_model.add(layers.Dense(3, activation='softmax'))
emb_history = deep_model(emb_model, X_train_emb, y_train_emb, X_valid_emb, y_valid_emb)

У нас есть точность валидации около 74%. Количество слов в твитах достаточно низко, поэтому этот результат довольно хороший. Сравнивая убыток обучения и валидации, мы видим, что модель начинается переоборудование из эпохи 6.

В предыдущей статье я обсуждал, как мы можем избежать переоценки. Вы можете прочитать, что если вы хотите глубоко погружаться на эту тему.

Когда мы тренируем модель на всех данных (включая данные проверки, но исключая данные теста) и устанавливаем количество эпохи на 6, мы получаем точность тестирования 78%. Этот результат теста в порядке, но давайте посмотрим, сможем ли мы улучшить с предварительно обученным словом встраивания.

emb_results = test_model(emb_model, X_train_seq_trunc, y_train_oh, X_test_seq_trunc, y_test_oh, 6)
print('/n')
print('Test accuracy of word embeddings model: {0:.2f}%'.format(emb_results[1]*100))

Предварительно обученные слов встраивания – перчатка

Поскольку данные тренировок не столь большие, модель может быть не в состоянии изучать хорошие вложения для анализа настроения. В качестве альтернативы, мы можем загрузить предварительно обученные вложения Word, построенные на гораздо большего тренировочных данных.

База данных Glove Содержит несколько предварительно обученных слов в подавлениях и более конкретных Встраивания обучены на твитах Отказ Так что это может быть полезно для задачи под рукой.

Во-первых, мы поместим слово вставки в словарь, где ключи являются словами и значениями встроенные слова.

glove_file = 'glove.twitter.27B.' + str(GLOVE_DIM) + 'd.txt'
emb_dict = {}
glove = open(input_path / glove_file)
for line in glove:
    values = line.split()
    word = values[0]
    vector = np.asarray(values[1:], dtype='float32')
    emb_dict[word] = vector
glove.close()

С встраиванию перчатки, загруженные в словаре, мы можем посмотреть в встраивание для каждого слова в корпусе твитов авиакомпании. Они будут храниться в матрице с формой Nb_words и Glove_dim Отказ Если в словаре перчатка не найден в словаре перчатки, слово встраивается в слово для слова равен нулю.

emb_matrix = np.zeros((NB_WORDS, GLOVE_DIM))
for w, i in tk.word_index.items():
    if i < NB_WORDS:
        vect = emb_dict.get(w)
        if vect is not None:
        emb_matrix[i] = vect
    else:
        break

Затем мы указываем модель так, как мы сделали с моделью выше.

glove_model = models.Sequential()
glove_model.add(layers.Embedding(NB_WORDS, GLOVE_DIM, input_length=MAX_LEN))
glove_model.add(layers.Flatten())
glove_model.add(layers.Dense(3, activation='softmax'))

В слое вложения (который здесь слой 0) мы Установите вес Для слов, которые можно найти в перчатке слов вложения. Установка тренируемый Чтобы ложь мы убедимся, что встроенные вложения перчатки не могут быть изменены. После этого мы запускаем модель.

glove_model.layers[0].set_weights([emb_matrix])
glove_model.layers[0].trainable = False
glove_history = deep_model(glove_model, X_train_emb, y_train_emb, X_valid_emb, y_valid_emb)

Модель заложена быстро после 3 эпох. Кроме того, точность валидации ниже по сравнению с вложениями, обученными на учебных данных.

glove_results = test_model(glove_model, X_train_seq_trunc, y_train_oh, X_test_seq_trunc, y_test_oh, 3)
print('/n')
print('Test accuracy of word glove model: {0:.2f}%'.format(glove_results[1]*100))

В качестве окончательного упражнения давайте посмотрим, какие результаты мы получаем, когда мы тренируем вложения с тем же количеством измерений, что и данные перчатки.

Учебные вложения слова с большим количеством измерений

Мы будем тренировать слово вложения с одинаковым количеством измерений, что и вставка перчатки (I.E. GLOVE_DIM).

emb_model2 = models.Sequential()
emb_model2.add(layers.Embedding(NB_WORDS, GLOVE_DIM, input_length=MAX_LEN))
emb_model2.add(layers.Flatten())
emb_model2.add(layers.Dense(3, activation='softmax'))
emb_history2 = deep_model(emb_model2, X_train_emb, y_train_emb, X_valid_emb, y_valid_emb)
emb_results2 = test_model(emb_model2, X_train_seq_trunc, y_train_oh, X_test_seq_trunc, y_test_oh, 3)
print('/n')
print('Test accuracy of word embedding model 2: {0:.2f}%'.format(emb_results2[1]*100))

На тестовые данные мы получаем хорошие результаты, но мы не превосходят логистику с CountVectorizer. Так что есть все еще комната для улучшения.

Лучший результат достигается с помощью 100-мерных вложений слов, которые обучаются на доступных данных. Это даже превосходит использование слов вложений, которые были обучены на гораздо более крупном корпусе Twitter.

До сих пор мы просто поставили плотный слой на сплющенных вложений. Делая это, Мы не учитываем отношения между словами в твитом. Это может быть достигнуто с рецидивирующей нейронной сетью или 1D-сверточной сетью. Но это что-то для будущего поста:)