GPT2 för textklassificering med kramande ansiktstransformatorer

Källnod: 809063

textklassificering

Denna anteckningsbok används för att finjustera GPT2-modellen för textklassificering med Kramande ansikte transformatorer bibliotek på en anpassad dataset.

Att krama ansikte är mycket trevligt för oss att inkludera all den funktionalitet som behövs för att GPT2 ska användas i klassificeringsuppgifter. Tack Kramande ansikte!

Jag kunde inte hitta mycket information om hur man använder GPT2 för klassificering så jag bestämde mig för att göra denna handledning med liknande struktur med andra transformatormodeller.

Om detta fördjupade utbildningsinnehåll är användbart för dig, prenumerera på vår AI-forskningsmaillista att bli varnade när vi släpper nytt material. 

Huvudidé: Eftersom GPT2 är en avkodartransformator används den sista token i ingångssekvensen för att göra förutsägelser om nästa token som ska följa ingången. Detta innebär att den sista token i ingångssekvensen innehåller all information som behövs i förutsägelsen. Med detta i åtanke kan vi använda den informationen för att göra en förutsägelse i en klassificeringsuppgift istället för generationsuppgift.

Med andra ord, istället för att använda första tokeninbäddning för att göra förutsägelser som vi gör i Bert, kommer vi att använda den senaste inbäddningen av token för att göra förutsägelser med GPT2.

Eftersom vi bara brydde oss om den första token i Bert, paddade vi till höger. Nu i GPT2 använder vi den sista token för förutsägelse så vi kommer att behöva pad till vänster. På grund av en trevlig uppgradering till HuggingFace Transformers kan vi konfigurera GPT2 Tokenizer för att göra just det.

Vad ska jag veta för den här anteckningsboken?

Eftersom jag använder PyTorch för att finjustera våra transformatormodeller är all kunskap om PyTorch mycket användbar.

Att veta lite om transformatorer biblioteket hjälper också.

Hur använder jag den här anteckningsboken?

Som med alla projekt byggde jag den här anteckningsboken med tanke på återanvändbarhet.

Alla ändringar kommer att ske i databehandlingsdelen där du behöver anpassa PyTorch Dataset, Data Collator och DataLoader för att passa dina egna databehov.

Alla parametrar som kan ändras finns under Import sektion. Varje parameter är snyggt kommenterad och strukturerad för att vara så intuitiv som möjligt.

dataset

Den här anteckningsboken täcker förtränade transformatorer i en anpassad dataset. Jag kommer att använda de välkända filmrecensionerna positiva - negativa märkta Stor filmgranskningsdataset.

Beskrivningen på Stanfords webbplats:

Detta är en dataset för binär sentimentklassificering som innehåller betydligt mer data än tidigare referensdatauppsättningar. Vi tillhandahåller en uppsättning av 25,000 25,000 mycket polära filmrecensioner för träning och XNUMX XNUMX för testning. Det finns ytterligare omärkta data för användning också. Råtext och redan bearbetad påse med ordformat tillhandahålls. Se README-filen i utgåvan för mer information.

Varför denna dataset? Jag tror är en lättförståelig och använd datamängd för klassificering. Jag tycker att sentimentdata alltid är roliga att arbeta med.

Kodning

Låt oss nu göra lite kodning! Vi kommer att gå igenom varje kodningscell i anteckningsboken och beskriva vad den gör, vad koden är och när är relevant - visa utdata.

Jag gjorde det här formatet enkelt att följa om du bestämde dig för att köra varje kodcell i din egen python-anteckningsbok.

När jag lär mig av en handledning försöker jag alltid replikera resultaten. Jag tror att det är lätt att följa med om du har koden bredvid förklaringarna.

Nedladdningar

ladda ner Stor filmgranskningsdataset och packa upp den lokalt.

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

installerar

  • transformatorer biblioteket måste installeras för att kunna använda all den fantastiska koden från Hugging Face. För att få den senaste versionen installerar jag den direkt från GitHub.
  • ml_saker bibliotek som används för olika maskininlärningsrelaterade uppgifter. Jag skapade det här biblioteket för att minska mängden kod jag behöver skriva för varje maskininlärningsprojekt.
# 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

Import

Importera alla bibliotek som behövs för den här anteckningsboken. Förklara parametrar som används för den här anteckningsboken:

  • set_seed(123) - Alltid bra att ställa in ett fast utsäde för reproducerbarhet.
  • epochs - Antal träningsepoker (författare rekommenderar mellan 2 och 4).
  • batch_size - Antal satser - beroende på max sekvenslängd och GPU-minne. För 512 sekvenslängd fungerar en sats på 10 USUALY utan problem med cuda-minne. För liten sekvenslängd kan du testa batch på 32 eller högre. max_length - Pad eller avkorta textsekvenser till en viss längd. Jag ställer in den på 60 för att påskynda träningen.
  • device - Leta efter gpu att använda. Kommer att använda cpu som standard om ingen gpu hittades.
  • model_name_or_path - Namn på transformatormodell - använder redan förutbildad modell. Path of transformator model - laddar din egen modell från lokal disk. I denna handledning ska jag använda gpt2 modell.
  • labels_ids - Ordbok över etiketter och deras id - detta kommer att användas för att konvertera strängetiketter till nummer.
  • n_labels - Hur många etiketter använder vi i denna dataset. Detta används för att bestämma storleken på klassificeringshuvudet.
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)

Hjälparfunktioner

Jag vill behålla alla klasser och funktioner som kommer att användas i den här anteckningsboken under detta avsnitt för att bibehålla ett rent utseende på anteckningsboken:

MovieReviewsDataset (Dataset)

Om du arbetat med PyTorch tidigare är detta ganska standard. Vi behöver den här klassen för att läsa i vår dataset, analysera den och returnera texter med tillhörande etiketter.

I den här klassen behöver jag bara läsa in innehållet i varje fil, använda fix_text för att åtgärda Unicode-problem och hålla koll på positiva och negativa känslor.

Jag lägger till alla texter och etiketter i listor.

Det finns tre huvuddelar i denna PyTorch-datasatsklass:

  • i det() där vi läser i datasetet och omvandlar text och etiketter till siffror.
  • len () där vi behöver returnera antalet exempel vi läser i. Detta används när vi ringer till len (MovieReviewsDataset ()).
  • getitem () tar alltid som ingång ett int-värde som representerar vilket exempel från våra exempel som ska returneras från vår dataset. Om värdet 3 passeras returnerar vi exemplet från vår dataset på position 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]}

Gpt2ClassificationCollator

Jag använder den här klassen för att skapa Data Collator. Detta kommer att användas i DataLoader för att skapa bad av data som matas till modellen. Jag använder tokenizer och etikettkodare i varje sekvens för att konvertera texter och etiketter till nummer.

Tur för oss, Hugging Face tänkte på allt och fick tokenisern att göra alla tunga lyft (delad text i tokens, stoppning, avkortning, kodning av text i siffror) och är väldigt lätt att använda!

Det finns två huvuddelar i denna Data Collator-klass:

  • i det() där vi initialiserar tokenisern vi planerar att använda, hur vi kodar våra etiketter och om vi behöver ställa in sekvenslängden till ett annat värde.
  • ring upp() används som funktionssammanställare som tar som inmatning ett antal dataexempel. Det måste returnera ett objekt med det format som kan matas till vår modell. Lyckligtvis gör vår tokenizer det för oss och returnerar en ordbok med variabler redo att matas till modellen på detta sätt: model(**inputs). Eftersom vi finjusterar modellen inkluderade jag också etiketterna.
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

tåg (datalader, optimizer_, scheduler_, device_)

Jag skapade den här funktionen för att utföra en fullständig genomgång av DataLoader-objektet (DataLoader-objektet skapas från vårt Dataset * -typobjekt med hjälp av klassen ** MovieReviewsDataset). Detta är i grunden ett epoktåg genom hela datasetet.

Dataladdaren skapas från PyTorch DataLoader som tar objektet som skapats från klassen MovieReviewsDataset och sätter varje exempel i satser. På så sätt kan vi mata våra modellbatcher med data!

Optimizer_ och scheduler_ är mycket vanliga i PyTorch. De måste uppdatera parametrarna i vår modell och uppdatera vår inlärningshastighet under träningen. Det finns mycket mer än så men jag kommer inte att gå in på detaljer. Detta kan faktiskt vara ett stort kaninhål eftersom MYCKET händer bakom dessa funktioner som vi inte behöver oroa oss för. Tack PyTorch!

I processen håller vi reda på de faktiska etiketterna och de förutsedda etiketterna tillsammans med förlusten.

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

validering (datalader, enhet_)

Jag implementerade den här funktionen på ett mycket liknande sätt som tåg men utan uppdatering av parametrar, bakåtpass och gradient anständig del. Vi behöver inte göra alla dessa MYCKET beräkningsintensiva uppgifter eftersom vi bara bryr oss om vår modells förutsägelser.

Jag använder DataLoader på ett liknande sätt som i tåg för att få ut satser för att mata till vår modell.

I processen håller jag reda på de faktiska etiketterna och de förutsagda etiketterna tillsammans med förlusten.

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

Ladda modell och Tokenizer

Laddar de tre väsentliga delarna av den förtränade GPT2-transformatorn: konfiguration, tokenizer och modell.

För detta exempel kommer jag att använda gpt2 från HuggingFace förtränade transformatorer. Du kan använda vilken variant av GP2 du vill.

När du skapar model_config Jag kommer att nämna antalet etiketter jag behöver för min klassificeringsuppgift. Eftersom jag bara förutsäger två känslor: positiva och negativa behöver jag bara två etiketter för num_labels.

Skapa tokenizer är ganska standard när du använder Transformers-biblioteket. Efter att du har skapat tokenizer är det viktigt för denna handledning att ställa in padding till vänster tokenizer.padding_side = "left" och initialisera stoppningstoken till tokenizer.eos_token vilket är GPT2: s ursprungliga slutet av sekvenstoken. Detta är den viktigaste delen av denna handledning eftersom GPT2 använder den sista token för förutsägelse, så vi måste lägga till vänster.

HuggingFace gjorde redan det mesta av arbetet för oss och lade till ett klassificeringsskikt till GPT2-modellen. När jag skapade den modell jag använde GPT2ForSequenceClassification. Eftersom vi har en anpassad vadderingstoken måste vi initialisera den för modellen med model.config.pad_token_id. Slutligen måste vi flytta modellen till den enhet som vi definierade tidigare.

# 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`

Dataset och Collator

Det är här jag skapar PyTorch Dataset och Data Loader med Data Collator-objekt som kommer att användas för att mata in data i vår modell.

Det är här jag använder MovieReviewsDataset klass för att skapa PyTorch-datauppsättningen som returnerar texter och etiketter.

Eftersom vi behöver mata in siffror till vår modell måste vi konvertera texterna och etiketterna till siffror. Detta är syftet med en kollator! Det krävs data som matas ut av PyTorch-datauppsättningen och skickas genom Data Collator-funktionen för att mata ut sekvensen för vår modell.

Jag håller tokenizer borta från PyTorch-datauppsättningen för att göra koden renare och bättre strukturerad. Du kan självklart använda tokenizern inuti PyTorch-datauppsättningen och mata ut sekvenser som kan användas direkt i modellen utan att använda en Data Collator.

Jag rekommenderar starkt att du använder en valideringstextfil för att avgöra hur mycket utbildning som behövs för att undvika övermontering. När du har räknat ut vilka parametrar som ger bäst resultat kan valideringsfilen införlivas i tåget och köra ett sista tåg med hela datasetet.

Datasamlaren används för att formatera PyTorch-datauppsättningsutgångarna så att de matchar de ingångar som behövs för 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!

Tåg

Jag skapade optimerings- och schemaläggningsanvändning av PyTorch under träning. Jag använde de vanligaste parametrarna som användes av transformatormodeller.

Jag slog igenom antalet definierade epoker och kallade tåg och godkännande funktioner.

Jag försöker mata ut liknande info efter varje epok som Keras: train_loss: - val_loss: - train_acc: - valid_acc.

Efter träning, kurva tåg och validerings- och noggrannhetskurvor för att kontrollera hur träningen gick.

Notera: Träningsplanerna kan se lite konstiga ut: Valideringsnoggrannheten börjar högre än träningsnoggrannheten och valideringsförlusten börjar lägre än träningsförlusten. Normalt blir detta motsatsen. Jag antar att datadelningen bara är lättare för valideringsdelen eller för svår för träningsdel eller båda. Eftersom den här guiden handlar om att använda GPT2 för klassificering kommer jag inte att oroa mig för resultatet av modellen för mycket.

# 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
Förlust av tåg och validering.
Tränings- och valideringsnoggrannhet.

Utvärdera

När det gäller klassificering är det användbart att titta på precision återkallande och F1 poäng.

En bra mätare att ha när man utvärderar en modell är förvirringsmatrisen.

# 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
Förvirringsmatris normaliserad.

slutlig Obs

Om du lyckades så långt Grattis! 🎊 och Tack! 🙏 för ditt intresse för min handledning!

Jag har använt den här koden ett tag nu och jag känner att den har kommit till en punkt där den är snyggt dokumenterad och lätt att följa.

Naturligtvis är det lätt för mig att följa eftersom jag byggde den. Det är därför som alla feedback är välkomna och det hjälper mig att förbättra mina framtida tutorials!

Om du ser något fel, vänligen meddela mig genom att öppna ett problem på min ml_things GitHub-förvar!

Många handledning där ute är mestadels en engångs sak och underhålls inte. Jag planerar att hålla mina handledningar uppdaterade så mycket jag kan.

Den här artikeln publicerades ursprungligen den George Mihailas personliga webbplats  och publiceras på nytt till TOPBOTS med tillstånd från författaren.

Tycker du om den här artikeln? Registrera dig för fler AI-uppdateringar.

Vi meddelar dig när vi släpper mer teknisk utbildning.

Källa: https://www.topbots.com/gpt2-text-classification-using-hugging-face-transformers/

Tidsstämpel:

Mer från TOPPBOTS