Освоение сверхспособностей NLP пошаговое руководство по настройке Hugging Face Fine Tuning

Освоение сверхспособностей NLP Пошаговое руководство по настройке Fine Tuning Hugging Face

Введение

Тонкая настройка модели обработки естественного языка (Natural Language Processing, NLP) включает изменение гиперпараметров и архитектуры модели и обычно корректировку набора данных для улучшения результатов модели на задаче. Это можно достичь путем регулировки скорости обучения, количества слоев в модели, размера эмбеддингов и других параметров. Тонкая настройка является трудоемкой процедурой, требующей глубокого понимания модели и постановки задачи. В этой статье будут рассмотрены основы тонкой настройки модели от Hugging Face.

Цели обучения

  • Понять структуру модели T5, включая Трансформеры и механизм само-внимания.
  • Научиться оптимизировать гиперпараметры для повышения производительности модели.
  • Овладеть подготовкой текстовых данных, включая токенизацию и форматирование.
  • Узнать, как адаптировать предобученные модели к конкретным задачам.
  • Научиться очищать, разделять и создавать наборы данных для обучения.
  • Получить опыт тренировки и оценки модели с использованием метрик, таких как потери и точность.
  • Исследовать реальные применения тонко настроенной модели для генерации ответов или решений.

Эта статья была опубликована в рамках Data Science Blogathon.

О моделях Hugging Face

Hugging Face – это компания, предоставляющая платформу для обучения и развертывания моделей обработки естественного языка (Natural Language Processing, NLP). Платформа содержит библиотеку моделей, подходящих для различных задач NLP, включая перевод языка, генерацию текста и вопросно-ответной анализ. Эти модели обучаются на обширных наборах данных и разработаны для успешного выполнения широкого спектра задач обработки естественного языка (NLP).

Платформа Hugging Face также предоставляет инструменты для тонкой настройки предобученных моделей на конкретных наборах данных, что помогает адаптировать алгоритмы к определенным областям или языкам. В платформе также есть API для доступа и использования предобученных моделей в приложениях и инструменты для создания индивидуальных моделей и их развертывания в облаке.

Использование библиотеки Hugging Face для задач обработки естественного языка (NLP) имеет различные преимущества:

  1. Широкий выбор моделей: Библиотека Hugging Face предлагает широкий выбор предобученных моделей NLP, включая модели, обученные на задачах, таких как перевод языка, вопросно-ответный анализ и категоризация текста. Это позволяет легко выбрать модель, которая соответствует вашим требованиям.
  2. Совместимость с различными платформами: Библиотека Hugging Face совместима с такими стандартными системами глубокого обучения, как TensorFlow, PyTorch и Keras, что упрощает интеграцию в существующий рабочий процесс.
  3. Простая тонкая настройка: Библиотека Hugging Face содержит инструменты для тонкой настройки предобученных моделей на ваших наборах данных, что экономит время и усилия по сравнению с обучением модели с нуля.
  4. Активное сообщество: Библиотека Hugging Face имеет огромное и активное сообщество пользователей, что позволяет получить помощь и поддержку, а также внести свой вклад в развитие библиотеки.
  5. Хорошая документация: Библиотека Hugging Face содержит обширную документацию, что облегчает начало работы и эффективное использование.

Импорт необходимых библиотек

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

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
import torch
from transformers import T5Tokenizer
from transformers import T5ForConditionalGeneration, AdamW
import pytorch_lightning as pl
from pytorch_lightning.callbacks import ModelCheckpoint

pl.seed_everything(100)

import warnings
warnings.filterwarnings("ignore")

Импорт набора данных

Импорт набора данных — это важный первый шаг в проектах, основанных на данных.

df = pd.read_csv("/kaggle/input/queestion-answer-dataset-qa/train.csv")
df.columns

df = df[['context','question', 'text']]
print("Количество записей: ", df.shape[0])

Постановка проблемы

“Создать модель, способную генерировать ответы на основе контекста и вопросов.”

Например,

Контекст = “Группировка схожих случаев, например, позволяет найти похожих пациентов или использовать для сегментации клиентов в банковской сфере. Техника ассоциации используется для поиска элементов или событий, которые часто встречаются вместе, например, продукты в магазине, которые определенный клиент обычно покупает вместе. Обнаружение аномалий используется для выявления нетипичных и необычных случаев, например, обнаружение мошенничества с кредитными картами.”

Вопрос = “Каков пример обнаружения аномалий?”

Ответ = ????????????????????????????????

df["context"] = df["context"].str.lower()
df["question"] = df["question"].str.lower()
df["text"] = df["text"].str.lower()
df.head()

Инициализация параметров

  • Длина ввода: Во время обучения под длиной ввода понимается количество токенов (слов или символов), подаваемых на вход модели в одном примере. Если вы обучаете языковую модель для предсказания следующего слова в предложении, длина ввода будет равна количеству слов в фразе.
  • Длина вывода: Во время обучения модель должна сгенерировать определенное количество выходных токенов, таких как слова или символы, в одном образце. Длина вывода соответствует количеству слов, которые модель предсказывает внутри предложения.
  • Размер пакета для обучения: Во время обучения модель обрабатывает несколько образцов одновременно. Если вы устанавливаете размер пакета обучения равным 32, модель обрабатывает 32 экземпляра, например, 32 фразы, одновременно перед обновлением весов модели.
  • Размер пакета для проверки: Аналогично размеру пакета обучения, этот параметр указывает количество экземпляров, которые модель обрабатывает во время проверки. Другими словами, это объем данных, который модель обрабатывает при тестировании на отдельном наборе данных.
  • Эпохи: Эпоха — это одно обращение ко всему обучающему набору данных. Таким образом, если обучающий набор данных состоит из 1000 экземпляров, и размер пакета обучения составляет 32, одна эпоха потребует 32 обучающих шага. Если модель обучается в течение десяти эпох, она будет обрабатывать десять тысяч экземпляров (10 * 1000 = десять тысяч).
DEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
INPUT_MAX_LEN = 512 # Длина ввода
OUT_MAX_LEN = 128 # Длина вывода
TRAIN_BATCH_SIZE = 8 # Размер пакета обучения
VALID_BATCH_SIZE = 2 # Размер пакета для проверки
EPOCHS = 5 # Количество итераций

Трансформер T5

Модель T5 основана на архитектуре Transformer, нейронной сети, предназначенной для эффективной обработки последовательных входных данных. Она включает в себя энкодер и декодер, которые включают последовательность взаимосвязанных “слоев”.

Слои кодировщика и декодера содержат различные механизмы “внимания” и сети “feedforward”. Механизмы внимания позволяют модели сосредоточиться на разных секциях входной последовательности в разное время. В то же время, сети feedforward изменяют входные данные, используя набор весов и смещений.

Модель T5 также использует “self-attention”, который позволяет каждому элементу во входной последовательности обращать внимание на каждый другой элемент. Это позволяет модели распознавать связи между словами и фразами во входных данных, что критически важно для многих приложений обработки естественного языка.

В дополнение к кодировщику и декодеру, модель T5 содержит “голову языковой модели”, которая предсказывает следующее слово в последовательности на основе предыдущих слов. Это важно для задач перевода и создания текста, где модель должна предоставить связный и естественно звучащий вывод.

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

T5Tokenizer

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

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

T5Tokenizer также вставляет уникальные токены в текст, чтобы обозначить начало и конец предложений и разделить их. Например, он добавляет токены s > и / s >, чтобы обозначить начало и конец фразы, и pad > для обозначения заполнения.

MODEL_NAME = "t5-base"tokenizer = T5Tokenizer.from_pretrained(MODEL_NAME, model_max_length= INPUT_MAX_LEN)

print("eos_token: {} и id: {}".format(tokenizer.eos_token,                   tokenizer.eos_token_id)) # Конец токена (eos_token)print("unk_token: {} и id: {}".format(tokenizer.unk_token,                   tokenizer.eos_token_id)) # Неизвестный токен (unk_token)print("pad_token: {} и id: {}".format(tokenizer.pad_token,                 tokenizer.eos_token_id)) # Токен заполнения (pad_token)

Подготовка набора данных

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

Метод init заполняет набор данных списком текстов, списком меток и токенизатором. Функция len возвращает количество образцов в наборе данных. Функция getitem возвращает один элемент из набора данных по индексу. Она принимает индекс idx и выдает токенизированный ввод и метки.

Также принято включать различные этапы предварительной обработки, такие как заполнение и обрезка токенизированных входов. Вы также можете преобразовать метки в тензоры.

class T5Dataset:    def __init__(self, context, question, target):        self.context = context        self.question = question        self.target = target        self.tokenizer = tokenizer        self.input_max_len = INPUT_MAX_LEN        self.out_max_len = OUT_MAX_LEN    def __len__(self):        return len(self.context)    def __getitem__(self, item):        context = str(self.context[item])        context = " ".join(context.split())        question = str(self.question[item])        question = " ".join(question.split())        target = str(self.target[item])        target = " ".join(target.split())                        inputs_encoding = self.tokenizer(            context,            question,            add_special_tokens=True,            max_length=self.input_max_len,            padding = 'max_length',            truncation='only_first',            return_attention_mask=True,            return_tensors="pt"        )                output_encoding = self.tokenizer(            target,            None,            add_special_tokens=True,            max_length=self.out_max_len,            padding = 'max_length',            truncation= True,            return_attention_mask=True,            return_tensors="pt"        )        inputs_ids = inputs_encoding["input_ids"].flatten()        attention_mask = inputs_encoding["attention_mask"].flatten()        labels = output_encoding["input_ids"]        labels[labels == 0] = -100  # Согласно документации T5        labels = labels.flatten()        out = {            "context": context,            "question": question,            "answer": target,            "inputs_ids": inputs_ids,            "attention_mask": attention_mask,            "targets": labels        }        return out   

DataLoader

Класс DataLoader загружает данные параллельно и по пакетам, что позволяет работать с большими наборами данных, которые иначе были бы слишком объемными для хранения в памяти. Комбинация класса DataLoader с классом набора данных, содержащего данные для загрузки.

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

class T5DatasetModule(pl.LightningDataModule):    def __init__(self, df_train, df_valid):        super().__init__()        self.df_train = df_train        self.df_valid = df_valid        self.tokenizer = tokenizer        self.input_max_len = INPUT_MAX_LEN        self.out_max_len = OUT_MAX_LEN    def setup(self, stage=None):        self.train_dataset = T5Dataset(        context=self.df_train.context.values,        question=self.df_train.question.values,        target=self.df_train.text.values        )        self.valid_dataset = T5Dataset(        context=self.df_valid.context.values,        question=self.df_valid.question.values,        target=self.df_valid.text.values        )    def train_dataloader(self):        return torch.utils.data.DataLoader(         self.train_dataset,         batch_size= TRAIN_BATCH_SIZE,         shuffle=True,          num_workers=4        )    def val_dataloader(self):        return torch.utils.data.DataLoader(         self.valid_dataset,         batch_size= VALID_BATCH_SIZE,         num_workers=1        )

Построение модели

При создании модели-трансформера в PyTorch обычно начинают с создания нового класса, который производный от torch. nn.Module. В этом классе описывается архитектура модели, включая слои и функцию forward. Инициализирующая функция класса определяет архитектуру модели, часто путем создания экземпляров разных уровней модели и их присвоения в качестве атрибутов класса.

Метод forward отвечает за передачу данных через модель в прямом направлении. Этот метод принимает входные данные и применяет слои модели для создания выходных данных. Метод forward должен реализовывать логику модели, такую как передачу входа через последовательность слоев и возврат результата.

Инициализирующая функция класса создает слой вложения, слой трансформера и полносвязный слой, и присваивает их в качестве атрибутов класса. Метод forward принимает входные данные x, обрабатывает их с помощью заданных этапов и возвращает результат. При обучении модели-трансформера обычно используются два этапа: обучение и валидация.

Метод training_step определяет рационал для выполнения одного шага обучения, который обычно включает:

  • прямое прохождение через модель
  • вычисление потерь
  • вычисление градиентов
  • Обновление параметров модели

Метод val_step, подобно методу training_step, используется для оценки модели на валидационном наборе данных. Обычно он включает:

  • прямое прохождение через модель
  • вычисление метрик оценки
class T5Model(pl.LightningModule):        def __init__(self):        super().__init__()        self.model = T5ForConditionalGeneration.from_pretrained(MODEL_NAME, return_dict=True)    def forward(self, input_ids, attention_mask, labels=None):        output = self.model(            input_ids=input_ids,             attention_mask=attention_mask,             labels=labels        )        return output.loss, output.logits    def training_step(self, batch, batch_idx):        input_ids = batch["inputs_ids"]        attention_mask = batch["attention_mask"]        labels= batch["targets"]        loss, outputs = self(input_ids, attention_mask, labels)                self.log("train_loss", loss, prog_bar=True, logger=True)        return loss    def validation_step(self, batch, batch_idx):        input_ids = batch["inputs_ids"]        attention_mask = batch["attention_mask"]        labels= batch["targets"]        loss, outputs = self(input_ids, attention_mask, labels)        self.log("val_loss", loss, prog_bar=True, logger=True)                return loss    def configure_optimizers(self):        return AdamW(self.parameters(), lr=0.0001)

Обучение модели

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

def run():        df_train, df_valid = train_test_split(        df[0:10000], test_size=0.2, random_state=101    )        df_train = df_train.fillna("none")    df_valid = df_valid.fillna("none")        df_train['context'] = df_train['context'].apply(lambda x: " ".join(x.split()))    df_valid['context'] = df_valid['context'].apply(lambda x: " ".join(x.split()))        df_train['text'] = df_train['text'].apply(lambda x: " ".join(x.split()))    df_valid['text'] = df_valid['text'].apply(lambda x: " ".join(x.split()))        df_train['question'] = df_train['question'].apply(lambda x: " ".join(x.split()))    df_valid['question'] = df_valid['question'].apply(lambda x: " ".join(x.split()))       df_train = df_train.reset_index(drop=True)    df_valid = df_valid.reset_index(drop=True)        dataModule = T5DatasetModule(df_train, df_valid)    dataModule.setup()    device = DEVICE    models = T5Model()    models.to(device)    checkpoint_callback  = ModelCheckpoint(        dirpath="/kaggle/working",        filename="best_checkpoint",        save_top_k=2,        verbose=True,        monitor="val_loss",        mode="min"    )    trainer = pl.Trainer(        callbacks = checkpoint_callback,        max_epochs= EPOCHS,        gpus=1,        accelerator="gpu"    )    trainer.fit(models, dataModule)run()

Прогноз модели

Чтобы делать прогнозы с использованием настроенной модели NLP, такой как T5, для новых входных данных, можно следовать следующим шагам:

  • Предварительная обработка новых входных данных: Токенизировать и предварительно обработать новый входной текст, чтобы он соответствовал предварительной обработке, примененной к данным обучения. Убедитесь, что он находится в правильном формате, ожидаемом моделью.
  • Использование настроенной модели для вывода: Загрузите настроенную модель T5, которую вы ранее обучили или загрузили из контрольной точки.
  • Генерация прогнозов: Передайте предварительно обработанный новый ввод модели для прогнозирования. В случае T5 вы можете использовать метод generate для генерации ответов.
train_model = T5Model.load_from_checkpoint("/kaggle/working/best_checkpoint-v1.ckpt")
train_model.freeze()
def generate_question(context, question):
    inputs_encoding = tokenizer(
        context,
        question,
        add_special_tokens=True,
        max_length=INPUT_MAX_LEN,
        padding='max_length',
        truncation='only_first',
        return_attention_mask=True,
        return_tensors="pt"
        )
    generate_ids = train_model.model.generate(
        input_ids=inputs_encoding["input_ids"],
        attention_mask=inputs_encoding["attention_mask"],
        max_length=INPUT_MAX_LEN,
        num_beams=4,
        num_return_sequences=1,
        no_repeat_ngram_size=2,
        early_stopping=True,
        )
    preds = [
        tokenizer.decode(gen_id, skip_special_tokens=True, clean_up_tokenization_spaces=True)
        for gen_id in generate_ids
    ]
    return "".join(preds)

Прогноз

Давайте сгенерируем прогноз с использованием настроенной модели T5 на новых входных данных:

context = “Группировка похожих случаев, например, обнаружение схожих пациентов или использование для сегментации клиентов в банковской сфере. Использование техники ассоциации для поиска элементов или событий, которые часто встречаются вместе, например, продукты питания, которые обычно покупаются вместе определенным клиентом. Использование обнаружения аномалий для обнаружения ненормальных и необычных случаев, например, обнаружение мошенничества с кредитными картами.”

que = “Какой пример аномального обнаружения?”

print(generate_question(context, que))

context = "Классификация используется, когда ваша цель категориальна, а регрессия используется, когда ваша целевая переменная непрерывна. Классификация и регрессия относятся к категории алгоритмов машинного обучения с учителем."
que = "Когда используется классификация?"
print(generate_question(context, que))

Заключение

В этой статье мы отправились в путешествие, чтобы настроить модель обработки естественного языка (NLP), а именно модель T5, для задачи ответа на вопросы. В ходе этого процесса мы изучили различные аспекты разработки и развертывания моделей NLP.

Основные выводы:

  • Исследована структура кодировщика-декодировщика и механизмы самовнимания, лежащие в основе его возможностей.
  • Искусство настройки гиперпараметров является важным навыком для оптимизации производительности модели.
  • Экспериментирование с learning rate, размером пакета и размерами модели позволило нам эффективно настроить модель.
  • Умение токенизировать, заполнять и преобразовывать исходные текстовые данные в подходящий формат для ввода в модель.
  • Рассмотрено настройку модели, включая загрузку предобученных весов, модификацию слоев модели и их адаптацию к конкретным задачам.
  • Изучено, как очистить и структурировать данные, разделив их на обучающий и проверочный наборы.
  • Показано, как модель может генерировать ответы на основе контекста ввода и вопросов, демонстрируя ее применимость в реальном мире.

Часто задаваемые вопросы

Представленные в статье изображения не принадлежат Analytics Vidhya и используются на усмотрение автора.