Использование NLP для построения классификатора сарказма

МЕНЮ


Искусственный интеллект
Поиск
Регистрация на сайте
Помощь проекту

ТЕМЫ


Новости ИИРазработка ИИВнедрение ИИРабота разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика

Авторизация



RSS


RSS новости


В этой статье мы попробуем написать классификатор определяющий саркастические статьи используя машинное обучение и TensorFlow

Статья является переводом с Machine Learning Foundations: Part 10 — Using NLP to build a sarcasm classifier

В качестве обучающего набора данных используется датасет «Sarcasm in News Headlines» Ришаба Мишры. Это интересный набор данных, который собирает заголовки новостей из обычных источников новостей, а также еще несколько комедийных с поддельных новостных сайтов.

Набор данных представляет собой файл JSON с тремя столбцами.

  • is_sarcastic  — 1, если запись саркастическая, иначе 0
  • headline — заголовок статьи
  • article_link — URL-адрес текста статьи

Здесь мы просто рассмотрим заголовки. Итак, у нас есть очень простой набор данных для работы. Заголовок — это наша особенность, а is_sarcastic наш ярлык.

Данные в JSON выглядят примерно так.

{     "article_link": "https://www.huffingtonpost.com/entry/versace-black-code_us_5861fbefe4b0de3a08f600d5",     "headline": "former versace store clerk sues over secret 'black code' for minority shoppers",     "is_sarcastic": 0 }

Каждая запись представляет собой поле JSON с парами имя-значение, показывающими столбец и связанные данные.

Вот код для загрузки данных в Python

import json  with open("sarcasm.json", 'r') as f:     datastore = json.load(f) sentences = []  labels = [] urls = [] for item in datastore:     sentences.append(item['headline'])     labels.append(item['is_sarcastic'])     urls.append(item['article_link'])

Разберем этот код. Во-первых, import json позволяет использовать парсеры json в Python. Затем мы открываем файл sarcasm.json. Используя метод json.load(), мы можем все загрузить и проанализировать. Далее инициализируем массивы для предложений, меток и URL-адресов. И теперь можно просто пройтись по хранилищу данных. И для каждого элемента  добавляем его заголовок, метку сарказма и URL-адрес в соответствующий массив.

Следующий код выполнит токенизацию и упорядочивание набора данных.

from tensorflow.keras.preprocessing.text import Tokenizer from tensorflow.keras.preprocessing.sequence import pad_sequences tokenizer = Tokenizer(oov_token="") tokenizer.fit_on_texts(sentences) word_index = tokenizer.word_index print(len(word_index)) print(word_index) sequences = tokenizer.texts_to_sequences(sentences) padded = pad_sequences(sequences, padding='post') print(padded[0]) print(padded.shape)

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

... 'blowing': 4064, 'packed': 4065, 'deficit': 4066, 'essential': 4067, 'explaining': 4068, 'pollution': 4069, 'braces': 4070, 'protester': 4071, 'uncle': 4072 ...

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

[  308 15115   679  3337  2298    48   382  2576 15116     6  2577  8434      0     0     0     0     0     0     0     0     0     0     0     0      0     0     0     0     0     0     0     0     0     0     0     0      0     0     0     0] (26709, 40)

Это первое предложение после токенизации и заполнения. Оно короче, поэтому заканчивается кучей нулей.  Нижнее значение означает что у нас есть 26 709 дополненных предложений, и каждое из них имеет длину 40 значений.

С помощью всего нескольких строк кода мы загрузили данные из датасета в массивы предложений, токенизировали и дополнили их.

Далее в коде будут использоваться следующие параметры

voiceab_size = 10000  embedding_dim = 16  max_length = 100  trunc_type = 'post'  padding_type = 'post'  oov_tok = ""  training_size = 20000

У нас есть 26 000 предложений их которых 20 000 будут использоваться для обучения, значение training_size, а 6000 оставим для проверки.

training_sentences = sentences[0:training_size] testing_sentences = sentences[training_size:] training_labels = labels[0:training_size] testing_labels = labels[training_size:]

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

tokenizer = Tokenizer(num_words=vocab_size, oov_token=oov_tok) tokenizer.fit_on_texts(training_sentences)  word_index = tokenizer.word_index  training_sequences = tokenizer.texts_to_sequences(training_sentences) training_padded = pad_sequences(training_sequences, maxlen=max_length, padding=padding_type, truncating=trunc_type)  testing_sequences = tokenizer.texts_to_sequences(testing_sentences) testing_padded = pad_sequences(testing_sequences, maxlen=max_length, padding=padding_type, truncating=trunc_type)

Сначала мы создадим токенизатор и укажем количество слов, которое нам нужно, и какой должен быть токен вне словарного запаса. Мы приспособим токенизатор только к корпусу training_sentence. Это поможет нам точно отразить любое использование в реальном мире. Наши test_sentences можно протестировать на основе словаря, полученного из обучающего набора. Теперь мы можем создать набор training_sequences из набора training_sentences. Далее дополним их, чтобы получить набор дополненных обучающих предложений. То же самое проделаем для testing_sentences и для всех ярлыков.

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

Например, рассмотрите слова «Bad» и «Good». Теперь мы знаем, что они имеют противоположное значение. Так что мы можем нарисовать их в виде стрелок, указывающих в противоположных направлениях.

Основы машинного обучения: часть 10 - Использование НЛП для построения классификатора сарказма

Тогда мы могли бы описать слово «meh» как нечто плохое, но не совсем такое уж плохое. Так что это может быть такая стрелка.

Основы машинного обучения: часть 10 - Использование НЛП для построения классификатора сарказма

И тогда фраза «not bad», она не так сильна, как «Good», но более или менее в том же направлении, что и хорошо. Итак, мы могли нарисовать его такой стрелкой.

Основы машинного обучения: часть 10 - Использование НЛП для построения классификатора сарказма

Если мы затем нанесем их на график, мы сможем получить координаты этих стрелок. Затем эти координаты можно рассматривать как вложения для тональности этих слов.

Основы машинного обучения: часть 10 - Использование НЛП для построения классификатора сарказма

Абсолютного значения нет, но значения относительно  друг друга мы можем установить.

Чтобы сделать это в коде, мы можем просто использовать слой Keras, называемый Embedding.

model = tf.keras.Sequential([     tf.keras.layers.Embedding(vocab_size, embedding_dim, input_length=max_length),     tf.keras.layers.GlobalAveragePooling1D(),     tf.keras.layers.Dense(24, activation='relu'),     tf.keras.layers.Dense(1, activation='sigmoid') ]) model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['accuracy'])

Embedding должно быть определено как вектор для каждого слова. Итак, мы возьмем слова размером со словарь, а затем определим, сколько измерений мы хотим использовать в направлении стрелки. В данном случае это 16, которые мы создали ранее. Таким образом, слой Embedding будет изучать 10 016 размерных векторов, где направление вектора определяет тональность слова. Сопоставив слова с метками, у него будет направление, в котором он сможет начать учиться.

После того как мы определили модель, мы можем обучить ее следующим образом.

num_epochs = 30 history = model.fit(training_padded, training_labels, epochs=num_epochs, validation_data=(testing_padded, testing_labels), verbose=2)

Мы просто указываем функции и метки training_padded, а также валидационные данные.

Вот и все, весь код доступен на  Google Colab, где вы можете с ним поиграть.


Источник: habr.com

Комментарии: