Введение:

Могут ли машины распознать сарказм? Этот вопрос годами озадачивал как исследователей, так и юмористов. Сарказм может быть трудно обнаружить даже для людей, поскольку он часто подразумевает высказывание противоположного тому, что на самом деле имеется в виду. Однако благодаря недавним достижениям в области обработки естественного языка (NLP) и машинного обучения (ML) теперь можно обучать модели распознавать сарказм в тексте.

В этой статье мы рассмотрим проект, который использует методы NLP и ML для обнаружения сарказма в заголовках новостей. Мы рассмотрим процесс шаг за шагом, рассмотрев наиболее важные фрагменты кода и обсудив производительность моделей. К концу этой статьи вы будете лучше понимать, как работает обнаружение сарказма, и потенциальные области применения этой технологии. Вы можете найти полный файл кода в репозитории GitHub, который я создал для этого проекта.

Процесс (пошаговая проверка кода)

Шаг 1: Сбор данных и предварительная обработка

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

import pandas as pd
import numpy as np
import tensorflow as tf
from tensorflow import keras
import matplotlib.pyplot as plt
from keras.preprocessing.text import Tokenizer
from sklearn.model_selection import train_test_split
from tensorflow.keras.preprocessing.sequence import pad_sequences
from sklearn.metrics import mean_squared_error,mean_absolute_error
from sklearn.metrics import classification_report, confusion_matrix, ConfusionMatrixDisplay, f1_score
import warnings

warnings.filterwarnings("ignore")

dataset = pd.read_json("sarcasm.json")
df = dataset.drop(["article_link"], axis = 1)

Затем мы предварительно обрабатываем текстовые данные, размечая заголовки и преобразовывая их в последовательности. Затем мы дополняем последовательности до максимальной длины 152, что является самой длинной длиной последовательности в наборе данных.

VOCAB_SIZE = 30000
tokenizer = Tokenizer(num_words = VOCAB_SIZE, oov_token = "OOV")
tokenizer.fit_on_texts(df.headline.values)
headline_sequences = tokenizer.texts_to_sequences(df.headline.values)

len_each_sublist = [len(sublist) for sublist in headline_sequences]
# result of max(len_each_sublist) is 152
MAX_LEN = 152

padded_headline_seq = pad_sequences(headline_sequences, truncating = 'post', padding = 'post', maxlen = MAX_LEN)

Шаг 2: Разделение данных

Мы разделяем предварительно обработанные данные на наборы для обучения и тестирования, используя функцию train_test_split() из scikit-learn. Мы используем размер теста 20% и случайное состояние 13 для воспроизводимости.

RS  = 13

X_train, X_test, y_train, y_test = train_test_split(padded_headline_seq, df.is_sarcastic, test_size = 0.2, random_state = RS)

Шаг 4: Создание и обучение модели SNN

Следующим шагом является построение модели простой нейронной сети (SNN) с использованием функции build_snn_model().

EPOCHS = 100

def build_snn_model():
    model = keras.Sequential()
    model.add(keras.layers.Input((X_train.shape[1],)))
    model.add(keras.layers.Dense(100, activation = 'relu'))
    model.add(keras.layers.Dense(100, activation = 'relu'))
    model.add(keras.layers.Dense(1, activation = 'sigmoid'))
    model.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy'])
    return model
    
snn_model = build_snn_model()
snn_history = snn_model.fit(X_train,y_train, epochs = EPOCHS)

вот послойное описание архитектуры модели SNN:

  1. Входной слой: этот слой принимает входные данные, которые имеют форму (X_train.shape[1]), где X_train — входные обучающие данные.
  2. Скрытый слой 1: этот слой имеет 100 нейронов и использует функцию активации Rectified Linear Unit (ReLU). Этот слой применяет линейное преобразование к входным данным и выводит максимум результата и 0.
  3. Скрытый слой 2: этот слой похож на первый скрытый слой и также имеет 100 нейронов с функцией активации ReLU.
  4. Выходной слой: этот слой имеет один нейрон и использует сигмовидную функцию активации. Он выводит значение от 0 до 1, которое можно интерпретировать как вероятность того, что входные данные принадлежат положительному классу.

Используемая функция потерь представляет собой двоичную кросс-энтропию, которая обычно используется в задачах бинарной классификации, а используемый оптимизатор — это Адам, который является популярным алгоритмом оптимизации для обучения нейронных сетей. Модель обучается на 100 эпох с использованием метода fit() с входными данными обучения и метками (y_train).

Шаг 5: Оцените модель SNN

Эта часть кода отвечает за оценку производительности модели SNN на тестовом наборе.

snn_notfinal_predict = snn_model.predict(X_test)
snn_predict = np.where(snn_notfinal_predict > 0.5, 1, 0)
snn_f1_score = f1_score(y_test, snn_predict)
print(f"SNN f1_score: {snn_f1_score}")
snn_class_report = classification_report(y_test, snn_predict)
print(snn_class_report)
snn_conf = confusion_matrix(y_test, snn_predict)
snn_conf_plot = ConfusionMatrixDisplay(snn_conf)
snn_conf_plot.plot()
plt.show()
  • snn_notfinal_predict = snn_model.predict(X_test): предскажите метки для тестовых данных, используя обученную модель SNN.
  • snn_predict = np.where(snn_notfinal_predict > 0.5, 1, 0) : пороговое значение прогнозируемых значений равно 0 или 1 на основе вероятностных выходных данных модели SNN.
  • snn_f1_score = f1_score(y_test, snn_predict) : Рассчитать f1-оценку для предсказанных значений модели SNN.
  • print(f"SNN f1_score: {snn_f1_score}"): распечатайте f1-оценку для модели SNN.
  • snn_class_report = classification_report(y_test, snn_predict) : Создайте отчет о классификации для модели SNN, включая точность, полноту, оценку f1 и поддержку для каждого класса.
  • print(snn_class_report) : Распечатать отчет о классификации для модели SNN.
  • snn_conf = confusion_matrix(y_test, snn_predict): вычислить матрицу путаницы для предсказанных значений модели SNN.
  • snn_conf_plot = ConfusionMatrixDisplay(snn_conf) : Создайте объект ConfusionMatrixDisplay для матрицы путаницы SNN.
  • snn_conf_plot.plot() : Постройте матрицу путаницы SNN.
  • plt.show() : Показать график матрицы путаницы SNN.

Точность модели SNN составила 55 %, что указывает на ограниченный успех в точном обнаружении сарказма в заголовках новостей.

Шаг 6: Создание и обучение модели CMP

Это функция с именем build_cmp_model(), которая возвращает модель Sequential, построенную с использованием слоев Keras.

EMBEDDING_DIM = 150

def build_cmp_model():
    model = keras.Sequential()
    model.add(keras.layers.Embedding(VOCAB_SIZE, EMBEDDING_DIM, input_length = X_train.shape[1]))
    model.add(keras.layers.Conv1D(16, 3, activation = 'relu'))
    model.add(keras.layers.MaxPooling1D(2))
    model.add(keras.layers.Dropout(0.2))
    model.add(keras.layers.Flatten())
    model.add(keras.layers.Dense(10, activation = 'relu'))
    model.add(keras.layers.Dense(1, activation = 'sigmoid'))
    model.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy'])
    return model
    
cmp_model = build_cmp_model()
cmp_history = cmp_model

Архитектура модели состоит из:

  1. Слой Embedding с размером словаря VOCAB_SIZE, размером внедрения EMBEDDING_DIM и длиной входных данных, равной количеству столбцов в обучающих данных (X_train.shape[1]). Этот слой изучает встроенное представление входного текста.
  2. Слой Conv1D с 16 фильтрами, размером ядра 3 и функцией активации ReLU. Этот слой применяет одномерную свертку к входной последовательности, извлекая локальные признаки из представления встраивания.
  3. Слой MaxPooling1D с размером пула 2. Этот слой выполняет максимальное объединение локальных объектов для понижения дискретизации выходных данных сверточного слоя.
  4. Слой Dropout со скоростью 0,2. Этот слой случайным образом отбрасывает 20% выходных единиц, предотвращая переоснащение.
  5. Слой Flatten, который объединяет выходные данные предыдущего слоя в одномерный массив.
  6. Слой Dense с 10 единицами и функцией активации ReLU. Этот слой применяет полносвязное линейное преобразование к сглаженному выходу.
  7. Слой Dense с 1 единицей и сигмовидной функцией активации. Этот слой выводит одно значение вероятности от 0 до 1, представляющее прогноз модели для входного текста.
  8. Модель скомпилирована с оптимизатором Адама, бинарной функцией кроссэнтропийных потерь и метрикой точности.

Возвращенный объект cmp_model является экземпляром построенной модели, которую можно использовать для обучения и прогнозирования. Код не показывает, что переменной cmp_history присваивается какое-либо значение, что говорит о том, что эта модель еще не обучена.

Шаг 7: Оцените модель CMP

Эта часть кода используется для оценки производительности модели CMP на тестовых данных.

cmp_notfinal_predict = cmp_model.predict(X_test)
cmp_predict = np.where(cmp_notfinal_predict > 0.5, 1, 0)
cmp_f1_score = f1_score(y_test,cmp_predict, average = 'weighted')
print(f"CMP f1_score: {cmp_f1_score}")
cmp_class_report = classification_report(y_test, cmp_predict)
print(cmp_class_report)
cmp_conf = confusion_matrix(y_test, cmp_predict)
cmp_conf_plot = ConfusionMatrixDisplay(cmp_conf)
cmp_conf_plot.plot()
plt.show()

cmp_notfinal_predict содержит предсказанные вероятности для каждой выборки в тестовом наборе. Порог для бинарной классификации установлен на 0,5, поэтому cmp_predict содержит предсказанные метки, 0 или 1, для каждого образца в тестовом наборе.

Оценка F1 рассчитывается для модели CMP с использованием функции f1_score из sklearn.metrics. Параметр average имеет значение 'weighted', что означает, что он будет вычислять оценку F1 для каждого класса независимо, а затем взвешивать их по количеству образцов в каждом классе.

classification_report из sklearn.metrics используется для распечатки отчета, содержащего точность, полноту и оценку F1 для каждого класса.

Наконец, матрица путаницы вычисляется с использованием confusion_matrix из sklearn.metrics. Матрица путаницы отображается с использованием ConfusionMatrixDisplay из sklearn.metrics.plotting, а plt.show() используется для отображения графика. Матрица путаницы помогает понять, насколько хорошо модель работает с точки зрения правильного определения положительных и отрицательных образцов.

Модель CMP продемонстрировала замечательную точность 84%.

Заключение

В заключение, проект успешно продемонстрировал потенциал методов НЛП и машинного обучения в обнаружении сарказма в заголовках новостей. Модель CMP, в которой использовались сверточные нейронные сети, достигла точности 84%, что является значительным улучшением по сравнению с моделью SNN, которая достигла точности только 55%. Эта разница в производительности подчеркивает эффективность использования CNN в задачах обработки естественного языка, особенно при обнаружении сарказма. Успех проекта предполагает, что эту технологию можно применять в различных областях, таких как анализ социальных сетей, управление репутацией бренда и анализ настроений.