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

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

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

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

1- Категоризация жанров фильмов по платформам ОТТ.

2- Текстовые классификации по банковским и финансовым учреждениям.

3- Автоматическая генерация титров.

Здесь мы представляем структуру глубокого обучения, которая использовалась для классификации предложений по различным меткам. Цель статьи - ознакомить аудиторию с тем, как сети CNN и Bi-LSTM в комбинациях используются для создания нового классификатора с несколькими метками. Набор данных, который мы будем использовать для этой демонстрации, - это набор данных Toxic Comment Classification Challenge, представленный в соревновании Kaggle. Цель заключалась в том, чтобы классифицировать приговор на токсичный, очень токсичный, непристойный, угрожающий, оскорбительный и т. Д. Более подробную информацию о наборе данных можно найти здесь.

Мы возьмем образец полного набора данных для демонстрации фреймворка. Для наилучшего использования предлагаемой структуры настоятельно рекомендуется использовать полный набор данных. Задача этой задачи Kaggle состояла в том, чтобы предсказать токсичность комментариев, и модель принимает комментарии, предварительно обрабатывает их и выдает ярлыки, которым они принадлежат. Загрузим данные!

import pandas as pd

import numpy as np
df.info() 
import seaborn as sns
import matplotlib.pyplot as plt
import re
df = pd.read_csv(r"Dataset_toxic_comment\train.csv", encoding='iso-8859-1')

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

Примечание. Для достижения наилучших результатов рекомендуется использовать полные данные с графическим процессором

## Taking sample to work on just for framework demonstration ##
df_data = df.sample(frac=0.2, replace=True, random_state=1)
df_data.isnull().sum()

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

## Word Pre-Processing 
#### Function to normalize text for pre-processing #### Apply the written function ##
processed_list = []
import nltk
def normalize_text(text):
df_data['comment_text'] = df_data['comment_text'].apply(lambda x: normalize_text(x)) 
for j in df_data['comment_text']:
 process = j.replace('...','')
 processed_list.append(process)
 
df_processed = pd.DataFrame(processed_list)
df_processed.columns = ['comments']
df_processed.head(n=5) 
 text = text.lower()
 text = re.sub('\[.*?\]', ' ', text)
 text = re.sub('https?://\S+|www\.\S+', ' ', text)
 text = re.sub('<.*?>+', ' ', text)
 text = re.sub('[%s]' % re.escape(string.punctuation), ' ', text)
 text = re.sub('\n', ' ', text)
 text = re.sub('\w*\d\w*', ' ', text)
 return text 
import string
wpt = nltk.WordPunctTokenizer()
stop_words_init = nltk.corpus.stopwords.words('english')
stop_words = [i for i in stop_words_init if i not in ('not','and','for')]
print(stop_words)

Теперь, когда данные готовы и очищены, самое время объединить метки. После объединения меток перед тем, как переходить к построению и классификации модели, в первую очередь необходимо проверить, какие существуют типы меток и какие классы относятся к меткам. Это необходимо в случае классификации по нескольким меткам, чтобы получить представление о распределении меток.

labels = ["toxic", "severe_toxic", "obscene", "threat", "insult", "identity_hate"]plt.figure(figsize=(8,5))plt.title("Labels per Classes")rects = ax.patches
targets = df_data[labels].values import matplotlib.pyplot as plt val_counts = df_data[labels].sum() 
ax = sns.barplot(val_counts.index, val_counts.values, alpha=0.8) 
plt.xlabel("Various Label Type")
plt.ylabel("Counts of the Labels") 
labels = val_counts.values
for rect, label in zip(rects, labels):
 height = rect.get_height()
 ax.text(rect.get_x() + rect.get_width()/2, height+5, label, ha="center", va="bottom") plt.show()

Мы также построим график для проверки дисбаланса данных в пределах каждого типа метки токсичности.

import seaborn as sns fig , axes = plt.subplots(2,3,figsize = (10,10), constrained_layout = True)
sns.countplot(ax=axes[0,0],x='toxic',data=df_data )
sns.countplot(ax=axes[0,1],x='severe_toxic',data=df_data)
sns.countplot(ax=axes[0,2],x='obscene',data=df_data)
sns.countplot(ax = axes[1,0],x='threat',data=df_data)
sns.countplot(ax=axes[1,1],x='insult',data=df_data)
sns.countplot(ax=axes[1,2],x='identity_hate',data=df_data)
plt.suptitle('Number Of Labels of each Toxicity Type')
plt.show()

Преобразование данных в формат, соответствующий требованиям платформы

X = list(df_processed['comments'])
y_data = df_data[["toxic", "severe_toxic", "obscene", "threat", "insult", "identity_hate"]]
y = y_data.values

Тренировка тестового сплита

from sklearn.model_selection import train_test_split x_train, x_test, y_train, y_test = train_test_split(X, y,
 test_size=0.15, train_size=0.85)

Yayyyyyy !!! мы закончили создание тестовых данных поезда и предварительную обработку текста. Перейдем к тому, за чем вы пришли :)

  • Загрузите все необходимые библиотеки keras.
  • Возьмите верхние 10000 слов в качестве функций, чтобы преобразовать тексты в последовательность целых чисел.
  • Задайте максимальную длину последовательности 100.
  • Наконец, дополните текстовую последовательность, чтобы все входные тексты имели одинаковую длину для моделирования.
from keras.preprocessing.text import one_hotmax_len = 100tokenizer = Tokenizer(num_words=max_features)x_train = tokenizer.texts_to_sequences(x_train)x_train = pad_sequences(x_train, padding='post', maxlen=max_len)
from keras.preprocessing.sequence import pad_sequences
from keras.models import Sequential
max_features = 10000
tokenizer.fit_on_texts(list(x_train)+list(x_test)) 
x_test= tokenizer.texts_to_sequences(x_test) 
x_test = pad_sequences(x_test, padding='post', maxlen=max_len) 
embed_size = 300 
from keras.layers.core import Activation, Dropout, Dense
from keras.layers import Flatten, LSTM
from keras.layers import Bidirectional,GRU,concatenate,SpatialDropout1D
from keras.layers import GlobalMaxPooling1D,GlobalAveragePooling1D,Conv1D
from keras.models import Model
from keras.layers.embeddings import Embedding
from sklearn.model_selection import train_test_split
from keras.preprocessing.text import Tokenizer
from keras.layers import Input
from keras.layers.merge import Concatenate
import matplotlib.pyplot as plt
from keras import layers
from keras.optimizers import Adam,SGD,RMSprop ######## Textual Features for Embedding ###################

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

Ха !!, сейчас мы подготовим матрицу вложения….

from numpy import arrayfor line in glove_file:vocab_size = len(tokenizer.word_index) + 1 ## total distinct words is the Vocabulary ##embedding_matrix = zeros((num_words, embed_size)) ## has to be similar to glove dimension ##
from numpy import asarray
from numpy import zeros embeddings_dictionary = dict() glove_file = open(".....", encoding="utf8") ## pre-trained or self trained global vectors file ## 
 records = line.split()
 word = records[0]
word_index = tokenizer.word_index
for word, index in tokenizer.word_index.items():
 if index >= max_features:
 continue
 embedding_vector = embeddings_dictionary.get(word)
 if embedding_vector is not None:
 embedding_matrix[index] = embedding_vector 
num_words = min(max_features,len(word_index)+1) 
 vector_dimensions = asarray(records[1:], dtype='float32')
 embeddings_dictionary[word] = vector_dimensions
glove_file.close()

Как только матрица вложения готова, мы можем приступить к определению нашей последней части. Поздравляю !!!!! Вы дошли до последнего…

  • Первый слой будет слоем встраивания, который использует векторы длины 300 и вес, полученный из разработанной матрицы встраивания.
  • Затем идет слой пространственного отсева, который выполняет отсев вариационно.
  • Следующий слой - сверточный слой для извлечения одномерных объектов более высокого уровня из входной последовательности.
  • Следующий уровень - это уровень Bi-LSTM со 128 единицами.
  • Тогда у нас есть средний полинг-слой
  • Наконец, у нас есть плотный слой, за которым следует простой слой исключения, который затем закрывается другим плотным слоем, который имеет единицы, аналогичные выходным данным с несколькими метками.

Пример схематического представления архитектуры приведен ниже:

sequence_input = Input(shape=(max_len, ))
x = Embedding(max_features, embed_size, weights=[embedding_matrix],trainable = False)(sequence_input)
x = SpatialDropout1D(0.2)(x) ## ostly drops the entire 1D feature map rather than individual elements.
x = Conv1D(64, kernel_size = 3, padding = "valid", kernel_initializer = "glorot_uniform")(x)
x = Bidirectional(LSTM(128, return_sequences=True,dropout=0.1,recurrent_dropout=0.1))(x)
avg_pool = GlobalAveragePooling1D()(x)
x = Dense(128, activation='relu')(avg_pool)
x = Dropout(0.1)(x)
preds = Dense(6, activation="sigmoid")(x)
model = Model(sequence_input, preds)
model.compile(loss='binary_crossentropy',optimizer=RMSprop(lr=1e-3),metrics=['accuracy'])
print(model.summary())
history = model.fit(x_train, y_train, batch_size=128, epochs=5,
 verbose=1, validation_split=0.2) model.save_weights("./BiLSTM_ver1.h5")
score = model.evaluate(x_test, y_test, verbose=1)

Наконец, построение кривых точности и потерь при обучении модели.

plt.plot(history.history['accuracy'])plt.title('model accuracy')
plt.plot(history.history['val_accuracy']) 
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train','test'], loc='upper left')
plt.show()
plt.plot(history.history['loss'])plt.title('model loss')
plt.plot(history.history['val_loss']) 
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train','test'], loc='upper left')
plt.show()

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

Оставляйте аплодисменты, если цените содержание и старания :) !!!!

Первоначально опубликовано на https://diwas26.medium.com 21 февраля 2021 г.