GPT2 для классификации текста с помощью преобразователей обнимающего лица

Исходный узел: 809063

классификация текста

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

Нам очень приятно, что Hugging Face включает в себя все функции, необходимые для использования GPT2 в задачах классификации. Спасибо, Обнимающее лицо!

Мне не удалось найти много информации о том, как использовать GPT2 для классификации, поэтому я решил сделать это руководство, используя аналогичную структуру с другими моделями трансформаторов.

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

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

Другими словами, вместо того, чтобы использовать встраивание первого токена для прогнозирования, как мы делаем в Bert, мы будем использовать вложение последнего токена для прогнозирования с помощью GPT2.

Поскольку нас интересовал только первый токен в Bert, мы двигались вправо. Теперь в GPT2 мы используем последний токен для прогнозирования, поэтому нам нужно будет ввести его слева. Благодаря хорошему обновлению HuggingFace Transformers мы можем настроить токенизатор GPT2 для этого.

Что мне нужно знать об этом ноутбуке?

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

Зная немного о трансформеры библиотека тоже помогает.

Как пользоваться этим ноутбуком?

Как и в любом другом проекте, я создавал этот ноутбук с расчетом на возможность повторного использования.

Все изменения произойдут в части обработки данных, где вам необходимо настроить набор данных PyTorch, Data Collator и DataLoader в соответствии с вашими потребностями в данных.

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

Dataset

В этой записной книжке будет рассказано о предварительном обучении трансформаторов на настраиваемом наборе данных. Я буду использовать обзоры известных фильмов с положительной или отрицательной меткой. Большой набор данных обзора фильмов.

Описание на сайте Стэнфорда:

Это набор данных для двоичной классификации тональности, содержащий значительно больше данных, чем предыдущие наборы контрольных данных. Мы предоставляем набор из 25,000 25,000 крайне полярных обзоров фильмов для обучения и XNUMX XNUMX для тестирования. Также есть дополнительные немаркированные данные. Предоставляются форматы исходного текста и уже обработанного пакета слов. См. Файл README, содержащийся в выпуске, для получения более подробной информации.

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

Кодирование

Теперь займемся кодированием! Мы рассмотрим каждую ячейку кодирования в записной книжке и опишем, что она делает, что это за код и когда это актуально, - покажем результат.

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

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

Скачать

Скачать Большой набор данных обзора фильмов и разархивируйте его локально.

Download the dataset.
!wget -q -nc http://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz
Unzip the dataset.
!tar -zxf /content/aclImdb_v1.tar.gz

Устанавливается

  • трансформеры необходимо установить библиотеку, чтобы использовать весь замечательный код от Hugging Face. Чтобы получить последнюю версию, я установлю ее прямо с GitHub.
  • мл_вещи библиотека, используемая для различных задач, связанных с машинным обучением. Я создал эту библиотеку, чтобы уменьшить объем кода, который мне нужно написать для каждого проекта машинного обучения.
# Install transformers library.
!pip install -q git+https://github.com/huggingface/transformers.git
# Install helper functions.
!pip install -q git+https://github.com/gmihaila/ml_things.git
Installing build dependencies ... done Getting requirements to build wheel ... done Preparing wheel metadata ... done |████████████████████████████████| 2.9MB 6.7MB/s |████████████████████████████████| 890kB 48.9MB/s |████████████████████████████████| 1.1MB 49.0MB/s Building wheelfor transformers (PEP 517) ... done Building wheel for sacremoses (setup.py) ... done |████████████████████████████████| 71kB 5.2MB/s Building wheel for ml-things (setup.py) ... done Building wheel for ftfy (setup.py) ... done

Импорт

Импортируйте все необходимые библиотеки для этого блокнота. Объявите параметры, используемые для этого блокнота:

  • set_seed(123) - Всегда полезно устанавливать фиксированные семена для воспроизводимости.
  • epochs - Количество эпох обучения (авторы рекомендуют от 2 до 4).
  • batch_size - Количество пакетов - в зависимости от максимальной длины последовательности и памяти графического процессора. Для длины последовательности 512 пакет из 10 ОБЫЧНЫХ работает без проблем с памятью cuda. Для небольшой длины последовательности можно попробовать пакет из 32 и выше. max_length - дополняет или усекает текстовые последовательности до определенной длины. Я установлю 60, чтобы ускорить тренировку.
  • device - Ищите GPU для использования. Если графический процессор не найден, по умолчанию будет использоваться процессор.
  • model_name_or_path - Название модели трансформаторов - будет использоваться уже предварительно обученная модель. Путь к модели трансформатора - загрузит вашу собственную модель с локального диска. В этом уроке я буду использовать gpt2 модели.
  • labels_ids - Словарь меток и их идентификаторов - будет использоваться для преобразования строковых меток в числа.
  • n_labels - Сколько меток мы используем в этом наборе данных. Это используется для определения размера классификационной головки.
import io
import os
import torch
from tqdm.notebook import tqdm
from torch.utils.data import Dataset, DataLoader
from ml_things import plot_dict, plot_confusion_matrix, fix_text
from sklearn.metrics import classification_report, accuracy_score
from transformers import (set_seed, TrainingArguments, Trainer, GPT2Config, GPT2Tokenizer, AdamW, get_linear_schedule_with_warmup, GPT2ForSequenceClassification) # Set seed for reproducibility.
set_seed(123) # Number of training epochs (authors on fine-tuning Bert recommend between 2 and 4).
epochs = 4 # Number of batches - depending on the max sequence length and GPU memory.
# For 512 sequence length batch of 10 works without cuda memory issues.
# For small sequence length can try batch of 32 or higher.
batch_size = 32 # Pad or truncate text sequences to a specific length
# if `None` it will use maximum sequence of word piece tokens allowed by model.
max_length = 60 # Look for gpu to use. Will use `cpu` by default if no gpu found.
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') # Name of transformers model - will use already pretrained model.
# Path of transformer model - will load your own model from local disk.
model_name_or_path = 'gpt2' # Dictionary of labels and their id - this will be used to convert.
# String labels to number ids.
labels_ids = {'neg': 0, 'pos': 1} # How many labels are we using in training.
# This is used to decide size of classification head.
n_labels = len(labels_ids)

Вспомогательные функции

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

MovieReviewsDataset (набор данных)

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

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

Я буду добавлять все тексты и надписи в списки.

Класс PyTorch Dataset состоит из трех основных частей:

  • в этом() где мы читаем набор данных и преобразуем текст и метки в числа.
  • len () где нам нужно вернуть количество примеров, которые мы читаем. Это используется при вызове len (MovieReviewsDataset ()).
  • getitem () всегда принимает в качестве входных данных значение типа int, которое представляет, какой пример из наших примеров следует вернуть из нашего набора данных. Если передано значение 3, мы вернем пример из нашего набора данных в позиции 3.
class MovieReviewsDataset(Dataset): r"""PyTorch Dataset class for loading data. This is where the data parsing happens. This class is built with reusability in mind: it can be used as is as. Arguments: path (:obj:`str`): Path to the data partition. """ def __init__(self, path, use_tokenizer): # Check if path exists. if not os.path.isdir(path): # Raise error if path is invalid. raise ValueError('Invalid `path` variable! Needs to be a directory') self.texts = [] self.labels = [] # Since the labels are defined by folders with data we loop # through each label. for label in ['pos', 'neg']: sentiment_path = os.path.join(path, label) # Get all files from path. files_names = os.listdir(sentiment_path)#[:10] # Sample for debugging. # Go through each file and read its content. for file_name in tqdm(files_names, desc=f'{label} files'): file_path = os.path.join(sentiment_path, file_name) # Read content. content = io.open(file_path, mode='r', encoding='utf-8').read() # Fix any unicode issues. content = fix_text(content) # Save content. self.texts.append(content) # Save encode labels. self.labels.append(label) # Number of exmaples. self.n_examples = len(self.labels) return def __len__(self): r"""When used `len` return the number of examples. """ return self.n_examples def __getitem__(self, item): r"""Given an index return an example from the position. Arguments: item (:obj:`int`): Index position to pick an example to return. Returns: :obj:`Dict[str, str]`: Dictionary of inputs that contain text and asociated labels. """ return {'text':self.texts[item], 'label':self.labels[item]}

Gpt2КлассификацияКоллатор

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

К счастью для нас, Hugging Face продумал все и заставил токенизатор делать всю тяжелую работу (разбивать текст на токены, дополнять, усекать, кодировать текст в числа) и очень прост в использовании!

Этот класс Data Collator состоит из двух основных частей:

  • в этом() где мы инициализируем токенизатор, который планируем использовать, как кодировать наши метки и нужно ли установить для длины последовательности другое значение.
  • вызов() используется как сборщик функций, который принимает в качестве входных данных набор примеров данных. Он должен вернуть объект в формате, который можно передать в нашу модель. К счастью, наш токенизатор делает это за нас и возвращает словарь переменных, готовых для передачи в модель следующим образом: model(**inputs). Поскольку мы дорабатываем модель, я также включил метки.
class Gpt2ClassificationCollator(object): r""" Data Collator used for GPT2 in a classificaiton rask. It uses a given tokenizer and label encoder to convert any text and labels to numbers that can go straight into a GPT2 model. This class is built with reusability in mind: it can be used as is as long as the `dataloader` outputs a batch in dictionary format that can be passed straight into the model - `model(**batch)`. Arguments: use_tokenizer (:obj:`transformers.tokenization_?`): Transformer type tokenizer used to process raw text into numbers. labels_ids (:obj:`dict`): Dictionary to encode any labels names into numbers. Keys map to labels names and Values map to number associated to those labels. max_sequence_len (:obj:`int`, `optional`) Value to indicate the maximum desired sequence to truncate or pad text sequences. If no value is passed it will used maximum sequence size supported by the tokenizer and model. """ def __init__(self, use_tokenizer, labels_encoder, max_sequence_len=None): # Tokenizer to be used inside the class. self.use_tokenizer = use_tokenizer # Check max sequence length. self.max_sequence_len = use_tokenizer.model_max_length if max_sequence_len is None else max_sequence_len # Label encoder used inside the class. self.labels_encoder = labels_encoder return def __call__(self, sequences): r""" This function allowes the class objesct to be used as a function call. Sine the PyTorch DataLoader needs a collator function, I can use this class as a function. Arguments: item (:obj:`list`): List of texts and labels. Returns: :obj:`Dict[str, object]`: Dictionary of inputs that feed into the model. It holddes the statement `model(**Returned Dictionary)`. """ # Get all texts from sequences list. texts = [sequence['text'] for sequence in sequences] # Get all labels from sequences list. labels = [sequence['label'] for sequence in sequences] # Encode all labels using label encoder. labels = [self.labels_encoder[label] for label in labels] # Call tokenizer on all texts to convert into tensors of numbers with # appropriate padding. inputs = self.use_tokenizer(text=texts, return_tensors="pt", padding=True, truncation=True, max_length=self.max_sequence_len) # Update the inputs with the associated encoded labels as tensor. inputs.update({'labels':torch.tensor(labels)}) return inputs

поезд (загрузчик данных, оптимизатор_, планировщик_, устройство_)

Я создал эту функцию, чтобы выполнить полный проход через объект DataLoader (объект DataLoader создается из нашего объекта типа Dataset * с использованием класса ** MovieReviewsDataset). По сути, это поезд одной эпохи по всему набору данных.

Загрузчик данных создается из PyTorch DataLoader, который берет объект, созданный из класса MovieReviewsDataset, и помещает каждый пример в пакеты. Таким образом, мы можем кормить нашу модель пакетами данных!

Optimizer_ и scheduler_ очень распространены в PyTorch. Они необходимы для обновления параметров нашей модели и обновления скорости обучения во время обучения. Есть еще много чего, но я не буду вдаваться в подробности. На самом деле это может быть огромная кроличья нора, поскольку за этими функциями стоит ОЧЕНЬ много, о чем нам не о чем беспокоиться. Спасибо, PyTorch!

В процессе мы отслеживаем фактические метки и прогнозируемые метки вместе с потерями.

def train(dataloader, optimizer_, scheduler_, device_): r""" Train pytorch model on a single pass through the data loader. It will use the global variable `model` which is the transformer model loaded on `_device` that we want to train on. This function is built with reusability in mind: it can be used as is as long as the `dataloader` outputs a batch in dictionary format that can be passed straight into the model - `model(**batch)`. Arguments: dataloader (:obj:`torch.utils.data.dataloader.DataLoader`): Parsed data into batches of tensors. optimizer_ (:obj:`transformers.optimization.AdamW`): Optimizer used for training. scheduler_ (:obj:`torch.optim.lr_scheduler.LambdaLR`): PyTorch scheduler. device_ (:obj:`torch.device`): Device used to load tensors before feeding to model. Returns: :obj:`List[List[int], List[int], float]`: List of [True Labels, Predicted Labels, Train Average Loss]. """ # Use global variable for model. global model # Tracking variables. predictions_labels = [] true_labels = [] # Total loss for this epoch. total_loss = 0 # Put the model into training mode. model.train() # For each batch of training data... for batch in tqdm(dataloader, total=len(dataloader)): # Add original labels - use later for evaluation. true_labels += batch['labels'].numpy().flatten().tolist() # move batch to device batch = {k:v.type(torch.long).to(device_) for k,v in batch.items()} # Always clear any previously calculated gradients before performing a # backward pass. model.zero_grad() # Perform a forward pass (evaluate the model on this training batch). # This will return the loss (rather than the model output) because we # have provided the `labels`. # The documentation for this a bert model function is here: # https://huggingface.co/transformers/v2.2.0/model_doc/bert.html#transformers.BertForSequenceClassification outputs = model(**batch) # The call to `model` always returns a tuple, so we need to pull the # loss value out of the tuple along with the logits. We will use logits # later to calculate training accuracy. loss, logits = outputs[:2] # Accumulate the training loss over all of the batches so that we can # calculate the average loss at the end. `loss` is a Tensor containing a # single value; the `.item()` function just returns the Python value # from the tensor. total_loss += loss.item() # Perform a backward pass to calculate the gradients. loss.backward() # Clip the norm of the gradients to 1.0. # This is to help prevent the "exploding gradients" problem. torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0) # Update parameters and take a step using the computed gradient. # The optimizer dictates the "update rule"--how the parameters are # modified based on their gradients, the learning rate, etc. optimizer.step() # Update the learning rate. scheduler.step() # Move logits and labels to CPU logits = logits.detach().cpu().numpy() # Convert these logits to list of predicted labels values. predictions_labels += logits.argmax(axis=-1).flatten().tolist() # Calculate the average loss over the training data. avg_epoch_loss = total_loss / len(dataloader) # Return all true labels and prediction for future evaluations. return true_labels, predictions_labels, avg_epoch_loss

проверка (загрузчик данных, устройство_)

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

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

В процессе я отслеживаю фактические метки и предсказанные метки вместе с потерями.

def validation(dataloader, device_): r"""Validation function to evaluate model performance on a separate set of data. This function will return the true and predicted labels so we can use later to evaluate the model's performance. This function is built with reusability in mind: it can be used as is as long as the `dataloader` outputs a batch in dictionary format that can be passed straight into the model - `model(**batch)`. Arguments: dataloader (:obj:`torch.utils.data.dataloader.DataLoader`): Parsed data into batches of tensors. device_ (:obj:`torch.device`): Device used to load tensors before feeding to model. Returns: :obj:`List[List[int], List[int], float]`: List of [True Labels, Predicted Labels, Train Average Loss] """ # Use global variable for model. global model # Tracking variables predictions_labels = [] true_labels = [] #total loss for this epoch. total_loss = 0 # Put the model in evaluation mode--the dropout layers behave differently # during evaluation. model.eval() # Evaluate data for one epoch for batch in tqdm(dataloader, total=len(dataloader)): # add original labels true_labels += batch['labels'].numpy().flatten().tolist() # move batch to device batch = {k:v.type(torch.long).to(device_) for k,v in batch.items()} # Telling the model not to compute or store gradients, saving memory and # speeding up validation with torch.no_grad(): # Forward pass, calculate logit predictions. # This will return the logits rather than the loss because we have # not provided labels. # token_type_ids is the same as the "segment ids", which # differentiates sentence 1 and 2 in 2-sentence tasks. # The documentation for this `model` function is here: # https://huggingface.co/transformers/v2.2.0/model_doc/bert.html#transformers.BertForSequenceClassification outputs = model(**batch) # The call to `model` always returns a tuple, so we need to pull the # loss value out of the tuple along with the logits. We will use logits # later to to calculate training accuracy. loss, logits = outputs[:2] # Move logits and labels to CPU logits = logits.detach().cpu().numpy() # Accumulate the training loss over all of the batches so that we can # calculate the average loss at the end. `loss` is a Tensor containing a # single value; the `.item()` function just returns the Python value # from the tensor. total_loss += loss.item() # get predicitons to list predict_content = logits.argmax(axis=-1).flatten().tolist() # update list predictions_labels += predict_content # Calculate the average loss over the training data. avg_epoch_loss = total_loss / len(dataloader) # Return all true labels and prediciton for future evaluations. return true_labels, predictions_labels, avg_epoch_loss

Модель загрузки и токенизатор

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

В этом примере я буду использовать gpt2 от предварительно обученных трансформеров HuggingFace. Вы можете использовать любые вариации GP2, какие захотите.

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

Создание tokenizer является довольно стандартным при использовании библиотеки Transformers. После создания токенизатора для этого руководства очень важно установить отступ влево. tokenizer.padding_side = "left" и инициализируйте маркер заполнения как tokenizer.eos_token который является исходным токеном конца последовательности GPT2. Это самая важная часть этого руководства, поскольку GPT2 использует последний токен для прогнозирования, поэтому нам нужно ввести его влево.

HuggingFace уже сделал большую часть работы за нас и добавил уровень классификации в модель GPT2. При создании модели я использовал GPT2ForSequenceClassification. Поскольку у нас есть собственный токен заполнения, нам нужно инициализировать его для модели, используя model.config.pad_token_id. Наконец, нам нужно будет переместить модель на устройство, которое мы определили ранее.

# Get model configuration.
print('Loading configuraiton...')
model_config = GPT2Config.from_pretrained(pretrained_model_name_or_path=model_name_or_path, num_labels=n_labels) # Get model's tokenizer.
print('Loading tokenizer...')
tokenizer = GPT2Tokenizer.from_pretrained(pretrained_model_name_or_path=model_name_or_path)
# default to left padding
tokenizer.padding_side = "left"
# Define PAD Token = EOS Token = 50256
tokenizer.pad_token = tokenizer.eos_token # Get the actual model.
print('Loading model...')
model = GPT2ForSequenceClassification.from_pretrained(pretrained_model_name_or_path=model_name_or_path, config=model_config) # resize model embedding to match new tokenizer
model.resize_token_embeddings(len(tokenizer)) # fix model padding token id
model.config.pad_token_id = model.config.eos_token_id # Load model to defined device.
model.to(device)
print('Model loaded to `%s`'%device)
Loading configuraiton... Loading tokenizer... Loading model... Some weights of GPT2ForSequenceClassification were not initialized from the model checkpoint at gpt2 and are newly initialized: ['score.weight'] You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference. Model loaded to `cuda`

Набор данных и подборщик

Здесь я создаю набор данных PyTorch и загрузчик данных с объектами Data Collator, которые будут использоваться для передачи данных в нашу модель.

Здесь я использую ФильмОтзывы для создания набора данных PyTorch, который будет возвращать тексты и метки.

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

Я держу токенизатор подальше от набора данных PyTorch, чтобы код был чище и лучше структурирован. Очевидно, вы можете использовать токенизатор внутри набора данных PyTorch и выходных последовательностей, которые можно использовать прямо в модели без использования Data Collator.

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

Сортировщик данных используется для форматирования выходных данных PyTorch Dataset в соответствии с входными данными, необходимыми для GPT2.

# Create data collator to encode text and labels into numbers.
gpt2_classificaiton_collator = Gpt2ClassificationCollator(use_tokenizer=tokenizer, labels_encoder=labels_ids, max_sequence_len=max_length) print('Dealing with Train...')
# Create pytorch dataset.
train_dataset = MovieReviewsDataset(path='/content/aclImdb/train', use_tokenizer=tokenizer)
print('Created `train_dataset` with %d examples!'%len(train_dataset)) # Move pytorch dataset into dataloader.
train_dataloader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True, collate_fn=gpt2_classificaiton_collator)
print('Created `train_dataloader` with %d batches!'%len(train_dataloader)) print() print('Dealing with Validation...')
# Create pytorch dataset.
valid_dataset = MovieReviewsDataset(path='/content/aclImdb/test', use_tokenizer=tokenizer)
print('Created `valid_dataset` with %d examples!'%len(valid_dataset)) # Move pytorch dataset into dataloader.
valid_dataloader = DataLoader(valid_dataset, batch_size=batch_size, shuffle=False, collate_fn=gpt2_classificaiton_collator)
print('Created `eval_dataloader` with %d batches!'%len(valid_dataloader))
Dealing with Train... pos files: 100%|████████████████████████████████|12500/12500 [01:17<00:00, 161.19it/s] neg files: 100%|████████████████████████████████|12500/12500 [01:05<00:00, 190.72it/s] Created `train_dataset` with 25000 examples! Created `train_dataloader` with 782 batches! Reading pos files... pos files: 100%|████████████████████████████████|12500/12500 [00:54<00:00, 230.93it/s] neg files: 100%|████████████████████████████████|12500/12500 [00:42<00:00, 291.07it/s] Created `valid_dataset` with 25000 examples! Created `eval_dataloader` with 782 batches!

Train

Я создал оптимизатор и планировщик, которые PyTorch использует на тренировках. Я использовал наиболее распространенные параметры, используемые в моделях трансформаторов.

Я перебрал количество определенных эпох и назвал поезд и Проверка функции.

Я пытаюсь выводить аналогичную информацию после каждой эпохи, как Керас: train_loss: - val_loss: - train_acc: - valid_acc.

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

Примечание: Графики обучения могут выглядеть немного странно: точность проверки начинается выше, чем точность обучения, а потери при проверке начинаются ниже, чем потери при обучении. Обычно бывает наоборот. Я предполагаю, что разделение данных просто проще для части проверки или слишком сложно для части обучения или того и другого. Поскольку это руководство посвящено использованию GPT2 для классификации, я не буду слишком беспокоиться о результатах модели.

# Note: AdamW is a class from the huggingface library (as opposed to pytorch) # I believe the 'W' stands for 'Weight Decay fix"
optimizer = AdamW(model.parameters(), lr = 2e-5, # default is 5e-5, our notebook had 2e-5 eps = 1e-8 # default is 1e-8. ) # Total number of training steps is number of batches * number of epochs.
# `train_dataloader` contains batched data so `len(train_dataloader)` gives # us the number of batches.
total_steps = len(train_dataloader) * epochs # Create the learning rate scheduler.
scheduler = get_linear_schedule_with_warmup(optimizer, num_warmup_steps = 0, # Default value in run_glue.py num_training_steps = total_steps) # Store the average loss after each epoch so we can plot them.
all_loss = {'train_loss':[], 'val_loss':[]}
all_acc = {'train_acc':[], 'val_acc':[]} # Loop through each epoch.
print('Epoch')
for epoch in tqdm(range(epochs)): print() print('Training on batches...') # Perform one full pass over the training set. train_labels, train_predict, train_loss = train(train_dataloader, optimizer, scheduler, device) train_acc = accuracy_score(train_labels, train_predict) # Get prediction form model on validation data. print('Validation on batches...') valid_labels, valid_predict, val_loss = validation(valid_dataloader, device) val_acc = accuracy_score(valid_labels, valid_predict) # Print loss and accuracy values to see how training evolves. print(" train_loss: %.5f - val_loss: %.5f - train_acc: %.5f - valid_acc: %.5f"%(train_loss, val_loss, train_acc, val_acc)) print() # Store the loss value for plotting the learning curve. all_loss['train_loss'].append(train_loss) all_loss['val_loss'].append(val_loss) all_acc['train_acc'].append(train_acc) all_acc['val_acc'].append(val_acc) # Plot loss curves.
plot_dict(all_loss, use_xlabel='Epochs', use_ylabel='Value', use_linestyles=['-', '--']) # Plot accuracy curves.
plot_dict(all_acc, use_xlabel='Epochs', use_ylabel='Value', use_linestyles=['-', '--'])
Epoch 100%|████████████████████████████████|4/4 [15:11<00:00, 227.96s/it] Training on batches... 100%|████████████████████████████████|782/782 [02:42<00:00, 4.82it/s] Validation on batches... 100%|████████████████████████████████|782/782 [02:07<00:00, 6.13it/s] train_loss: 0.54128 - val_loss: 0.38758 - train_acc: 0.75288 - valid_acc: 0.81904 Training on batches... 100%|████████████████████████████████|782/782 [02:36<00:00, 5.00it/s] Validation on batches... 100%|████████████████████████████████|782/782 [01:41<00:00, 7.68it/s] train_loss: 0.36716 - val_loss: 0.37620 - train_acc: 0.83288 -valid_acc: 0.82912 Training on batches... 100%|████████████████████████████████|782/782 [02:36<00:00, 5.00it/s] Validation on batches... 100%|████████████████████████████████|782/782 [01:24<00:00, 9.24it/s] train_loss: 0.31409 - val_loss: 0.39384 - train_acc: 0.86304 - valid_acc: 0.83044 Training on batches... 100%|████████████████████████████████|782/782 [02:36<00:00, 4.99it/s] Validation on batches... 100%|████████████████████████████████|782/782 [01:09<00:00, 11.29it/s] train_loss: 0.27358 - val_loss: 0.39798 - train_acc: 0.88432 - valid_acc: 0.83292
Потеря обучения и проверки.
Точность обучения и проверки.

Оценивать

Имея дело с классификацией, полезно посмотреть на точность отзыва и оценку F1.

Хорошим индикатором при оценке модели является матрица неточностей.

# Get prediction form model on validation data. This is where you should use
# your test data.
true_labels, predictions_labels, avg_epoch_loss = validation(valid_dataloader, device) # Create the evaluation report.
evaluation_report = classification_report(true_labels, predictions_labels, labels=list(labels_ids.values()), target_names=list(labels_ids.keys()))
# Show the evaluation report.
print(evaluation_report) # Plot confusion matrix.
plot_confusion_matrix(y_true=true_labels, y_pred=predictions_labels, classes=list(labels_ids.keys()), normalize=True, magnify=0.1, );
Training on batches... 100%|████████████████████████████████|782/782 [01:09<00:00, 11.24it/s] precision recall f1-score support neg 0.84 0.83 0.83 12500 pos 0.83 0.84 0.83 12500 accuracy 0.83 25000 macro avg 0.83 0.83 0.83 25000 weighted avg 0.83 0.83 0.83 25000
Матрица неточностей нормализована.

Заключительное примечание

Если вы зашли так далеко Поздравляю! 🎊 и Спасибо! 🙏 за ваш интерес к моему руководству!

Я использую этот код некоторое время, и я чувствую, что он дошел до того момента, когда он хорошо документирован и прост в использовании.

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

Если вы видите что-то не так, дайте мне знать, открыв вопрос на моем репозиторий ml_things на GitHub!

Многие обучающие программы в основном разовые и не поддерживаются. Я планирую постоянно обновлять свои учебные пособия.

Эта статья изначально была опубликована в Личный сайт Джорджа Михайлы  и повторно опубликовано в TOPBOTS с разрешения автора.

Понравилась эта статья? Подпишитесь на новые обновления AI.

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

Источник: https://www.topbots.com/gpt2-text-classification-using-hugging-face-transformers/

Отметка времени:

Больше от ТОП-БОТЫ