GPT2 for tekstklassifisering ved bruk av klemmende ansikts-transformatorer

Kilde node: 809063

tekst klassifisering

Denne notatboken brukes til å finjustere GPT2-modellen for tekstklassifisering ved hjelp av Klemme ansiktet transformers bibliotek på et tilpasset datasett.

Hugging Face er veldig hyggelig for oss å inkludere all funksjonaliteten som trengs for at GPT2 skal brukes i klassifiseringsoppgaver. Takk Klem Ansikt!

Jeg var ikke i stand til å finne mye informasjon om hvordan du bruker GPT2 til klassifisering, så jeg bestemte meg for å lage denne opplæringen ved å bruke lignende struktur med andre transformatormodeller.

Hvis dette inngående pedagogiske innholdet er nyttig for deg, abonner på vår adresseliste for AI-forskning å bli varslet når vi slipper nytt materiale. 

Hovedide: Siden GPT2 er en dekoder-transformator, brukes det siste token i inngangssekvensen for å komme med spådommer om neste token som skal følge inngangen. Dette betyr at det siste token i inngangssekvensen inneholder all informasjonen som er nødvendig i spådommen. Med dette i bakhodet kan vi bruke denne informasjonen til å lage en prediksjon i en klassifiseringsoppgave i stedet for generasjonsoppgave.

Med andre ord, i stedet for å bruke første token-innebygging for å lage spådommer som vi gjør i Bert, vil vi bruke den siste token-innebyggingen for å spå med GPT2.

Siden vi bare brydde oss om det første token i Bert, polstret vi til høyre. Nå i GPT2 bruker vi det siste symbolet for prediksjon, så vi må putte til venstre. På grunn av en fin oppgradering til HuggingFace Transformers, kan vi konfigurere GPT2 Tokenizer til å gjøre nettopp det.

Hva skal jeg vite om denne notatboken?

Siden jeg bruker PyTorch for å finjustere transformatormodellene våre, er all kunnskap om PyTorch veldig nyttig.

Å vite litt om transformers biblioteket hjelper også.

Hvordan bruker jeg denne notatboken?

Som med alle prosjekter, bygde jeg denne notisboken med tanke på gjenbrukbarhet.

Alle endringer vil skje i databehandlingsdelen der du trenger å tilpasse PyTorch Dataset, Data Collator og DataLoader for å passe dine egne databehov.

Alle parametere som kan endres er under Importen seksjon. Hver parameter er pent kommentert og strukturert for å være så intuitiv som mulig.

datasett

Denne notisboken vil dekke transformatorer på forhånd som trener på et tilpasset datasett. Jeg vil bruke de kjente filmomtalene positive - negative merket Stor datasett for filmanmeldelse.

Beskrivelsen gitt på Stanfords nettsted:

Dette er et datasett for binær sentimentklassifisering som inneholder vesentlig mer data enn tidligere datasett. Vi tilbyr et sett med 25,000 25,000 høypolare filmanmeldelser for opplæring, og XNUMX XNUMX for testing. Det er ytterligere umerkede data for bruk også. Råtekst og allerede behandlet pose med ordformater er gitt. Se README-filen i utgivelsen for mer informasjon.

Hvorfor dette datasettet? Jeg tror er et enkelt å forstå og bruke datasett for klassifisering. Jeg synes sentimentdata er alltid morsomt å jobbe med.

Koding

La oss nå gjøre litt koding! Vi vil gå gjennom hver kodingscelle i notatboken og beskrive hva den gjør, hva koden er og når er relevant - vis utdataene.

Jeg gjorde dette formatet for å være enkelt å følge hvis du bestemmer deg for å kjøre hver kodecelle i din egen python-notatbok.

Når jeg lærer av en opplæring prøver jeg alltid å replikere resultatene. Jeg tror det er lett å følge med hvis du har koden ved siden av forklaringene.

Nedlastinger

Last ned Stor datasett for filmanmeldelse og pakke den ut 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

installasjoner

  • transformers biblioteket må installeres for å bruke all den fantastiske koden fra Hugging Face. For å få den nyeste versjonen vil jeg installere den rett fra GitHub.
  • ml_ting bibliotek brukt til ulike maskinlæringsrelaterte oppgaver. Jeg opprettet dette biblioteket for å redusere mengden kode jeg trenger å skrive for hvert maskinlæringsprosjekt.
# 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

Importen

Importer alle nødvendige biblioteker for denne bærbare PC-en.

  • set_seed(123) - Alltid godt å sette et fast frø for reproduserbarhet.
  • epochs - Antall treningsperioder (forfattere anbefaler mellom 2 og 4).
  • batch_size - Antall batcher - avhengig av maks sekvenslengde og GPU-minne. For 512 sekvenslengder fungerer en gruppe på 10 USUALY uten problemer med cuda-minne. For liten sekvenslengde kan du prøve batch på 32 eller høyere. max_length - Pad eller avkort tekstsekvenser til en bestemt lengde. Jeg vil sette den til 60 for å få raskere trening.
  • device - Se etter GPU å bruke. Bruker cpu som standard hvis ingen gpu er funnet.
  • model_name_or_path - Navn på transformatormodell - vil bruke allerede forhåndsøvd modell. Path of transformer model - vil laste din egen modell fra lokal disk. I denne opplæringen vil jeg bruke gpt2 modell.
  • labels_ids - Ordbok over etiketter og deres id - dette vil bli brukt til å konvertere strengetiketter til tall.
  • n_labels - Hvor mange etiketter bruker vi i dette datasettet. Dette brukes til å bestemme størrelsen på klassifiseringshodet.
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)

Hjelperfunksjoner

Jeg liker å beholde alle klasser og funksjoner som skal brukes i denne bærbare PC-en under denne delen for å opprettholde et rent utseende på den bærbare datamaskinen:

MovieReviewsDataset (datasett)

Hvis du jobbet med PyTorch før, er dette ganske standard. Vi trenger denne klassen for å lese i datasettet vårt, analysere det og returnere tekster med tilhørende etiketter.

I denne klassen trenger jeg bare å lese innholdet i hver fil, bruke fix_text for å fikse eventuelle Unicode-problemer og holde oversikt over positive og negative følelser.

Jeg vil legge til alle tekster og etiketter i lister.

Det er tre hoveddeler av denne PyTorch-datasettklassen:

  • i det() der vi leser i datasettet og transformerer tekst og etiketter til tall.
  • len () der vi trenger å returnere antall eksempler vi leser i. Dette brukes når vi ringer til len (MovieReviewsDataset ()).
  • getitem () tar alltid som en inngang en int-verdi som representerer hvilket eksempel fra eksemplene våre som skal returneres fra datasettet vårt. Hvis verdien 3 blir bestått, returnerer vi eksemplet fra datasettet vårt på posisjon 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

Jeg bruker denne klassen til å lage Data Collator. Dette vil bli brukt i DataLoader for å lage bad av data som blir matet til modellen. Jeg bruker tokenizer og etikettkoder på hver sekvens for å konvertere tekster og etiketter til nummer.

Heldig for oss, Hugging Face tenkte på alt og fikk tokeniseren til å gjøre alle tunge løft (delt tekst i tokens, polstring, avkorting, koding av tekst i tall) og er veldig enkel å bruke!

Det er to hoveddeler av denne Data Collator-klassen:

  • i det() hvor vi initialiserer tokenisatoren vi planlegger å bruke, hvordan vi koder etikettene våre, og om vi trenger å sette sekvenslengden til en annen verdi.
  • anrop() brukes som funksjonssamler som tar som input en mengde dataeksempler. Det må returnere et objekt med formatet som kan mates til modellen vår. Heldigvis gjør vår tokenizer det for oss og returnerer en ordliste med variabler som er klare til å bli matet til modellen på denne måten: model(**inputs). Siden vi finjusterer modellen, inkluderte jeg også etikettene.
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

tog (datalader, optimizer_, scheduler_, device_)

Jeg opprettet denne funksjonen for å utføre en full gjennomgang gjennom DataLoader-objektet (DataLoader-objektet er opprettet fra vårt datasett * -objekt ved hjelp av klassen ** MovieReviewsDataset). Dette er i utgangspunktet ett epoketog gjennom hele datasettet.

Datalader er opprettet fra PyTorch DataLoader som tar objektet opprettet fra klassen MovieReviewsDataset og setter hvert eksempel i grupper. På denne måten kan vi mate modellbatchene våre med data!

Optimizer_ og scheduler_ er veldig vanlig i PyTorch. Det kreves at de oppdaterer parametrene til modellen vår og oppdaterer læringsgraden vår under trening. Det er mye mer enn det, men jeg vil ikke gå i detaljer. Dette kan faktisk være et stort kaninhull siden MYE skjer bak disse funksjonene som vi ikke trenger å bekymre oss for. Takk PyTorch!

I prosessen holder vi rede på de faktiske etikettene og de forutsagte etikettene sammen med tapet.

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, device_)

Jeg implementerte denne funksjonen på en veldig lignende måte som tog, men uten parametereoppdatering, bakoverpass og gradient anstendig del. Vi trenger ikke å gjøre alle disse VELDIG beregningsintensive oppgavene fordi vi bare bryr oss om modellens spådommer.

Jeg bruker DataLoader på en lignende måte som i tog for å få ut batcher for å mate til modellen vår.

I prosessen holder jeg rede på de faktiske etikettene og de forutsagte etikettene sammen med tapet.

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

Last inn modell og tokenizer

Laster inn de tre viktige delene av den forhåndsøvde GPT2-transformatoren: konfigurasjon, tokenizer og modell.

For dette eksemplet vil jeg bruke gpt2 fra HuggingFace forhåndsøvde transformatorer. Du kan bruke alle variantene av GP2 du ønsker.

Ved å skape model_config Jeg vil nevne antall etiketter jeg trenger for klassifiseringsoppgaven min. Siden jeg bare forutsier to følelser: positive og negative, trenger jeg bare to etiketter for num_labels.

Opprette tokenizer er ganske standard når du bruker Transformers-biblioteket. Etter å ha opprettet tokenizer er det viktig for denne opplæringen å sette polstring til venstre tokenizer.padding_side = "left" og initialiser polstringstokenet til tokenizer.eos_token som er GPT2s opprinnelige slutt på sekvens-token. Dette er den viktigste delen av denne opplæringen siden GPT2 bruker det siste symbolet for prediksjon, så vi må pute til venstre.

HuggingFace gjorde allerede det meste av arbeidet for oss og la til et klassifiseringslag til GPT2-modellen. Ved å lage modellen jeg brukte GPT2ForSequenceClassification. Siden vi har et tilpasset polstringstoken, må vi initialisere det for modellen ved hjelp av model.config.pad_token_id. Endelig må vi flytte modellen til enheten vi definerte tidligere.

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

Datasett og samler

Det er her jeg oppretter PyTorch Dataset og Data Loader med Data Collator-objekter som skal brukes til å mate data inn i modellen vår.

Det er her jeg bruker Filmanmeldelser Datasett klasse for å lage PyTorch-datasettet som returnerer tekster og etiketter.

Siden vi trenger å legge inn tall til modellen vår, må vi konvertere tekstene og merkelappene til tall. Dette er formålet med en kollator! Det tar data som sendes ut av PyTorch-datasettet og sendes gjennom Data Collator-funksjonen for å sende sekvensen for modellen vår.

Jeg holder tokenisatoren borte fra PyTorch-datasettet for å gjøre koden renere og bedre strukturert. Du kan åpenbart bruke tokeniseren inne i PyTorch-datasettet og utgangssekvenser som kan brukes rett inn i modellen uten å bruke en Data Collator.

Jeg anbefaler på det sterkeste å bruke en valideringstekstfil for å bestemme hvor mye trening som trengs for å unngå overmontering. Etter at du har funnet ut hvilke parametere som gir de beste resultatene, kan valideringsfilen innlemmes i toget og kjøre et siste tog med hele datasettet.

Datasamleren brukes til å formatere PyTorch-datasettutgangene for å matche inngangene som trengs for 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!

Tog

Jeg opprettet optimalisering og planleggerbruk av PyTorch i trening. Jeg brukte de vanligste parametrene som ble brukt av transformatormodeller.

Jeg gikk gjennom antall definerte epoker og kaller tog og validering funksjoner.

Jeg prøver å sende lignende informasjon etter hver epoke som Keras: train_loss: - val_loss: - train_acc: - valid_acc.

Etter trening, plottog og valideringstap og nøyaktighetskurver for å sjekke hvordan treningen gikk.

OBS: Treningsplanene kan se litt rare ut: Valideringsnøyaktigheten starter høyere enn treningsnøyaktigheten, og valideringstapet begynner lavere enn treningstapet. Normalt vil dette være motsatt. Jeg antar at datasplittingen tilfeldigvis er lettere for valideringsdelen eller for vanskelig for opplæringsdel eller begge deler. Siden denne veiledningen handler om å bruke GPT2 til klassifisering, vil jeg ikke bekymre meg for resultatene av modellen for mye.

# 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
Tog og valideringstap.
Trenings- og valideringsnøyaktighet.

Evaluere

Når det gjelder klassifisering er det nyttig å se på presisjonsgjenkalling og F1-poengsum.

En god måler å ha når man vurderer en modell er forvirringsmatrisen.

# 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
Forvirringsmatrise normalisert.

Siste beskjed

Hvis du nådde det så langt Congrats! 🎊 og Takk skal du ha! 🙏 for din interesse for veiledningen min!

Jeg har brukt denne koden en stund nå, og jeg føler at den kom til et punkt der den er pent dokumentert og lett å følge.

Selvfølgelig er det lett for meg å følge fordi jeg bygde den. Det er derfor noen tilbakemeldinger er velkomne, og det hjelper meg å forbedre mine fremtidige veiledninger!

Hvis du ser noe galt, kan du gi meg beskjed ved å åpne et problem på min ml_things GitHub-depot!

Mange opplæringer der ute er for det meste en engangs ting og blir ikke vedlikeholdt. Jeg har tenkt å holde veiledningene mine oppdatert så mye jeg kan.

Denne artikkelen ble opprinnelig publisert på George Mihailas personlige nettside  og publisert på nytt til TOPBOTS med tillatelse fra forfatteren.

Liker du denne artikkelen? Registrer deg for flere AI-oppdateringer.

Vi gir beskjed når vi slipper mer teknisk utdanning.

Kilde: https://www.topbots.com/gpt2-text-classification-using-hugging-face-transformers/

Tidstempel:

Mer fra TOPPBOTS