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

Вы можете сослаться на https://www.kaggle.com/datasets/shashwatwork/consume-complaints-dataset-fo-nlp/download?datasetVersionNumber=1 для набора данных из kaggle.

В нашем наборе данных у нас есть 5 типов жалоб.

  1. кредитная отчетность
  2. взыскание долгов
  3. ипотека и кредиты
  4. кредитные карты
  5. розничные банковские услуги

Разделение между поездами и тестами

Импортируйте функцию «train_test_split» из модуля «sklearn.model_selection», которая используется для разделения данных на наборы для обучения и тестирования.

X = df_new['narrative'].values
y = df_new['product'].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.30,
 random_state = 0)

Разделите данные на наборы для обучения и тестирования, используя функцию «train_test_split», где:

  • «X» — входные данные (нарративы), которые необходимо разделить.
  • «y» — это целевые данные (этикетки продуктов), которые нужно разделить.
  • «test_size = 0.30» указывает, что 30% данных будут использоваться для тестирования и 70% для обучения.
  • «random_state = 0» гарантирует, что для каждого запуска выбираются одни и те же случайные выборки, что делает результаты воспроизводимыми.

Зависимая переменная OneHotEncoding

Преобразует переменную «y_train» и «y_test» в массив NumPy с помощью функции «np.array()».

Измените форму переменных «y_train» и «y_train», чтобы они имели один столбец, используя метод «reshape ()» с аргументом «-1,1». Аргумент «-1» указывает, что NumPy должен автоматически вычислять размер первого измерения на основе размера второго измерения, для которого установлено значение 1. Это делается для того, чтобы данные были в правильном формате для дальнейших операций.

Импортируйте класс OneHotEncoder из модуля sklearn.preprocessing, создайте экземпляр класса OneHotEncoder и назначьте его переменной enc.

Примените метод «fit_transform» объекта «enc» к переменной «y_train» и «y_test», чтобы выполнить однократное кодирование целевой переменной «y_train» и «y_test».

Результат операции горячего кодирования присваивается переменным «y_train_ohe» и «y_test_ohe» в виде разреженной матрицы.

Наконец, мы преобразуем разреженное матричное представление закодированных меток в плотный массив NumPy, используя метод toarray().

from sklearn.preprocessing import OneHotEncoder
import numpy as np
y_train = np.array(y_train)
y_test = np.array(y_test)
y_train = y_train.reshape(-1,1)
y_test = y_test.reshape(-1,1)

enc = OneHotEncoder()

y_train_ohe = enc.fit_transform(y_train)
y_test_ohe = enc.fit_transform(y_test)
y_train_ohe = y_train_ohe.toarray()
y_test_ohe = y_test_ohe.toarray()
print("="*50)
print("shape of y_train_ohe : ",y_train_ohe.shape)
print("="*50)
print("shape of y_test_ohe : ",y_test_ohe.shape)

Токенизация текстовых данных с использованием «bert-base-uncased»

Импортируйте класс «BertTokenizer» из модуля «transformers». Создайте экземпляр класса «BertTokenizer», который предварительно обучен на модели «bert-base-uncased», и присвойте его переменной «tokenizer».

Определите функцию с именем «tokenize», которая принимает предложение в качестве входных данных и возвращает токенизированную версию предложения с помощью объекта «tokenizer». Метод encode_plus объекта tokenizer используется для токенизации входного предложения. Метод возвращает словарь, содержащий два ключа: «input_ids» и «attention_mask». Параметр «max_length» установлен на 512, чтобы гарантировать, что все входные последовательности имеют одинаковую длину. Для параметра «truncation» установлено значение «True», чтобы обрезать любые последовательности, длина которых превышает указанную «max_length». Параметр padding устанавливается равным max_length, чтобы дополнять любые последовательности короче указанного max_length нулями. Для параметра add_special_tokens установлено значение «True», чтобы добавить специальные токены ([CLS] и [SEP]) в начало и конец последовательности соответственно. Для параметра return_token_type_ids установлено значение False, так как для нашей задачи это не требуется. Параметр return_tensors имеет значение tf, чтобы возвращать тензоры TensorFlow вместо тензоров PyTorch. Функция «tokenize» возвращает тензоры «input_ids» и «attention_mask».

from transformers import BertTokenizer
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')

def tokenize(sentence):
    tokens = tokenizer.encode_plus(sentence,
                                  max_length = 512,
                                  truncation = True,
                                  padding = 'max_length',
                                  add_special_tokens = True,
                                  return_token_type_ids = False,
                                  return_tensors = 'tf')
    return tokens['input_ids'],tokens['attention_mask']

X_train_ids = np.zeros((len(X_train),512))
X_train_mask = np.zeros((len(X_train),512))
X_test_ids = np.zeros((len(X_test),512))
X_test_mask = np.zeros((len(X_test),512))

print("="*50)
print("Shape of X_train_ids:",X_train_ids.shape)
print("="*50)
print("Shape of X_train_mask:",X_train_mask.shape)
print("="*50)
print("Shape of X_test_ids:",X_test_ids.shape)
print("="*50)
print("Shape of X_test_mask:",X_test_mask.shape)

for i,sequence in enumerate(X_train):
    tokens = tokenize(sequence)
    X_train_ids[i,:] , X_train_mask[i,:] = tokens[0], tokens[1]
    
for i, sequence in enumerate(X_test):
    tokens = tokenize(sequence)
    X_test_ids[i,:] , X_test_mask[i,:] = tokens[0], tokens[1]

  1. «X_train_ids»: этот массив используется для хранения токенизированных входных последовательностей для обучающего набора.
  2. «X_train_mask»: этот массив используется для хранения масок внимания для тренировочного набора.
  3. «X_test_ids»: этот массив используется для хранения токенизированных входных последовательностей для набора тестов.
  4. «X_test_mask»: этот массив используется для хранения масок внимания для набора тестов.

Форма этих массивов (количество примеров, 512), потому что мы установили максимальную длину входных последовательностей на 512, используя параметр «max_length» метода «encode_plus» объекта «токенизатор». Эти массивы будут использоваться для хранения токенизированных входных последовательностей и их масок внимания для обучающих и тестовых наборов.

Прокрутите каждую последовательность в обучающем наборе «X_train», используя цикл «for» и индексную переменную «i». Для каждой последовательности он вызывает функцию «токенизации», чтобы получить токенизированную входную последовательность и ее маску внимания. Назначьте токенизированную входную последовательность и ее маску внимания соответствующей строке массивов X_train_ids и X_train_mask соответственно. Выполните аналогичную операцию с «X_test» и сгенерируйте «X_test_ids» и «X_test_mask».

Преобразование токенизированных идентификаторов и масок в тензор тензорного потока

Преобразуйте массивы NumPy «X_train_ids», «X_train_mask», «X_test_ids» и «X_test_mask» в тензоры TensorFlow, используя метод «convert_to_tensor» модуля TensorFlow.

import tensorflow as tf
X_train_ids = tf.convert_to_tensor(X_train_ids)
X_train_mask = tf.convert_to_tensor(X_train_mask)

X_test_ids = tf.convert_to_tensor(X_test_ids)
X_test_mask = tf.convert_to_tensor(X_test_mask)

Преобразование массивов в тензоры необходимо для передачи их в качестве входных данных модели TensorFlow. После запуска этого кода массивы будут преобразованы в тензоры и сохранены в переменных «X_train_ids», «X_train_mask», «X_test_ids» и «X_test_mask» соответственно.

Подготовка обучающего и тестового набора данных для формата TensorFlow

Создайте наборы данных TensorFlow из входных данных тензора, используя метод from_tensor_slices модуля набора данных TensorFlow. Метод from_tensor_slices создает набор данных из входных тензоров, разрезая их по первому измерению. В этом случае он создает два набора данных: один для обучающего набора («data_train») и один для тестового набора («data_test»).

data_train = tf.data.Dataset.from_tensor_slices((X_train_ids,
                                                X_train_mask,
                                                y_train_ohe))

data_test = tf.data.Dataset.from_tensor_slices((X_test_ids,
                                                X_test_mask,
                                                y_test_ohe))

Каждый набор данных создается путем передачи кортежа входных тензоров в качестве аргумента методу from_tensor_slices. Входными тензорами для обучающего набора данных являются «X_train_ids», «X_train_mask» и «y_train_ohe». Входными тензорами для тестового набора данных являются «X_test_ids», «X_test_mask» и «y_test_ohe». После запуска вышеуказанного кода будут созданы наборы данных data_train и data_test, которые можно использовать для обучения и оценки модели TensorFlow.

Создание мини-пакетов с использованием функций тензорного потока

Определите функцию отображения «map_func», а затем примените эту функцию к наборам данных «data_train» и «data_test», используя метод «map» модуля набора данных TensorFlow. Метод «карта» применяет данную функцию к каждому элементу набора данных и возвращает новый набор данных с преобразованными элементами.

SHUFFLE = 100000
BATCH_SIZE = 16

def map_func(input_ids,masks,labels):
    return {'input_ids' : input_ids , 'attention_mask' : masks}, labels

data_train = data_train.map(map_func)
data_test = data_test.map(map_func)

train = data_train.shuffle(SHUFFLE).batch(BATCH_SIZE)
val = data_test.shuffle(SHUFFLE).batch(BATCH_SIZE)

Функция «map_func» принимает три аргумента: «input_ids», «маски» и «метки» и возвращает словарь с ключами «input_ids» и «attention_mask» и значением «метки». Эта функция используется для создания словаря функций и соответствующих им меток, которые можно использовать в качестве входных данных для модели TensorFlow.

После применения «map_func» к наборам данных «data_train» и «data_test» код перемешивает и группирует полученные наборы данных, используя методы «shuffle» и «batch» модуля набора данных TensorFlow. Метод «shuffle» случайным образом перемешивает элементы набора данных с размером буфера «SHUFFLE». Это помогает уменьшить любую корреляцию между соседними пакетами набора данных. Метод «пакет» группирует элементы набора данных в пакеты, каждый пакет содержит количество элементов «BATCH_SIZE».

После запуска этого кода будут созданы наборы данных «train» и «val», которые можно использовать для обучения и оценки модели TensorFlow.

Построение модели с использованием bert-base-uncased

Импортируйте класс «TFAutoModel» из библиотеки Transformers, которая является оболочкой для версии TensorFlow модели BERT. Затем он загружает предварительно обученную модель «bert-base-uncased», используя метод «from_pretrained» класса «TFAutoModel».

from transformers import TFAutoModel
bert = TFAutoModel.from_pretrained('bert-base-uncased')
bert.summary()

Выводит сводку модели BERT, используя метод «summary» класса «TFAutoModel». Этот метод отображает сводку архитектуры модели, включая количество слоев, форму входных и выходных данных, а также количество обучаемых параметров в модели. Сводка содержит полезную информацию для отладки модели, проверки правильности построения модели и оптимизации производительности модели.

Настройка выходного слоя для нашей задачи

input_ids = tf.keras.layers.Input(shape=(512,),name='input_ids',dtype='int32')
mask = tf.keras.layers.Input(shape=(512,),name='attention_mask',dtype='int32')
embedding = bert.bert(input_ids,attention_mask=mask)[0]

x = tf.keras.layers.Dropout(0.4)(embedding)
x = tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(786))(x)
y = tf.keras.layers.Dense(5,activation='softmax',name='outputs')(x)

model = tf.keras.Model(inputs=[input_ids,mask],outputs=y)
model.layers[2].trainable = False

Приведенный выше код определяет модель нейронной сети на основе BERT с использованием Keras API TensorFlow 2.x. Входной слой определяется с использованием класса «Ввод» Keras с формой (512,), чтобы соответствовать максимальной длине входной последовательности. Два входных слоя определены для input_ids и warning_mask соответственно.

Затем вызывается уровень BERT для входных_идентификаторов и маски внимания, чтобы получить вложения BERT входной последовательности. Внедрение маркера [CLS] извлекается из выходных данных BERT с использованием индексации ([0]) и передается через уровень отсева со скоростью 0,4.

За выпадающим слоем следует двунаправленный слой LSTM с 786 скрытыми единицами. Выходные данные слоя LSTM проходят через плотный слой с 5 единицами и функцией активации softmax для прогнозирования вероятностей 5 классов. Последний выходной слой называется «выходы».

Затем модель определяется с использованием класса «Модель» Keras с входным и выходным слоями в качестве аргументов. Наконец, для атрибута «обучаемый» слоя BERT установлено значение False, чтобы заморозить предварительно обученные веса слоя BERT и предотвратить их обновление во время обучения.

Обобщить модель

Создайте визуализацию определенной модели, используя функцию plot_model из служебного модуля Keras. Функция «plot_model» принимает объект модели, путь к файлу для сохранения изображения и аргумент «show_shapes = True» для отображения форм входных и выходных тензоров для каждого слоя в модели.

from tensorflow.keras.utils import plot_model
plot_model(model,'model.png',show_shapes=True)

После запуска этого кода в текущем рабочем каталоге будет сохранен файл с именем «model.png» с графическим представлением архитектуры модели. На изображении будут показаны входной и выходной слои, а также BERT, отсев, LSTM и плотные слои между ними со стрелками, указывающими поток данных через слои. Форма каждого тензора отображается рядом с каждым слоем в скобках.

Составление модели и обучение модели

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

optimizer = tf.keras.optimizers.legacy.Adam(learning_rate=0.0001,decay=1e-6)
loss = tf.keras.losses.CategoricalCrossentropy()
acc = tf.keras.metrics.CategoricalAccuracy('accuracy')
model.compile(optimizer = optimizer, loss=loss, metrics=[acc])

from keras.callbacks import EarlyStopping,ModelCheckpoint

early_stopping = EarlyStopping(monitor='val_accuracy',
                              min_delta=0,
                              patience=3,
                              verbose=1,
                              mode='max')

checkpoint = ModelCheckpoint("best_model.hdf5",
                            monitor = 'val_accuracy',
                            verbose=1,
                            save_best_only= True,
                            mode='max',
                            save_freq=1)

callbacks_1 = [early_stopping,checkpoint]

history = model.fit(train,
                   validation_data=val,
                   epochs=2,
                   callbacks=callbacks_1)

Затем определяются два обратных вызова Keras: «EarlyStopping» и «ModelCheckpoint». Обратный вызов «EarlyStopping» будет отслеживать точность проверки во время обучения и останавливать процесс обучения, если точность проверки не улучшится после определенного количества эпох (как указано в параметре «терпение»). Обратный вызов «ModelCheckpoint» сохранит веса модели в файл с именем «best_model.hdf5», если точность проверки улучшится.

Эти обратные вызовы передаются функции «подгонки», которая обучает модель на обучающих данных и оценивает ее производительность на проверочных данных. Функция «подгонки» принимает наборы данных для обучения и проверки в качестве аргументов, а также количество эпох для обучения и используемые обратные вызовы.

После завершения обучения история обучения (включая значения потерь и точности для каждой эпохи) сохраняется в объекте «история».

График производительности

plt.figure()
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.ylabel('ACC_SCORE')
plt.xlabel('NO_OF_EPOCHS')
plt.title('bert model NUMBER OF EPOCHS VS ACC_SCORE')
plt.grid()

Надеюсь, вам понравится этот блог, и он добавит что-то новое в ваши знания. На написание этого блога меня вдохновил Абхинандан Пис.

С нетерпением ждем ваших ценных предложений и материалов.