Сверточные нейронные сети, двунаправленная долговременная краткосрочная память
В последние годы в области Обработка естественного языка было сделано много инноваций, достижений и исследований. Эти исследования включают использование простого подхода 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 г.