Finjuster Transformers i PyTorch ved hjælp af Hugging Face Transformers

Kildeknude: 747727

finjustere transformatorer

Denne notesbog er designet til at bruge en fortrænet transformatormodel og finjustere den på en klassificeringsopgave. Fokus i denne tutorial vil være på selve koden, og hvordan du tilpasser den til dine behov.

Denne notesbog bruger Autoklasser fra transformer by Knusende ansigt funktionalitet. Denne funktionalitet kan gætte en models konfiguration, tokenizer og arkitektur blot ved at indtaste modellens navn. Dette giver mulighed for genbrug af kode på et stort antal transformatormodeller!

Hvis dette dybdegående undervisningsindhold er nyttigt for dig, kan du abonner på vores AI-forskningsmailingliste for at blive advaret, når vi udgiver nyt materiale. 

Hvad skal jeg vide om denne notesbog?

Jeg gav nok instruktioner og kommentarer til at kunne følge med med minimum Python-kodningsviden.

Da jeg bruger PyTorch til at finjustere vores transformatormodeller, er enhver viden om PyTorch meget nyttig. Ved lidt om transformers biblioteket hjælper også.

Hvordan bruger man denne notesbog?

Jeg byggede denne notesbog med genbrug i tankerne. Den måde, jeg indlæser datasættet på i PyTorch datasæt klasse er ret standard og kan nemt genbruges til ethvert andet datasæt.

De eneste ændringer, der er nødvendige for at bruge dit eget datasæt, vil være i læsning i datasættet inde i Filmanmeldelser Datasæt klasse, der bruger PyTorch datasæt. Det DataLoader vil returnere en ordbog over parti inputformat, så det kan føres direkte til modellen ved hjælp af sætningen: outputs = model(**batch)Så længe denne erklæring holder, vil resten af ​​koden virke!

Hvilke transformatormodeller fungerer med denne notesbog?

Der er sjældne tilfælde, hvor jeg bruger en anden model end Bert, når jeg beskæftiger mig med klassificering fra tekstdata. Når der er behov for at køre en anden transformermodelarkitektur, hvilken ville så arbejde med denne kode?

Da navnet på notesbøgerne er finetune_transformers den skal fungere med mere end én type transformere.

Jeg kørte denne notesbog over alle de fortrænede modeller fundet på Hugging Face Transformer. På denne måde ved du på forhånd, om den model, du planlægger at bruge, fungerer med denne kode uden ændringer.

Listen over fortrænede transformatormodeller, der fungerer med denne notesbog, kan findes link.. Der er 73 modeller, der virkede? 33 modeller, der ikke virkede? med denne notesbog.

datasæt

Denne notesbog vil dække finjustering af transformatorer til binær klassificeringsopgave. Jeg vil bruge de velkendte filmanmeldelser positive — negative mærket Stort filmanmeldelsesdatasæt.

Beskrivelsen på Stanfords hjemmeside:

Dette er et datasæt til binær sentimentklassificering, der indeholder væsentligt flere data end tidligere benchmarkdatasæt. Vi leverer et sæt på 25,000 meget polære filmanmeldelser til træning og 25,000 til test. Der er også yderligere umærkede data til brug. Rå tekst og allerede behandlede pose med ord-formater leveres. Se README-filen i udgivelsen for flere detaljer.

Hvorfor dette datasæt? Jeg tror, ​​det er et let at forstå og bruge datasæt til klassificering. Jeg synes, at sentimentdata altid er sjovt at arbejde med.

Kodning

Lad os nu lave noget kodning! Vi vil gennemgå hver kodningscelle i notesbogen og beskrive, hvad den gør, hvad koden er, og hvornår det er relevant - vis outputtet.

Jeg har lavet dette format, så det er nemt at følge, hvis du beslutter dig for at køre hver kodecelle i din egen python-notesbog.

Når jeg lærer fra en tutorial, prøver jeg altid at kopiere resultaterne. Jeg tror, ​​det er nemt at følge med, hvis du har koden ved siden af ​​forklaringerne.

Downloads

Download Stort filmanmeldelsesdatasæt og pak den ud 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

installationer

  • transformers biblioteket skal installeres for at bruge al den fantastiske kode fra Hugging Face. For at få den seneste version installerer jeg den direkte fra GitHub.
  • ml_ting bibliotek, der bruges til forskellige maskinlæringsrelaterede opgaver. Jeg oprettede dette bibliotek for at reducere mængden af ​​kode, jeg skal skrive til hvert maskinlæringsprojekt. Giv det en chance!
# 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 wheel for 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

Importer alle nødvendige biblioteker til denne notesbog.

Angiv parametre, der bruges til denne notesbog:

  • set_seed(123) – Altid godt at sætte et fast frø for reproducerbarhed.
  • epochs – Antal træningsepoker (forfattere anbefaler mellem 2 og 4).
  • batch_size – Antal batches – afhængig af den maksimale sekvenslængde og GPU-hukommelse. For 512 sekvenslængde en batch på 10 SOM SÆDLIGT virker uden problemer med cuda hukommelse. For lille sekvenslængde kan prøve batch på 32 eller højere.
  • max_length – Indtast eller afkort tekstsekvenser til en bestemt længde. Jeg vil sætte den til 60 tokens for at fremskynde træningen.
  • device – Se efter gpu at bruge. jeg vil bruge cpu som standard hvis nej gpu fundet.
  • model_name_or_path – Navn på transformatormodel – vil bruge allerede fortrænet model. Sti til transformermodel – indlæser din egen model fra lokal disk. Jeg kan altid godt lide at starte med bert-base-cased12-lags, 768-skjult, 12-hoveder, 109M parametre. Trænet på engelsk tekst med kasketter.
  • labels_ids – Ordbog over etiketter og deres id – dette vil blive brugt til at konvertere strengetiketter til tal.
  • n_labels – Hvor mange etiketter bruger vi i dette datasæt. Dette bruges til at bestemme størrelsen på klassifikationshovedet.
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 (AutoConfig, AutoModelForSequenceClassification, AutoTokenizer, AdamW, get_linear_schedule_with_warmup, set_seed, ) # Set seed for reproducibility,
set_seed(123) # Number of training epochs (authors 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.
batches = 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 = 'bert-base-cased' # Dicitonary 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ælpefunktioner

Jeg kan godt lide at beholde alle klasser og funktioner, som jeg vil bruge i denne notesbog under dette afsnit for at hjælpe med at bevare et rent udseende af notesbogen:

Filmanmeldelser Datasæt

Hvis du har arbejdet med PyTorch før, er dette ret standard. Vi har brug for denne klasse til at læse i vores datasæt, analysere den, bruge tokenizer, der omdanner tekst til tal og få den til et pænt format, der skal føres til modellen.

Heldig til brug, Knusende ansigt tænkte på alt og lavede Tokenizer gør alt det tunge løft (opdel tekst i tokens, polstring, trunkering, indkod tekst i tal) og er meget nem at bruge!

I denne klasse skal jeg kun læse indholdet af hver fil, brug fix_tekst at løse eventuelle Unicode-problemer og holde styr på positive og negative følelser.

Jeg vil tilføje alle tekster og etiketter i lister, som jeg senere vil føre til tokenizeren og til etiket-id'erne for at omdanne alt til tal.

Der er tre hoveddele af denne PyTorch datasæt klasse:

  • i det() hvor vi læser i datasættet og omdanner tekst og etiketter til tal.
  • __len__() hvor vi skal returnere antallet af eksempler vi læser i. Dette bruges når man ringer len(MovieReviewsDataset()) .
  • __getitem__() tager altid som input en int valuet hat repræsenterer hvilket eksempel fra vores eksempler, der skal returneres fra vores datasæt. Hvis en værdi på 3 passeres, returnerer vi eksemplet fra vores datasæt på position 3. Det skal returnere et objekt med det format, der kan føres til vores model. Heldigvis gør vores tokenizer det for os og returnerer en ordbog over variabler, der er klar til at blive ført til modellen på denne måde:model(**inputs).
class MovieReviewsDataset(Dataset): r"""PyTorch Dataset class for loading data. This is where the data parsing happens and where the text gets encoded using loaded tokenizer. 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: path (:obj:`str`): Path to the data partition. 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, path, use_tokenizer, labels_ids, max_sequence_len=None): # 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') # Check max sequence length. max_sequence_len = use_tokenizer.max_len if max_sequence_len is None else max_sequence_len texts = [] labels = [] print('Reading partitions...') # Since the labels are defined by folders with data we loop # through each label. for label, label_id, in tqdm(labels_ids.items()): sentiment_path = os.path.join(path, label) # Get all files from path. files_names = os.listdir(sentiment_path)#[:10] # Sample for debugging. print('Reading %s files...' % label) # Go through each file and read its content. for file_name in tqdm(files_names): 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. texts.append(content) # Save encode labels. labels.append(label_id) # Number of exmaples. self.n_examples = len(labels) # Use tokenizer on texts. This can take a while. print('Using tokenizer on all texts. This can take a while...') self.inputs = use_tokenizer(texts, add_special_tokens=True, truncation=True, padding=True, return_tensors='pt', max_length=max_sequence_len) # Get maximum sequence length. self.sequence_len = self.inputs['input_ids'].shape[-1] print('Texts padded or truncated to %d length!' % self.sequence_len) # Add labels. self.inputs.update({'labels':torch.tensor(labels)}) print('Finished!n') 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, object]`: Dictionary of inputs that feed into the model. It holddes the statement `model(**Returned Dictionary)`. """ return {key: self.inputs[key][item] for key in self.inputs.keys()}

train(dataloader, optimizer_, scheduler_, device_)

Jeg oprettede denne funktion for at udføre en fuld gennemgang DataLoader objekt (den DataLoader objekt er skabt ud fra vores datasæt skriv objekt ved hjælp af Filmanmeldelser Datasæt klasse). Dette er grundlæggende et epoketog gennem hele datasættet.

 dataindlæser er oprettet fra PyTorch DataLoader som tager objektet skabt af Filmanmeldelser Datasæt klasse og sætter hvert eksempel i batches. På denne måde kan vi fodre vores modelbatches af data!

 optimizer_ , planlægger_ er meget almindelige i PyTorch. De er forpligtet til at opdatere parametrene for vores model og opdatere vores indlæringshastighed under træning. Der er meget mere end det, men jeg vil ikke gå i detaljer. Dette kan faktisk være et stort kaninhul, da der sker MEGET bag disse funktioner, som vi ikke behøver at bekymre os om. Tak PyTorch!

I processen holder vi styr på de faktiske etiketter og de forudsagte etiketter sammen med tabet.

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 (dataloader, enhed_)

Jeg implementerede denne funktion på en meget lignende måde som tog men uden parametrene opdatering, baglæns pass og gradient anstændig del. Vi behøver ikke at udføre alle de MEGET beregningsintensive opgaver, fordi vi kun bekymrer os om vores models forudsigelser.

Jeg bruger DataLoader på samme måde som i tog for at få partier ud for at fodre til vores model.

I processen holder jeg styr på de faktiske etiketter og de forudsagte etiketter sammen med tabet.

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

Indlæs model og tokenizer

Indlæsning af de tre væsentlige dele af de fortrænede transformere: konfigurationTokenizer , model. Jeg skal også indlæse modellen på den enhed, jeg planlægger at bruge (GPU / CPU).

Siden jeg bruger AutoClass funktionalitet fra Knusende ansigt Jeg behøver kun at bekymre mig om modellens navn som input, og resten håndteres af transformatorbiblioteket.

# Get model configuration.
print('Loading configuraiton...')
model_config = AutoConfig.from_pretrained(pretrained_model_name_or_path=model_name_or_path, num_labels=n_labels) # Get model's tokenizer.
print('Loading tokenizer...')
tokenizer = AutoTokenizer.from_pretrained(pretrained_model_name_or_path=model_name_or_path) # Get the actual model.
print('Loading model...')
model = AutoModelForSequenceClassification.from_pretrained(pretrained_model_name_or_path=model_name_or_path, config=model_config) # Load model to defined device.
model.to(device)
print('Model loaded to `%s`'%device)
Loading configuraiton...
Loading tokenizer...
Loading model...
Some weights of the model checkpoint at bert-base-cased were not used when initializing BertForSequenceClassification: ['cls.predictions.bias', 'cls.predictions.transform.dense.weight', 'cls.predictions.transform.dense.bias', 'cls.predictions.decoder.weight', 'cls.seq_relationship.weight', 'cls.seq_relationship.bias', 'cls.predictions.transform.LayerNorm.weight', 'cls.predictions.transform.LayerNorm.bias']
- This IS expected if you are initializing BertForSequenceClassification from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPretraining model).
- This IS NOT expected if you are initializing BertForSequenceClassification from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model).
Some weights of BertForSequenceClassification were not initialized from the model checkpoint at bert-base-cased and are newly initialized: ['classifier.weight', 'classifier.bias']
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`

Datasæt og DataLoader

Det er her, jeg laver PyTorch datasæt , DataLoader objekter, der vil blive brugt til at føre data ind i vores model.

Det er her jeg bruger Filmanmeldelser Datasæt klasse og opret datasætvariablerne. Da data er partitioneret til både tog og test, vil jeg oprette en PyTorch datasæt og PyTorch DataLoader objekt til tog og test. KUN for nemheds skyld vil jeg bruge testen som validering. I praksis BRUG ALDRIG TESTDATA TIL VALIDERING!

print('Dealing with Train...')
# Create pytorch dataset.
train_dataset = MovieReviewsDataset(path='/content/aclImdb/train', use_tokenizer=tokenizer, labels_ids=labels_ids, max_sequence_len=max_length)
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)
print('Created `train_dataloader` with %d batches!'%len(train_dataloader)) print() print('Dealing with ...')
# Create pytorch dataset.
valid_dataset = MovieReviewsDataset(path='/content/aclImdb/test', use_tokenizer=tokenizer, labels_ids=labels_ids, max_sequence_len=max_length)
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)
print('Created `eval_dataloader` with %d batches!'%len(valid_dataloader))
Dealing with Train...
Reading partitions...
100%|████████████████████████████████|2/2 [00:34<00:00, 17.28s/it]
Reading neg files...
100%|████████████████████████████████|12500/12500 [00:34<00:00, 362.01it/s] Reading pos files...
100%|████████████████████████████████|12500/12500 [00:23<00:00, 534.34it/s] Using tokenizer on all texts. This can take a while...
Texts padded or truncated to 40 length!
Finished! Created `train_dataset` with 25000 examples!
Created `train_dataloader` with 25000 batches! Dealing with ...
Reading partitions...
100%|████████████████████████████████|2/2 [01:28<00:00, 44.13s/it]
Reading neg files...
100%|████████████████████████████████|12500/12500 [01:28<00:00, 141.71it/s] Reading pos files...
100%|████████████████████████████████|12500/12500 [01:17<00:00, 161.60it/s] Using tokenizer on all texts. This can take a while...
Texts padded or truncated to 40 length!
Finished! Created `valid_dataset` with 25000 examples!
Created `eval_dataloader` with 25000 batches!

Tog

Jeg opretter en optimizer og skemalægger, der vil blive brugt af PyTorch i træningen.

Jeg går gennem antallet af definerede epoker og kalder tog , validering funktioner.

Jeg udsender lignende information efter hver epoke som i Keras: train_tab: — val_loss: — train_acc: — valid_acc.

Efter træning plotter jeg kurverne for tog- og valideringstab og nøjagtighed for at tjekke, hvordan træningen gik.

# 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, # args.learning_rate - default is 5e-5, our notebook had 2e-5 eps = 1e-8 # args.adam_epsilon - 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[13:49<00:00, 207.37s/it] Training on batches... 100%|████████████████████████████████|782/782[02:40<00:00,4.86it/s] Validation on batches... 100%|████████████████████████████████|782/782[00:46<00:00,16.80it/s] train_loss: 0.44816 - val_loss: 0.38655 - train_acc: 0.78372 - valid_acc: 0.81892 Training on batches... 100%|████████████████████████████████|782/782[02:40<00:00,4.86it/s] Validation on batches... 100%|████████████████████████████████|782/782 [02:13<00:00,5.88it/s] train_loss: 0.29504 - val_loss: 0.43493 - train_acc: 0.87352 -valid_acc: 0.82360 Training on batches... 100%|████████████████████████████████|782/782[02:40<00:00, 4.87it/s] Validation on batches... 100%|████████████████████████████████|782/782[01:43<00:00,7.58it/s] train_loss: 0.16901 - val_loss: 0.48433 - train_acc: 0.93544 -valid_acc: 0.82624 Training on batches... 100%|████████████████████████████████|782/782[02:40<00:00, 4.87it/s] Validation on batches... 100%|████████████████████████████████|782/782[00:46<00:00,16.79it/s]
train_loss: 0.09816 - val_loss: 0.73001 - train_acc: 0.96936 - valid_acc: 0.82144

Det ser ud til, at lidt over én epoke er nok træning til denne model og datasæt.

Evaluer

Når man beskæftiger sig med klassificering er det nyttigt at se på præcision, tilbagekaldelse , f1 score. En anden god ting at se på, når modellen evalueres, er forvirringsmatricen.

# 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=3, );
Outputs: 100%|████████████████████████████████|782/782[00:46<00:00,16.77it/s]
precision recall f1-score support neg 0.83 0.81 0.82 12500 pos 0.81 0.83 0.82 12500 accuracy 0.82 25000 macro avg 0.82 0.82 0.82 25000 weighted avg 0.82 0.82 0.82 25000 

Resultaterne er ikke gode, men for denne tutorial er vi ikke interesserede i ydeevne.

Afsluttende Note

Hvis du nåede så langt Tillykke! ? , Tak skal du have! ? for din interesse for min tutorial!

Jeg har brugt denne kode i et stykke tid nu, og jeg føler, at den er nået til et punkt, hvor den er pænt dokumenteret og nem at følge.

Det er selvfølgelig nemt for mig at følge, fordi jeg byggede det. Derfor er enhver feedback velkommen, og den hjælper mig med at forbedre mine fremtidige tutorials!

Hvis du ser noget galt, så lad mig det vide ved at åbne en problem på mine ml_ting GitHub-depot!

Mange tutorials derude er for det meste en engangs ting og bliver ikke vedligeholdt. Jeg planlægger at holde mine tutorials ajour så meget som muligt.

Denne artikel blev oprindeligt offentliggjort den George Mihailas personlige hjemmeside og genudgivet til TOPBOTS med tilladelse fra forfatteren.

Nyder du denne artikel? Tilmeld dig flere AI-forskningsopdateringer.

Vi giver dig besked, når vi frigiver mere teknisk uddannelse.

Kilde: https://www.topbots.com/fine-tune-transformers-in-pytorch/

Tidsstempel:

Mere fra TOPBOTS