Реализация комплексных проектов глубокого обучения никогда не была проще с этими замечательными инструментами.

LLM, такие как GPT, BERT и Llama 2, меняют правила игры в области искусственного интеллекта. Используя эти модели, вы можете создавать инструменты искусственного интеллекта, такие как ChatGPT и Bard. Но вам необходимо точно настроить эти языковые модели при выполнении проектов глубокого обучения. Именно здесь на помощь приходят платформы искусственного интеллекта.

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

  • Точная настройка модели BERT с помощью библиотеки Transformers для классификации текста.
  • Создание веб-приложения с помощью Gradio.
  • Мониторинг этого приложения с помощью Comet.

После создания приложения оно будет выглядеть так, как показано ниже:

Вы можете использовать этот блокнот Kaggle, чтобы следить за кодом вместе со мной и просматривать этот репозиторий, чтобы просмотреть файлы проекта.

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

Шаг 1. Установка необходимых библиотек

Первое, что мы собираемся сделать, это установить необходимые библиотеки. Это очень легко сделать с помощью менеджера пакетов pip, как показано ниже:

!pip install -q comet_ml transformers datasets gradio

После этого давайте продолжим и инициализируем платформы, которые мы будем использовать.

Шаг 2. Инициализация кометы и обнимающего лица

Чтобы отслеживать наши гиперпараметры и контролировать наше приложение, мы будем использовать Comet. Для этого нам сначала нужно его инициализировать, как показано ниже:

import comet_ml

# Initializing the project
comet_ml.init(project_name="text-classification-with-transformers")

После запуска этого фрагмента вам необходимо ввести ключ Comet API. Перейдите в Comet и создайте бесплатную учетную запись, чтобы получить ключ API.

Кроме того, после обучения нашей модели LLM мы перенесем ее в Hugging Face Spaces, что позволит вам разместить демонстрационные приложения ML в своем профиле.

Войти в Hugging Face с помощью метода notebook_login очень просто. Для этого используйте API-ключ Hugging Face. Если у вас нет ключа API, вы можете получить его бесплатно здесь.

from huggingface_hub import notebook_login

# Logining Hugging Face
notebook_login()

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

Шаг 3. Загрузите данные

Набор данных, который мы будем использовать, представляет собой набор данных обзоров фильмов под названием гнилые помидоры. К счастью, этот набор данных доступен в библиотеке наборов данных. Все, что нам нужно сделать, это загрузить этот набор данных с помощью метода load_dataset. Давай сделаем это:

from datasets import load_dataset

# Loading the dataset
raw_datasets = load_dataset("rotten_tomatoes")

Отлично, наши данные загружены. Давайте посмотрим на эти данные:

raw_datasets

# Output:
""""
DatasetDict({
    train: Dataset({
        features: ['text', 'label'],
        num_rows: 8530
    })
    validation: Dataset({
        features: ['text', 'label'],
        num_rows: 1066
    })
    test: Dataset({
        features: ['text', 'label'],
        num_rows: 1066
    })
})
"""

Как видите, данные очень похожи на словарь Python, где каждый ключ соответствует отдельному набору данных. Мы можем использовать обычный синтаксис словаря, чтобы просмотреть один разбиение:

# Looking at the first sample of the training set
raw_datasets["train"][0]

# Output:
"""
{'text': 'the rock is destined to be the 21st century\'s new " conan " and that he\'s going to make a splash even greater than arnold schwarzenegger , jean-claud van damme or steven segal .',
 'label': 1}
"""

Отлично, мы увидели первый образец набора обучающих данных. Теперь, чтобы получить больше информации о данных, давайте преобразуем их в Pandas DataFrame.

Шаг 4. Понимание данных

Понимание данных — один из наиболее важных этапов жизненного цикла анализа данных. Для этого нет никаких сомнений в том, что панды — короли.

От наборов данных к фреймам данных Pandas

Сначала позвольте мне преобразовать данные в Pandas DataFrame с помощью метода set_format следующим образом:

import pandas as pd

# Converting the dataset into Pandas dataframe
raw_datasets.set_format(type="pandas")
df = raw_datasets["train"][:]
df.head()

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

Анализ распределения меток

Самый простой способ понять данные — это визуализировать их. Давайте нарисуем гистограмму с помощью Matplotlib, чтобы посмотреть на распределение меток.

import matplotlib.pyplot as plt

# Visualizing the frequency of classes
df["label_name"].value_counts(ascending=True).plot.barh()
plt.title("Frequency of Classes")
plt.show()

Как видите, распределение меток сбалансировано.

Какова длина наших текстов?

Модель, которую мы будем использовать, — DistilBERT. Как и другие модели трансформеров, эта модель имеет максимальную длину входного текста. Это число 512.

Давайте посмотрим на распределение слов по отзывам:

# Visualizing words per review
df["Words Per Review"] = df["text"].str.split().apply(len)
df.boxplot("Words Per Review", by="label_name", grid=False, showfliers=False,
           color="black")
plt.suptitle("")
plt.xlabel("")
plt.show()

Как видите, длина большинства обзоров составляет около 15 слов, а самые длинные обзоры значительно меньше максимального размера последовательности DistilBERT.

Отлично, мы проверили наши данные. Поскольку формат DataFrame нам больше не нужен, давайте сбросим формат нашего набора данных:

# Reseting the dataset format
raw_datasets.reset_format()

Теперь мы готовы к предварительной обработке данных. Давай сделаем это.

Шаг 5. Предварительная обработка данных

Модели глубокого обучения не любят необработанные строки в качестве входных данных. Вместо этого они хотят, чтобы текст был закодирован как числовое представление. Вот тут-то и приходит на помощь токенизация. Токенизация — это способ разбить предложения на более мелкие единицы, называемые токенами.

Нам повезло, что в Transformers есть класс AutoTokenizer. Этот класс помогает быстро загрузить токенизатор, связанный с предварительно обученной моделью. Все, что вам нужно сделать, это вызвать метод from_pretrained вашей модели. В нашем случае начнем с загрузки токенизатора для DistilBERT следующим образом:

from transformers import AutoTokenizer

# Loading the DistilBERT tokenizer 
checkpoint = "distilbert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)

Хорошо, наш токенизатор готов применить весь корпус. Давайте создадим функцию предварительной обработки и передадим ей параметр truncation. Этот параметр усекает тексты до максимального входного размера модели.

После создания функции давайте маркируем наши наборы данных, используя метод map с параметром batched. Этот параметр ускоряет работу функции за счет одновременной обработки нескольких элементов набора данных.

# Creating a function for tokenization
def tokenize_function(examples):
    return tokenizer(examples["text"], truncation=True)

# Applying the function to the entire dataset
tokenized_datasets = raw_datasets.map(tokenize_function, batched=True)

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

from transformers import DataCollatorWithPadding

# Padding
data_collator = DataCollatorWithPadding(tokenizer=tokenizer)

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

Шаг 6. Функция оценки

Как вы знаете, метрики помогают нам оценить производительность модели. Для этого анализа мы рассчитаем показатели точности, прецизионности, полноты и f1.

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

from sklearn.metrics import accuracy_score, precision_recall_fscore_support

# Indexing to example function
def get_example(index):
    return tokenized_datasets["test"][index]["text"]

# Creating a function to compute metrics
def compute_metrics(pred):
    experiment = comet_ml.get_global_experiment()

    labels = pred.label_ids
    preds = pred.predictions.argmax(-1)
    precision, recall, f1, _ = precision_recall_fscore_support(
        labels, preds, average="macro"
    )
    acc = accuracy_score(labels, preds)

    if experiment:
        epoch = int(experiment.curr_epoch) if experiment.curr_epoch is not None else 0
        experiment.set_epoch(epoch)
        experiment.log_confusion_matrix(
            y_true=labels,
            y_predicted=preds,
            file_name=f"confusion-matrix-epoch-{epoch}.json",
            labels=["negative", "positive"],
            index_to_example_function=get_example,
        )

    return {"accuracy": acc, "f1": f1, "precision": precision, "recall": recall}

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

Шаг 7. Модель трансформатора

Поверьте, подогнать модель с помощью Трансформеров несложно.

Сначала создайте экземпляр своей модели с помощью класса AutoModelForSequenceClassification, а затем настройте эту модель в соответствии с вашими данными с помощью параметра num_labels. Это просто, правда?

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

from transformers import AutoModelForSequenceClassification

# Mapping ids to labels 
id2label = {0: "NEGATIVE", 1: "POSITIVE"}
label2id = {"NEGATIVE": 0, "POSITIVE": 1}

# Building the model
model = AutoModelForSequenceClassification.from_pretrained(
              checkpoint, num_labels=2, id2label=id2label, label2id=label2id)

Отлично, мы загрузили нашу предварительно обученную модель. Давайте продолжим и начнем обучать эту модель.

Шаг 8. Запустите обучение

Пришло время обучить модель. Сначала давайте определим параметры обучения, используя класс TrainingArguments. На этом этапе мы установим push_to_hub=True, чтобы отправить эту модель в наш концентратор Hugging Face Hub, и report_to=["comet_ml"], чтобы отслеживать наши гиперпараметры на панели управления Comet.

После этого мы собираемся создать экземпляр нашей модели и точно настроить ее с помощью Trainer..

Наконец, мы собираемся вызвать метод train, чтобы начать обучение. Вот и все.

from transformers import TrainingArguments, Trainer

# Setting Comet enviroment variables
%env COMET_MODE=ONLINE
%env COMET_LOG_ASSETS=TRUE

# Setting training arguments
training_args = TrainingArguments(
    output_dir="my_distilbert_model",
    learning_rate=2e-5,
    per_device_train_batch_size=16,
    per_device_eval_batch_size=16,
    num_train_epochs=3,
    weight_decay=0.01,
    evaluation_strategy="epoch",
    save_strategy="epoch",
    load_best_model_at_end=True,
    push_to_hub=True,
    report_to=["comet_ml"],
)

# Creating a trainer object
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_datasets["train"],
    eval_dataset=tokenized_datasets["test"],
    compute_metrics=compute_metrics,
    data_collator=data_collator,
)

# Training the model
trainer.train()

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

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

# Pushing the model
trainer.push_to_hub()

Наша модель выглядит в моем хабе вот так:

Давайте посмотрим, как предсказать метку текста, которого модель раньше не видела.

Шаг 9. Вывод

Теперь у нас есть модель в Hugging Face Hub. Пришло время сделать прогноз с использованием этой модели. Самый простой способ сделать это — использовать конвейер. Все, что нам нужно сделать, это передать ему нашу модель. Давай сделаем это:

from transformers import pipeline

# Creating a text
text = "This is a great movie. It may be my favourite."

# Predicting the label
classifier = pipeline("sentiment-analysis", 
                       model="Tirendaz/my_distilbert_model")
classifier(text)

# Output:
# [{'label': 'POSITIVE', 'score': 0.971620500087738}]

Как видите, прогноз был сделан, и подсчитана оценка за этот прогноз. Наша модель правильно предсказала название текста.

Давайте перейдем к развертыванию нашей модели с помощью Gradio.

Шаг 10. Развертывание

На последнем этапе мы расскажем вам, как поделиться нашей моделью с сообществом. Gradio — король, когда дело доходит до обмена моделями машинного обучения.

Важно отметить, что вы можете отображать свое приложение на Hugging Face Hub. Кроме того, вы можете использовать панель управления Comet, чтобы поделиться ею с друзьями. Все, что вам нужно сделать, это использовать объект comet_ml.Experiment.

import gradio as gr
from transformers import pipeline

# Creating pipeline
classifier = pipeline("sentiment-analysis", 
                      model="Tirendaz/my_distilbert_model")

# Creating a function for text classification
def text_classification(text):
    result= classifier(text)
    sentiment_label = result[0]['label']
    sentiment_score = result[0]['score']
    formatted_output = f"This sentiment is {sentiment_label} with the probability {sentiment_score*100:.2f}%"
    return formatted_output

# Getting examples 
examples=["This is wonderful movie!", "The movie was really bad; I didn't like it."]

# Building a Gradio interface
io = gr.Interface(fn=text_classification, 
                         inputs= gr.Textbox(lines=2, label="Text", placeholder="Enter title here..."), 
                         outputs=gr.Textbox(lines=2, label="Text Classification Result"),
                         title="Text Classification",
                         description="Enter a text and see the text classification result!",
                         examples=examples)

io.launch(inline=False, share=True)

# Logging the app to the Comet Dashboard
experiment = comet_ml.Experiment()
experiment.add_tag("text-classifier")

# Integrating Comet
io.integrate(comet_ml=experiment)

Отлично, мы создали наше веб-приложение. На панели управления Comet это будет выглядеть так:

Как видите, мы зарегистрировали наше приложение Gradio в Comet. Теперь мы можем взаимодействовать с ним, используя пользовательскую панель Gradio, как указано выше.

Заворачивать

Поздравляем, теперь вы знаете, как создать приложение классификации текста на основе BERT для классификации меток текста. Как видите, благодаря недавно разработанным платформам это стало очень просто.

В этой статье мы сначала настроили модель BERT с помощью Transformers, создали приложение Gradio с использованием этой модели, а затем продемонстрировали ее на панели управления Comet.

Вот и все. Спасибо за прочтение. Подключим Ютуб | Твиттер | Линкедин





Если вам понравилась эта статья, не забудьте несколько раз нажать кнопку 👏 ниже 👇

Ресурсы:

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

Независимый от редакции, Heartbeat спонсируется и публикуется Comet, платформой MLOps, которая позволяет специалистам по данным и командам машинного обучения отслеживать, сравнивать, объяснять и оптимизировать свои эксперименты. Мы платим нашим авторам и не продаем рекламу.

Если вы хотите внести свой вклад, перейдите к нашему приглашению к участию. Вы также можете подписаться на нашу еженедельную рассылку новостей (Deep Learning Weekly), посетить блог Comet, присоединиться к нам в Slack и подписаться на Comet в Twitter и LinkedIn для получения ресурсов и событий. и многое другое, что поможет вам быстрее создавать более качественные модели машинного обучения.