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

Часть 1 (BagOfWords)

Часть 2 (Word2Vec)

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

Часть 4 (Сверточная нейронная сеть)

В более ранней истории (Часть 4 (Сверточная нейронная сеть)) мы использовали библиотеку Keras (которая представляет собой обертку над TensorFlow) для создания одномерных CNN для классификации текста с несколькими метками по выходным переменным — токсичное, серьезное_токсичное, непристойное, угрожающее. , оскорбление, identity_hate.

В этом мы будем использовать ту же библиотеку Keras для создания долговременной кратковременной памяти (LSTM), что является улучшением по сравнению с обычными RNN для классификации текста с несколькими метками. Сначала мы пройдемся по интуитивному пониманию того, как работают RNN и LSTM, а затем реализуем их, используя минималистичный одиночный выходной слой (с 6 нейронами) для классификации по нескольким меткам (вместо создания 6 отдельных сетей для каждого типа токсичности или создания нескольких сетей). -сеть выходного слоя, имеющая 6 выходных слоев). Мы будем использовать только один слой LSTM, и всего за одну эпоху он даст ~ 96 AUC в таблице лидеров.

Интуиция

Зачем нам нужны RNN?

В традиционной НС мы предполагаем, что все входы (и выходы) независимы друг от друга. Они не разделяют функции, изученные в разных позициях текста. Это может быть проблемой для последовательной информации, такой как текстовые данные или данные временных рядов, где каждый экземпляр также зависит от предыдущих. RNN называются рекуррентными, потому что они выполняют одну и ту же задачу для каждого элемента последовательности, а результат зависит от предыдущих вычислений. Другой способ думать о RNN состоит в том, что у них есть «память», которая фиксирует информацию о том, что было рассчитано до сих пор.

Какова архитектура RNN?

Общая архитектура RNN зависит от поставленной задачи. Для этой задачи, которая является задачей классификации, мы будем использовать 3-ю задачу: многие к одному. Но для интуиции давайте посмотрим на 5-е, которое является более обобщенным обозначением для RNN. Если мы знаем, как работает 5-я нотация, достаточно будет изменить небольшую часть.

Входные векторы показаны красным, выходные векторы — синим, а зеленые векторы содержат состояние RNN. Слева направо: (1) Стандартный режим обработки без RNN (например, классификация изображений) (2) Вывод последовательности (например, подпись к изображению) (3) Ввод последовательности (например, анализ тональности) (4) Ввод последовательности и вывод последовательности (например, машина Перевод) (5) Синхронизированный ввод и вывод последовательности (например, классификация видео — маркировка каждого кадра видео)

Что такое исчезающие градиенты?

Проблема исчезающего градиента возникает в очень глубоких НС, обычно РНС, которые используют функции активации, градиенты которых имеют тенденцию быть небольшими (в диапазоне 0-1). Поскольку эти небольшие градиенты умножаются во время обратного распространения, они имеют тенденцию «исчезать» или уменьшаться до 0 во всех слоях, не позволяя сети изучать долгосрочные зависимости. По мере того, как последовательность становится длиннее, градиенты/производные, переданные в предыдущие состояния, становятся все меньше и меньше. Есть много решений этой проблемы. Один из них использует вариант под названием LSTM.

Что такое LSTM?

Сети с долговременной кратковременной памятью — обычно называемые просто «LSTM» — представляют собой особый вид RNN, способный изучать долгосрочные зависимости. Все РНС имеют вид цепочки повторяющихся модулей нейронных сетей. LSTM также имеют эту цепочечную структуру, но вместо скрытого слоя у нас есть нечто, называемое ячейкой LSTM, и у нас есть другое соединение, которое проходит через все временные шаги вместе со скрытым состоянием. Это так называемый вектор «состояния ячейки», из которого информация может быть извлечена и удалена по мере необходимости.

Давайте рассмотрим 6 шагов:

  1. Это ворота забывания, которые отвечают за то, сколько нужно забыть, и, поскольку они проходят через сигмовидную функцию, они дают значение от 0 до 1, которое представляет собой объем памяти, который необходимо сохранить от предыдущего состояние клетки
  2. Это входные ворота, которые отвечают за то, сколько новой информации должно быть добавлено к состоянию ячейки. Подобно воротам забывания, это также даст значение от 0 до 1, которое является объемом новой памяти, которую нужно добавить.
  3. Это создание нового вектора-кандидата/состояния ячейки.
  4. Здесь обновляется состояние ячейки, которое представляет собой комбинацию предыдущего состояния ячейки и текущего состояния ячейки, вклад каждого из которых контролируется с помощью ворота забывания и ворота ввода. соответственно.
  5. Это выходной элемент, который отвечает за то, какая часть обновленного состояния ячейки должна быть запомнена в скрытом состоянии со значением от 0 до 1.
  6. Это обновленное скрытое состояние, которое будет входом для следующей ячейки и основано на текущем состоянии ячейки, контролируемом выходным вентилем.

Как LSTM решает исчезающие градиенты?

  • Архитектура LSTM упрощает для RNN сохранение информации в течение многих временных шагов, например. если ворота забывания настроены на запоминание всего на каждом временном шаге, то информация в ячейке сохраняется на неопределенный срок. Напротив, обычной RNN сложнее изучить рекуррентную матрицу весов, которая сохраняет информацию в скрытом состоянии.
  • LSTM не гарантирует отсутствие исчезающего/взрывающегося градиента, но предоставляет модели более простой способ изучения удаленных зависимостей.

До рождения Трансформеров миром НЛП правили LSTM. Даже сегодня он широко используется

В 2015 году Google использовал LSTM в Google Voice, и это уменьшило количество ошибок транскрипции на 49%.

В 2016 году Google использовал LSTM, чтобы предлагать сообщения в приложении для разговоров Allo. Google использовал LSTM для Google Translate, что уменьшило количество ошибок перевода на 60%. Apple объявила, что начнет использовать LSTM для быстрого набора в iPhone и для Siri. Amazon выпустила Полли, голоса Alexa, используя двунаправленный LSTM.

В 2017 году Facebook ежедневно выполнял около 4,5 миллиардов автоматических переводов с использованием LSTM.

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

Выполнение

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

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

Предварительная обработка для модели LSTM почти такая же, как и для CNN.

#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])
#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:])

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

Мы выполним следующие шаги для классификации текста с несколькими метками с использованием LSTM:Входная строка —> Токенизация —> Заполнение —> Встраивание —> LSTM —> Классификатор

3. Определение модели LSTM с несколькими метками

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

Dropout:Dropout — это метод решения проблемы переобучения. Ключевая идея состоит в том, чтобы случайным образом отбрасывать единицы (вместе с их соединениями) из нейронной сети во время обучения. Это предотвращает чрезмерную коадаптацию юнитов. Этот гиперпараметр вводится для определения вероятности исключения выходных данных слоя.

Повторяющееся отключение маскирует (или «отбрасывает») связи между повторяющимися единицами.

Важное примечание. В целом

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

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

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

rnn_model = Sequential()
rnn_model.add(Embedding(MAX_NUM_WORDS, 128))
rnn_model.add(LSTM(units = 128, dropout = 0.2, recurrent_dropout = 0.2))
rnn_model.add(Dense(units = 6, activation = 'sigmoid'))
print(rnn_model.summary()

5. Скомпилируйте и обучите модель LSTM

Код компиляции и обучения/подгонки также почти такой же, как и в модели CNN. Прежде чем приступить к обучению модели, нам необходимо ее настроить. Мы должны упомянуть функцию потерь, которая будет использоваться для расчета ошибки на каждой итерации, оптимизатор, который будет указывать, как будут обновляться веса, и метрики, которые будут оцениваться моделью во время обучения и тестирования. Я подробно обсуждал параметры обучения в предыдущем блоге (Часть 4 (Сверточная нейронная сеть))

#Configures the model for training.
rnn_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 = rnn_model.fit(X_train, y_train, batch_size = 128, epochs = 1, validation_data = (X_val, y_val))

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

  • Стек более 1 слоя LSTM
  • Настройка гиперпараметров для эпох, скорости обучения, размера партии, ранней остановки

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