Эта история является частью серии Текстовая классификация — от Bag-of-Words до BERT, реализующей несколько методов на конкурсе Kaggle под названием «Вызов классификации токсичных комментариев». В этом конкурсе перед нами стоит задача создать многоуровневую модель, способную выявлять различные типы токсичности, такие как угрозы, непристойности, оскорбления и ненависть на основе личных данных. Если вы не читали предыдущие новости, обязательно посмотрите их.

Часть 1 (BagOfWords)

Часть 2 (Word2Vec)

Часть 3 (быстрый текст)

В более ранней истории (Часть 3 (fastText)) мы использовали библиотеку fastText как для создания вложений для предложений, так и для классификации текста с несколькими метками по выходным переменным.

В этом мы будем использовать библиотеку Keras (которая является оболочкой TensorFlow) для создания одномерных сверточных нейронных сетей (CNN) для классификации текста с несколькими метками. Мы также рассмотрим некоторые фоновые работы модели.

Интуиция

С чего все началось? CNN были впервые представлены в 1980-х годах Яном Лекуном для распознавания рукописных цифр. Но ConvNets остались в стороне, потому что столкнулись с серьезной проблемой необходимости большого количества данных и вычислительных ресурсов для эффективной работы с большими изображениями.

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

Что такое CNN?

В ConvNet есть четыре основные операции, показанные на изображении выше:

1. Свертка

Этот слой является сердцем CNN. CNN используют карты / ядра функций для изучения функций ввода. Например, ядро в изображении [[1, 0, -1], [1, 0, -1], [1, 0, -1]] обнаруживает вертикальные линии на изображениях. Магия в том, что нам не нужно указывать ядра. Нам просто нужно указать количество ядер, и модель изучит ядра сама по себе, как веса в обычной ИНС. Общая идея заключается в том, что чем больше мы будем увеличивать количество слоев Conv и Pool, тем более сложные функции сможет обнаруживать модель. Первые слои распознают простые вещи, такие как линии/цвета, а последующие слои распознают более сложные узоры.

2. Нелинейность

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

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

ReLU часто предпочитают в скрытых слоях другим функциям, потому что он обучает нейронную сеть в несколько раз быстрее без существенного снижения точности обобщения. ReLU или выпрямленная линейная единица, которая применяет ненасыщающую функцию активации f (x) = max (0, x). Он также не страдает от явлений исчезающих градиентных функций активации Sigmoid и Tanh.

3. Объединение или субвыборка

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

Вот подробный блог о типах слоев Объединение слоев

4. Классификация (полностью подключенный слой)

Наконец, после нескольких слоев свертки и максимального объединения рассуждения высокого уровня в NN выполняются через полносвязные слои. Слои FC выполняют классификацию на основе признаков, извлеченных предыдущими слоями. Как правило, этот слой представляет собой традиционную ИНС, которая умножает веса на входные данные и активирует сквозную передачу для получения выходных данных.

Для тех, кому интересен полный код, вы можете найти его здесь. Тогда давайте углубимся в код 👨‍💻

Реализация

1. Чтение набора данных

2. Предварительная обработка текста

Текстовые данные должны быть закодированы как числа, которые будут использоваться в качестве входных или выходных данных для моделей ML/DL. Библиотека Keras предоставляет некоторые основные инструменты, которые помогут нам подготовить наши текстовые данные. Мы будем использовать класс Tokenizer, служебный класс, который позволяет векторизовать текстовый корпус, превращая каждый текст в последовательность целых чисел или в вектор, где коэффициент для каждого токена может быть двоичным, на основе количества слов, на основе tf-idf . Это будет трехэтапный процесс:

1. Инициализация класса Tokenizer

  • По умолчанию все знаки препинания удаляются, превращая тексты в последовательности слов, разделенных пробелами (слова могут включать символ ‘). Затем эти последовательности разбиваются на списки токенов. Затем они будут проиндексированы или векторизованы. 0 — зарезервированный индекс для заполнения.
  • Мы устанавливаем для num_words значение MAX_NUM_WORDS (20000), которое является максимальным количеством сохраняемых слов в зависимости от частоты слов. Будут сохранены только самые распространенные слова num_words-1.

2. Вызов функции fit_on_texts — обновляет внутренний словарь на основе списка текстов.

Этот метод создает индекс словарного запаса на основе частоты слов. Так что если вы скажете что-то вроде: «Кошка сидела на коврике». Это создаст словарь s.t. word_index["the"] = 1; word_index["cat"] = 2 это слово -> индексный словарь, поэтому каждое слово получает уникальное целочисленное значение. Таким образом, более низкое целое число означает более частые слова (часто первые несколько слов являются стоп-словами).

3. Вызов функции texts_to_sequences — преобразует каждый текст в texts в последовательность целых чисел.

Таким образом, он в основном берет каждое слово в тексте и заменяет его соответствующим целочисленным значением из словаря word_index.

Примечание: После fit_on_texts, который, по сути, создает матрицу word_index для словаря, мы можем сделать одну из двух вещей

  • texts_to_sequences, который используется, когда мы используем встраиваемый слой
  • text_to_matrix, который преобразует тексты в набор слов
#Initializing the class
tokenizer = Tokenizer(num_words = MAX_NUM_WORDS)
#Updates internal vocabulary based on a list of texts.
tokenizer.fit_on_texts(train_texts)
#Transforms each text in texts to a sequence of integers.
train_sequences = tokenizer.texts_to_sequences(train_texts)
test_sequences = tokenizer.texts_to_sequences(test_texts)
word_index = tokenizer.word_index
print(“Length of word Index:”, len(word_index))
print(“First 5 elements in the word_index dictionary:”, dict(list(word_index.items())[0: 5]) )
print(“First comment text in training set:\n”, train_sequences[0])

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

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

Это также делается в Computer Vision, где мы обычно изменяем размер всех изображений до фиксированного размера, который будет входным размером NN.

#Pad tokenized sequences
trainvalid_data = pad_sequences(train_sequences, maxlen=MAX_SEQUENCE_LENGTH)
test_data = pad_sequences(test_sequences, maxlen=MAX_SEQUENCE_LENGTH)
print(“Shape of padded sequence list:\n”, trainvalid_data.shape)
print(“First comment text in training set — 0 for padding — only last 50 sequences as the rest are paddings:\n”, trainvalid_data[0][-50:])

3. Определение одномерной модели CNN

В Keras самый простой способ определить модель — инициировать класс модели Sequential и продолжать добавлять необходимые слои. Последовательная модель представляет собой простой набор слоев, в котором каждый слой имеет ровно один входной тензор и один выходной тензор.

Стандартная модель классификации документов заключается в использовании слоя внедрения в качестве входных данных, за которым следует одномерная сверточная нейронная сеть, слой пула, а затем выходной слой прогнозирования. Мы использовали 1 слой внедрения, 3 набора слоев свертки и объединения и 2 набора плотного слоя. Мы можем либо использовать предварительно обученное вложение (например, Word2Vec) для создания матрицы встраивания размера Vocabulary * Dimension of embedding, либо обучить новое вложение, помещая его в качестве входного слоя вместе с другими весами.

Conv1D: CNN были разработаны для классификации изображений, в которых модель принимает двумерные входные данные, представляющие пиксели изображения и цветовые каналы. Этот же процесс можно применить к одномерным последовательностям данных. Модель извлекает функции из данных последовательности и отображает внутренние функции последовательности. CNN учитывают близость слов для создания обучаемых шаблонов. Размер/высота ядра в сверточном слое определяет количество слов, которые следует учитывать при прохождении свертки по входному текстовому документу, предоставляя параметр группировки. В нашем случае он будет рассматривать по 5 слов за раз, а в изображении — по 2 слова за раз.

Слой Max Pooling объединит выходные данные сверточного слоя.

Мы используем сигмовидную активацию в выходном слое. Сигмовидная функция дает нам оценку вероятности от 0 до 1 для каждого выхода из выходного узла. Если бы мы использовали softmax, это дало бы распределение вероятностей по выходным узлам, которое в сумме дает 1.

В целом,

  • Для двоичной классификации мы можем иметь 1 единицу вывода, использовать сигмовидную активацию в выходном слое и использовать двоичную кросс-энтропийную потерю.
  • Для многоклассовой классификации мы можем иметь N выходных единиц, использовать активацию softmax в выходном слое и использовать категориальную кросс-энтропийную потерю.
  • Для классификации с несколькими метками мы можем иметь N выходных единиц, использовать сигмовидную активацию в выходном слое и использовать двоичную кросс-энтропийную потерю.

cnn_model = Sequential()
cnn_model.add(Embedding(MAX_NUM_WORDS, 128))
cnn_model.add(Conv1D(filters = 128, kernel_size = 5, activation = “relu”))
cnn_model.add(MaxPooling1D(pool_size = 5))
cnn_model.add(Conv1D(filters = 128, kernel_size = 5, activation = “relu”))
cnn_model.add(MaxPooling1D(pool_size = 5))
cnn_model.add(Conv1D(filters = 128, kernel_size = 5, activation = “relu”))
cnn_model.add(GlobalMaxPool1D())
cnn_model.add(Dense(units = 128, activation = ‘relu’))
cnn_model.add(Dense(units = 6, activation = ‘sigmoid’))
print(cnn_model.summary())

4. Скомпилируйте и подгоните модель CNN

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

При подгонке/обучении модели вместе с обучающим набором мы также передаем следующие параметры:

  • batch_size = количество выборок, проходящих через сеть за раз.
  • эпохи = количество раз, когда весь набор обучающих выборок проходит через сеть
  • validation_data = набор данных, который будет использоваться для оценки потерь и любых показателей модели в конце каждой эпохи. Этот набор не будет использоваться для обучения.
#Configures the model for training
cnn_model.compile(loss = "binary_crossentropy", optimizer = "adam", metrics = ["AUC"])
#Split the dataset into train and validation set for training and evaludating the model
X_train, X_val, y_train, y_val = train_test_split(trainvalid_data, train_labels, shuffle = True, random_state = 123)
print(X_train.shape, y_train.shape, X_val.shape, y_val.shape)
#Trains the model for a fixed number of epochs (iterations on a dataset)
history = cnn_model.fit(X_train, y_train, batch_size = 128, epochs = 1, validation_data = (X_val, y_val)

5. Результаты и объем улучшений

  • Используйте многоканальную CNN, которая будет одновременно просматривать предложения разной длины (например, размер ядра 3, 5 и 7).
  • Настройте слои модели и гиперпараметры для повышения производительности.

Это было о CNN. Следующий будет посвящен долговременной кратковременной-временной памяти (LSTM), которая представляет собой шаг вперед по сравнению с РНС, изначально используемыми в НЛП. Оставайтесь в безопасности до тех пор. Опять же весь код присутствует (здесь). Пожалуйста, оставляйте свои отзывы в виде ответов и аплодисментов :)