GPT2 Untuk Klasifikasi Teks Menggunakan Hugging Face Transformers

Node Sumber: 809063

klasifikasi teks

Notebook ini digunakan untuk menyempurnakan model GPT2 untuk penggunaan klasifikasi teks Wajah Memeluk transformer perpustakaan pada set data khusus.

Hugging Face sangat menyenangkan bagi kami untuk menyertakan semua fungsionalitas yang diperlukan GPT2 untuk digunakan dalam tugas klasifikasi. Terima kasih Wajah Memeluk!

Saya tidak dapat menemukan banyak informasi tentang cara menggunakan GPT2 untuk klasifikasi jadi saya memutuskan untuk membuat tutorial ini menggunakan struktur yang mirip dengan model transformator lainnya.

Jika konten pendidikan yang mendalam ini bermanfaat bagi Anda, berlangganan milis penelitian AI kami untuk diperingatkan ketika kami merilis materi baru. 

Ide utama: Karena GPT2 adalah transformator dekoder, token terakhir dari urutan masukan digunakan untuk membuat prediksi tentang token berikutnya yang harus mengikuti masukan. Artinya, token terakhir dari urutan input berisi semua informasi yang dibutuhkan dalam prediksi. Dengan pemikiran ini, kita dapat menggunakan informasi tersebut untuk membuat prediksi dalam tugas klasifikasi, bukan tugas pembuatan.

Dengan kata lain, alih-alih menggunakan penyematan token pertama untuk membuat prediksi seperti yang kami lakukan di Bert, kami akan menggunakan penyematan token terakhir untuk membuat prediksi dengan GPT2.

Karena kami hanya peduli tentang token pertama di Bert, kami bergerak ke kanan. Sekarang di GPT2 kami menggunakan token terakhir untuk prediksi jadi kami perlu pad di sebelah kiri. Karena peningkatan yang bagus ke HuggingFace Transformers, kami dapat mengkonfigurasi Tokenizer GPT2 untuk melakukan hal itu.

Apa yang harus saya ketahui untuk buku catatan ini?

Karena saya menggunakan PyTorch untuk menyempurnakan model transformator kami, pengetahuan apa pun tentang PyTorch sangat berguna.

Mengetahui sedikit tentang transformer perpustakaan membantu juga.

Bagaimana cara menggunakan notebook ini?

Seperti setiap proyek, saya membuat notebook ini dengan mempertimbangkan kegunaan kembali.

Semua perubahan akan terjadi di bagian pemrosesan data di mana Anda perlu menyesuaikan Set Data PyTorch, Pengumpul Data, dan Pemuat Data agar sesuai dengan kebutuhan data Anda sendiri.

Semua parameter yang dapat diubah berada di bawah Impor bagian. Setiap parameter diberi komentar dengan baik dan disusun seintuitif mungkin.

Dataset

Notebook ini akan mencakup trafo pra-pelatihan pada set data kustom. Saya akan menggunakan review film-film terkenal berlabel positif - negatif Kumpulan Data Ulasan Film Besar.

Deskripsi tersedia di situs web Stanford:

Ini adalah kumpulan data untuk klasifikasi sentimen biner yang berisi lebih banyak data secara substansial daripada kumpulan data tolok ukur sebelumnya. Kami menyediakan 25,000 ulasan film yang sangat polar untuk pelatihan, dan 25,000 untuk pengujian. Ada data tambahan yang tidak berlabel untuk digunakan juga. Teks mentah dan format kantong kata-kata yang sudah diproses disediakan. Lihat file README yang terdapat dalam rilis untuk lebih jelasnya.

Mengapa kumpulan data ini? Saya percaya ini adalah kumpulan data yang mudah dipahami dan digunakan untuk klasifikasi. Saya pikir data sentimen selalu menyenangkan untuk dikerjakan.

Pengkodean

Sekarang mari kita lakukan pengkodean! Kami akan memeriksa setiap sel pengkodean di notebook dan menjelaskan apa yang dilakukannya, apa kodenya, dan kapan relevan - tunjukkan hasilnya.

Saya membuat format ini mudah diikuti jika Anda memutuskan untuk menjalankan setiap sel kode di notebook python Anda sendiri.

Ketika saya belajar dari tutorial, saya selalu mencoba meniru hasilnya. Saya yakin mudah untuk diikuti jika Anda memiliki kode di samping penjelasannya.

Download

Download Kumpulan Data Ulasan Film Besar dan unzip secara lokal.

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

Menginstal

  • transformer perpustakaan perlu diinstal untuk menggunakan semua kode mengagumkan dari Hugging Face. Untuk mendapatkan versi terbaru saya akan menginstalnya langsung dari GitHub.
  • ml_sesuatu perpustakaan yang digunakan untuk berbagai tugas terkait pembelajaran mesin. Saya membuat pustaka ini untuk mengurangi jumlah kode yang perlu saya tulis untuk setiap proyek pembelajaran mesin.
# 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

Impor

Impor semua pustaka yang diperlukan untuk notebook ini. Deklarasikan parameter yang digunakan untuk notebook ini:

  • set_seed(123) - Selalu baik untuk memasang benih tetap untuk reproduktifitas.
  • epochs - Jumlah periode pelatihan (penulis merekomendasikan antara 2 dan 4).
  • batch_size - Jumlah batch - tergantung pada panjang urutan maksimal dan memori GPU. Untuk 512 panjang urutan, 10 biasanya bekerja tanpa masalah memori cuda. Untuk panjang urutan kecil dapat mencoba batch 32 atau lebih tinggi. max_length - Pad atau potong urutan teks ke panjang tertentu. Saya akan mengaturnya menjadi 60 untuk mempercepat pelatihan.
  • device - Cari gpu untuk digunakan. Akan menggunakan cpu secara default jika tidak ada gpu yang ditemukan.
  • model_name_or_path - Nama model transformator - akan menggunakan model yang sudah dilatih sebelumnya. Jalur model transformator - akan memuat model Anda sendiri dari disk lokal. Dalam tutorial ini saya akan menggunakan gpt2 Model.
  • labels_ids - Kamus label dan id mereka - ini akan digunakan untuk mengubah label string menjadi angka.
  • n_labels - Berapa banyak label yang kami gunakan dalam kumpulan data ini. Ini digunakan untuk menentukan ukuran kepala klasifikasi.
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)

Fungsi Pembantu

Saya ingin menyimpan semua Kelas dan fungsi yang akan digunakan di notebook ini di bawah bagian ini untuk membantu menjaga tampilan notebook tetap bersih:

MovieReviewsDataset (Dataset)

Jika Anda pernah bekerja dengan PyTorch sebelumnya, ini cukup standar. Kami membutuhkan kelas ini untuk membaca dalam kumpulan data kami, menguraikannya, dan mengembalikan teks dengan label yang terkait.

Di kelas ini saya hanya perlu membaca konten setiap file, menggunakan fix_text untuk memperbaiki masalah Unicode apa pun dan melacak sentimen positif dan negatif.

Saya akan menambahkan semua teks dan label dalam daftar.

Ada tiga bagian utama dari kelas Dataset PyTorch ini:

  • init () di mana kita membaca dalam dataset dan mengubah teks dan label menjadi angka.
  • len () di mana kita perlu mengembalikan jumlah contoh yang kita baca. Ini digunakan saat memanggil len (MovieReviewsDataset ()).
  • getitem () selalu mengambil sebagai masukan nilai int yang mewakili contoh mana dari contoh kami untuk dikembalikan dari dataset kami. Jika nilai 3 dilewatkan, kami akan mengembalikan contoh dari dataset kami di posisi 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

Saya menggunakan kelas ini untuk membuat Pengumpul Data. Ini akan digunakan di DataLoader untuk membuat kumpulan data yang diumpankan ke model. Saya menggunakan tokenizer dan label encoder pada setiap urutan untuk mengubah teks dan label menjadi angka.

Beruntung bagi kami, Hugging Face memikirkan segalanya dan membuat tokenizer melakukan semua pekerjaan berat (membagi teks menjadi token, padding, memotong, menyandikan teks menjadi angka) dan sangat mudah digunakan!

Ada dua bagian utama dari kelas Pengumpul Data ini:

  • init () tempat kami menginisialisasi tokenizer yang akan kami gunakan, cara menyandikan label kami, dan jika kami perlu menyetel panjang urutan ke nilai yang berbeda.
  • panggilan() digunakan sebagai pengumpul fungsi yang mengambil sebagai masukan sekumpulan contoh data. Itu perlu mengembalikan objek dengan format yang bisa diumpankan ke model kita. Untungnya tokenizer kami melakukannya untuk kami dan mengembalikan kamus variabel yang siap untuk diumpankan ke model dengan cara ini: model(**inputs). Karena kami menyempurnakan model, saya juga menyertakan labelnya.
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

melatih (dataloader, pengoptimal_, penjadwal_, perangkat_)

Saya membuat fungsi ini untuk melakukan full pass melalui objek DataLoader (objek DataLoader dibuat dari objek tipe Dataset * menggunakan kelas ** MovieReviewsDataset). Ini pada dasarnya adalah satu rangkaian zaman melalui seluruh kumpulan data.

Dataloader dibuat dari PyTorch DataLoader yang mengambil objek yang dibuat dari kelas MovieReviewsDataset dan menempatkan setiap contoh dalam batch. Dengan cara ini kita dapat memberi makan kumpulan model data kita!

Pengoptimal_ dan penjadwal_ sangat umum di PyTorch. Mereka diminta untuk memperbarui parameter model kami dan memperbarui kecepatan pembelajaran kami selama pelatihan. Ada lebih dari itu tetapi saya tidak akan menjelaskan secara detail. Ini sebenarnya bisa menjadi lubang kelinci besar karena BANYAK terjadi di balik fungsi-fungsi ini sehingga kita tidak perlu khawatir. Terima kasih PyTorch!

Dalam prosesnya, kami melacak label sebenarnya dan label yang diprediksi beserta kerugiannya.

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

validasi (dataloader, device_)

Saya mengimplementasikan fungsi ini dengan cara yang sangat mirip seperti train tetapi tanpa pembaruan parameter, backward pass, dan bagian gradien yang layak. Kita tidak perlu melakukan semua tugas yang SANGAT intensif secara komputasi karena kita hanya peduli dengan prediksi model kita.

Saya menggunakan DataLoader dengan cara yang sama seperti di kereta untuk mengeluarkan batch untuk diumpankan ke model kami.

Dalam prosesnya saya melacak label yang sebenarnya dan label yang diprediksi bersama dengan kerugiannya.

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

Muat Model dan Tokenizer

Memuat tiga bagian penting dari trafo GPT2 yang sudah dilatih sebelumnya: konfigurasi, tokenizer, dan model.

Untuk contoh ini saya akan gunakan gpt2 dari trafo pra-pelatihan HuggingFace. Anda dapat menggunakan variasi GP2 apa pun yang Anda inginkan.

Dalam menciptakan model_config Saya akan menyebutkan jumlah label yang saya perlukan untuk tugas klasifikasi saya. Karena saya hanya memprediksi dua sentimen: positif dan negatif, saya hanya membutuhkan dua label num_labels.

Menciptakan tokenizer cukup standar saat menggunakan pustaka Transformers. Setelah membuat tokenizer, penting untuk tutorial ini untuk mengatur padding ke kiri tokenizer.padding_side = "left" dan menginisialisasi padding token ke tokenizer.eos_token yang merupakan token akhir urutan asli GPT2. Ini adalah bagian paling penting dari tutorial ini karena GPT2 menggunakan token terakhir untuk prediksi sehingga kita perlu berpindah ke kiri.

HuggingFace sudah melakukan sebagian besar pekerjaan untuk kami dan menambahkan lapisan klasifikasi ke model GPT2. Dalam membuat model yang saya gunakan GPT2ForSequenceClassification. Karena kita memiliki token padding khusus, kita perlu menginisialisasinya untuk model yang digunakan model.config.pad_token_id. Akhirnya kita perlu memindahkan model ke perangkat yang kita tentukan sebelumnya.

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

Set data dan Kolator

Di sinilah saya membuat PyTorch Dataset dan Data Loader dengan objek Data Collator yang akan digunakan untuk memasukkan data ke dalam model kita.

Di sinilah saya menggunakan Kumpulan Data Ulasan Film kelas untuk membuat Dataset PyTorch yang akan mengembalikan teks dan label.

Karena kita perlu memasukkan angka ke model kita, kita perlu mengubah teks dan label menjadi angka. Inilah tujuan seorang kolator! Ini mengambil data yang dikeluarkan oleh PyTorch Dataset dan melewati fungsi Data Collator untuk mengeluarkan urutan untuk model kita.

Saya menjauhkan tokenizer dari PyTorch Dataset untuk membuat kode lebih bersih dan terstruktur dengan lebih baik. Anda jelas dapat menggunakan tokenizer di dalam Dataset PyTorch dan urutan keluaran yang dapat digunakan langsung ke model tanpa menggunakan Pengumpul Data.

Saya sangat menyarankan untuk menggunakan file teks validasi untuk menentukan berapa banyak pelatihan yang diperlukan untuk menghindari overfitting. Setelah Anda mengetahui parameter apa yang menghasilkan hasil terbaik, file validasi dapat digabungkan dalam train dan menjalankan train terakhir dengan seluruh dataset.

Pengumpul data digunakan untuk memformat keluaran Set Data PyTorch agar sesuai dengan masukan yang diperlukan untuk 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!

Pelatihan VE

Saya membuat pengoptimal dan penggunaan penjadwal oleh PyTorch dalam pelatihan. Saya menggunakan parameter paling umum yang digunakan oleh model transformer.

Saya mengulang melalui jumlah periode yang ditentukan dan memanggil kereta api dan pengesahan fungsi.

Saya mencoba menampilkan info serupa setelah setiap periode sebagai Keras: train_loss: - val_loss: - train_acc: - valid_acc.

Setelah pelatihan, latih plot dan kerugian validasi serta kurva akurasi untuk memeriksa bagaimana pelatihan tersebut berjalan.

Catatan: Plot pelatihan mungkin terlihat sedikit aneh: Akurasi validasi dimulai lebih tinggi daripada akurasi pelatihan dan kerugian validasi dimulai lebih rendah daripada kerugian pelatihan. Biasanya ini akan sebaliknya. Saya berasumsi bahwa pemisahan data kebetulan lebih mudah untuk bagian validasi atau terlalu sulit untuk bagian pelatihan atau keduanya. Karena tutorial ini tentang penggunaan GPT2 untuk klasifikasi, saya tidak akan terlalu mengkhawatirkan hasil modelnya.

# 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
Kerugian pelatihan dan validasi.
Melatih dan akurasi validasi.

Mengevaluasi

Saat menangani klasifikasi berguna untuk melihat recall presisi dan skor F1.

Ukuran yang baik untuk dimiliki saat mengevaluasi model adalah matriks kebingungan.

# 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
Matriks kebingungan dinormalisasi.

Catatan akhir

Jika Anda berhasil sejauh ini Selamat! 🎊 dan Terima kasih! 🙏 atas minat Anda pada tutorial saya!

Saya telah menggunakan kode ini untuk sementara waktu sekarang dan saya merasa itu sampai pada titik di mana didokumentasikan dengan baik dan mudah diikuti.

Tentu mudah untuk saya ikuti karena saya membangunnya. Itulah sebabnya umpan balik apa pun diterima dan ini membantu saya meningkatkan tutorial saya di masa mendatang!

Jika Anda melihat sesuatu yang salah, beri tahu saya dengan membuka masalah di my ml_things repositori GitHub!

Banyak tutorial di luar sana yang sebagian besar bersifat satu kali dan tidak dipertahankan. Saya berencana untuk terus memperbarui tutorial saya sebanyak yang saya bisa.

Artikel ini awalnya diterbitkan pada Situs web pribadi George Mihaila  dan diterbitkan kembali ke TOPBOTS dengan izin dari penulis.

Nikmati artikel ini? Daftar untuk pembaruan AI lainnya.

Kami akan memberi tahu Anda ketika kami merilis lebih banyak pendidikan teknis.

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

Stempel Waktu:

Lebih dari TOPBOT