GPT2 để phân loại văn bản bằng cách sử dụng máy biến áp mặt ôm

Nút nguồn: 809063

phân loại văn bản

Máy tính xách tay này được sử dụng để tinh chỉnh mô hình GPT2 để phân loại văn bản bằng cách sử dụng Ôm mặt máy biến áp thư viện trên một tập dữ liệu tùy chỉnh.

Chúng tôi rất vui khi được chúng tôi bao gồm tất cả các chức năng cần thiết để GPT2 được sử dụng trong các tác vụ phân loại. Cảm ơn bạn Mặt ôm!

Tôi không thể tìm thấy nhiều thông tin về cách sử dụng GPT2 để phân loại nên tôi quyết định thực hiện hướng dẫn này bằng cách sử dụng cấu trúc tương tự với các mô hình máy biến áp khác.

Nếu nội dung giáo dục chuyên sâu này hữu ích cho bạn, đăng ký vào danh sách gửi thư nghiên cứu AI của chúng tôi để được cảnh báo khi chúng tôi phát hành tài liệu mới. 

Ý chính: Vì GPT2 là một biến áp giải mã, mã thông báo cuối cùng của chuỗi đầu vào được sử dụng để đưa ra dự đoán về mã thông báo tiếp theo sẽ theo đầu vào. Điều này có nghĩa là mã thông báo cuối cùng của chuỗi đầu vào chứa tất cả thông tin cần thiết trong dự đoán. Với ý nghĩ này, chúng ta có thể sử dụng thông tin đó để đưa ra dự đoán trong nhiệm vụ phân loại thay vì nhiệm vụ tạo.

Nói cách khác, thay vì sử dụng nhúng mã thông báo đầu tiên để đưa ra dự đoán như chúng tôi làm trong Bert, chúng tôi sẽ sử dụng nhúng mã thông báo cuối cùng để đưa ra dự đoán với GPT2.

Vì chúng tôi chỉ quan tâm đến mã thông báo đầu tiên trong Bert, chúng tôi đã đệm sang bên phải. Bây giờ trong GPT2, chúng tôi đang sử dụng mã thông báo cuối cùng để dự đoán, vì vậy chúng tôi sẽ cần phải đệm ở bên trái. Do có một bản nâng cấp tuyệt vời cho HuggingFace Transformers, chúng tôi có thể định cấu hình GPT2 Tokenizer để thực hiện điều đó.

Tôi nên biết gì về sổ ghi chép này?

Vì tôi đang sử dụng PyTorch để tinh chỉnh các mô hình máy biến áp của chúng tôi nên bất kỳ kiến ​​thức nào về PyTorch đều rất hữu ích.

Biết một chút về máy biến áp thư viện cũng giúp.

Làm thế nào để sử dụng sổ ghi chép này?

Giống như với mọi dự án, tôi đã xây dựng cuốn sổ này với tâm trí có thể tái sử dụng.

Tất cả các thay đổi sẽ xảy ra trong phần xử lý dữ liệu, nơi bạn cần tùy chỉnh Bộ dữ liệu PyTorch, Bộ thu thập dữ liệu và Bộ tải dữ liệu để phù hợp với nhu cầu dữ liệu của riêng bạn.

Tất cả các thông số có thể được thay đổi đều nằm trong Nhập khẩu phần. Mỗi tham số đều được nhận xét độc đáo và có cấu trúc trực quan nhất có thể.

Bộ dữ liệu

Sổ tay này sẽ bao gồm các máy biến áp tiền luyện trên một tập dữ liệu tùy chỉnh. Tôi sẽ sử dụng các đánh giá phim nổi tiếng được gắn nhãn tích cực - tiêu cực Tập dữ liệu đánh giá phim lớn.

Mô tả được cung cấp trên trang web Stanford:

Đây là tập dữ liệu để phân loại tình cảm nhị phân chứa nhiều dữ liệu hơn đáng kể so với các tập dữ liệu chuẩn trước đó. Chúng tôi cung cấp một bộ 25,000 bài đánh giá phim có tính phân cực cao để đào tạo và 25,000 để thử nghiệm. Cũng có thêm dữ liệu chưa được gắn nhãn để sử dụng. Văn bản thô và túi định dạng từ đã được xử lý được cung cấp. Xem tệp README có trong bản phát hành để biết thêm chi tiết.

Tại sao tập dữ liệu này? Tôi tin rằng đây là một tập dữ liệu dễ hiểu và dễ sử dụng để phân loại. Tôi nghĩ rằng dữ liệu tình cảm luôn thú vị khi làm việc với.

Lập trình

Bây giờ chúng ta hãy làm một số mã hóa! Chúng tôi sẽ xem qua từng ô mã hóa trong sổ ghi chép và mô tả chức năng của nó, mã là gì và khi nào có liên quan - hiển thị kết quả đầu ra.

Tôi đã tạo định dạng này để dễ làm theo nếu bạn quyết định chạy từng ô mã trong sổ ghi chép python của riêng bạn.

Khi tôi học từ một hướng dẫn, tôi luôn cố gắng lặp lại kết quả. Tôi tin rằng thật dễ dàng để làm theo nếu bạn có mã bên cạnh các giải thích.

Tải thư liệu

Tải về Tập dữ liệu đánh giá phim lớn và giải nén cục bộ.

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

Cài đặt

  • máy biến áp thư viện cần được cài đặt để sử dụng tất cả các mã tuyệt vời từ Hugging Face. Để có được phiên bản mới nhất, tôi sẽ cài đặt nó trực tiếp từ GitHub.
  • ml_things thư viện được sử dụng cho các tác vụ khác nhau liên quan đến học máy. Tôi đã tạo thư viện này để giảm số lượng mã tôi cần viết cho mỗi dự án học máy.
# 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

Nhập khẩu

Nhập tất cả các thư viện cần thiết cho sổ ghi chép này. Khai báo các tham số được sử dụng cho sổ ghi chép này:

  • set_seed(123) - Luôn luôn tốt để đặt một hạt giống cố định để tái sản xuất.
  • epochs - Số kỷ nguyên đào tạo (tác giả khuyến nghị từ 2 đến 4).
  • batch_size - Số lô - tùy thuộc vào độ dài chuỗi tối đa và bộ nhớ GPU. Đối với độ dài chuỗi 512, một loạt 10 USUALY hoạt động mà không có vấn đề về bộ nhớ cuda. Đối với độ dài chuỗi nhỏ có thể thử lô 32 hoặc cao hơn. max_length - Chèn hoặc cắt bớt chuỗi văn bản thành một độ dài cụ thể. Tôi sẽ đặt nó thành 60 để tăng tốc độ đào tạo.
  • device - Tìm gpu để sử dụng. Sẽ sử dụng cpu theo mặc định nếu không tìm thấy gpu.
  • model_name_or_path - Tên của mô hình máy biến áp - sẽ sử dụng mô hình đã được đào tạo trước. Đường dẫn của mô hình máy biến áp - sẽ tải mô hình của riêng bạn từ đĩa cục bộ. Trong hướng dẫn này, tôi sẽ sử dụng gpt2 mô hình.
  • labels_ids - Từ điển các nhãn và id của chúng - điều này sẽ được sử dụng để chuyển đổi các nhãn chuỗi thành số.
  • n_labels - Chúng ta đang sử dụng bao nhiêu nhãn trong tập dữ liệu này. Điều này được sử dụng để quyết định kích thước của đầu phân loại.
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)

Chức năng của người trợ giúp

Tôi muốn giữ lại tất cả các Lớp và chức năng sẽ được sử dụng trong sổ ghi chép này trong phần này để giúp duy trì vẻ ngoài sạch sẽ của sổ ghi chép:

MovieReviewsDataset (Dataset)

Nếu bạn đã làm việc với PyTorch trước đây, đây là tiêu chuẩn khá tốt. Chúng ta cần lớp này đọc trong tập dữ liệu của chúng ta, phân tích cú pháp nó và trả về văn bản với các nhãn được liên kết của chúng.

Trong lớp học này, tôi chỉ cần đọc nội dung của mỗi tệp, sử dụng fix_text để khắc phục mọi sự cố Unicode và theo dõi các cảm xúc tích cực và tiêu cực.

Tôi sẽ nối tất cả các văn bản và nhãn trong danh sách.

Có ba phần chính của lớp Tập dữ liệu PyTorch này:

  • trong đó() nơi chúng tôi đọc trong tập dữ liệu và chuyển đổi văn bản và nhãn thành số.
  • len () nơi chúng ta cần trả về số lượng ví dụ mà chúng ta đã đọc. Điều này được sử dụng khi gọi len (MovieReviewsDataset ()).
  • getitem () luôn nhận dưới dạng đầu vào một giá trị int đại diện cho ví dụ nào từ các ví dụ của chúng tôi sẽ trả về từ tập dữ liệu của chúng tôi. Nếu giá trị 3 được chuyển, chúng tôi sẽ trả về biểu mẫu ví dụ tập dữ liệu của chúng tôi ở vị trí 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]}

Bộ đối chiếu Gpt2Phân loại

Tôi sử dụng lớp này để tạo Bộ thu thập dữ liệu. Điều này sẽ được sử dụng trong DataLoader để tạo các nhóm dữ liệu được cung cấp cho mô hình. Tôi sử dụng tokenizer và bộ mã hóa nhãn trên mỗi chuỗi để chuyển đổi văn bản và nhãn thành số.

Thật may mắn cho chúng tôi, Ôm Face đã nghĩ ra mọi thứ và làm cho tokenizer thực hiện tất cả các công việc nặng nhọc (chia văn bản thành mã thông báo, đệm, cắt ngắn, mã hóa văn bản thành số) và rất dễ sử dụng!

Có hai phần chính của lớp Data Collator này:

  • trong đó() nơi chúng tôi khởi tạo tokenizer mà chúng tôi định sử dụng, cách mã hóa các nhãn của chúng tôi và nếu chúng tôi cần đặt độ dài chuỗi thành một giá trị khác.
  • gọi() được sử dụng như bộ đối chiếu hàm nhận làm đầu vào một loạt các ví dụ dữ liệu. Nó cần trả về một đối tượng có định dạng có thể được cung cấp cho mô hình của chúng ta. May mắn thay, tokenizer của chúng tôi thực hiện điều đó cho chúng tôi và trả về một từ điển các biến sẵn sàng được cung cấp cho mô hình theo cách này: model(**inputs). Vì chúng tôi đang tinh chỉnh mô hình nên tôi cũng bao gồm các nhãn.
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

đào tạo (dataloader, Optimizer_, Scheduler_, device_)

Tôi đã tạo hàm này để thực hiện chuyển toàn bộ qua đối tượng DataLoader (đối tượng DataLoader được tạo từ đối tượng kiểu Dataset * của chúng tôi bằng cách sử dụng lớp ** MovieReviewsDataset). Về cơ bản, đây là một đợt đào tạo kỷ nguyên thông qua toàn bộ tập dữ liệu.

Dataloader được tạo từ PyTorch DataLoader, lấy đối tượng được tạo từ lớp MovieReviewsDataset và đặt từng ví dụ theo lô. Bằng cách này, chúng tôi có thể cung cấp các lô dữ liệu mô hình của mình!

Trình tối ưu hóa_ và Trình lập biểu_ rất phổ biến trong PyTorch. Họ được yêu cầu cập nhật các thông số của mô hình của chúng tôi và cập nhật tỷ lệ học tập của chúng tôi trong quá trình đào tạo. Còn nhiều hơn thế nữa nhưng tôi sẽ không đi vào chi tiết. Đây thực sự có thể là một lỗ hổng lớn vì RẤT NHIỀU xảy ra đằng sau những chức năng này mà chúng ta không cần phải lo lắng. Xin cảm ơn PyTorch!

Trong quá trình này, chúng tôi theo dõi các nhãn thực tế và các nhãn dự đoán cùng với tổn thất.

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

xác thực (dataloader, device_)

Tôi đã triển khai chức năng này theo cách rất giống với train nhưng không có cập nhật tham số, chuyển ngược và một phần tốt gradient. Chúng tôi không cần phải thực hiện tất cả các tác vụ RẤT phức tạp về tính toán bởi vì chúng tôi chỉ quan tâm đến các dự đoán của mô hình của chúng tôi.

Tôi sử dụng DataLoader theo cách tương tự như trong đào tạo để lấy ra các lô để cung cấp cho mô hình của chúng tôi.

Trong quá trình này, tôi theo dõi các nhãn thực tế và các nhãn dự đoán cùng với tổn thất.

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

Tải mô hình và Tokenizer

Đang tải ba bộ phận thiết yếu của máy biến áp GPT2 được đào tạo trước: cấu hình, bộ tách sóng và mô hình.

Đối với ví dụ này, tôi sẽ sử dụng gpt2 từ máy biến áp đã được đào tạo trước của HuggingFace. Bạn có thể sử dụng bất kỳ biến thể nào của GP2 mà bạn muốn.

Trong việc tạo ra model_config Tôi sẽ đề cập đến số lượng nhãn tôi cần cho nhiệm vụ phân loại của mình. Vì tôi chỉ dự đoán hai cảm xúc: tích cực và tiêu cực, tôi sẽ chỉ cần hai nhãn cho num_labels.

Tạo tokenizer là khá tiêu chuẩn khi sử dụng thư viện Transformers. Sau khi tạo tokenizer, điều quan trọng đối với hướng dẫn này là đặt phần đệm ở bên trái tokenizer.padding_side = "left" và khởi tạo mã thông báo đệm để tokenizer.eos_token là mã thông báo kết thúc chuỗi ban đầu của GPT2. Đây là phần quan trọng nhất của hướng dẫn này vì GPT2 sử dụng mã thông báo cuối cùng để dự đoán, vì vậy chúng ta cần gạt sang bên trái.

HuggingFace đã thực hiện hầu hết công việc cho chúng tôi và thêm một lớp phân loại vào mô hình GPT2. Khi tạo mô hình tôi đã sử dụng GPT2ForSequenceClassification. Vì chúng tôi có mã thông báo đệm tùy chỉnh, chúng tôi cần khởi tạo nó cho mô hình bằng cách sử dụng model.config.pad_token_id. Cuối cùng, chúng ta sẽ cần di chuyển mô hình sang thiết bị mà chúng ta đã xác định trước đó.

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

Dataset và Collator

Đây là nơi tôi tạo Tập dữ liệu PyTorch và Trình tải dữ liệu với các đối tượng Data Collator sẽ được sử dụng để cung cấp dữ liệu vào mô hình của chúng tôi.

Đây là nơi tôi sử dụng MovieReviewsBộ dữ liệu lớp để tạo Tập dữ liệu PyTorch sẽ trả về văn bản và nhãn.

Vì chúng ta cần nhập số vào mô hình của mình, chúng ta cần chuyển đổi văn bản và nhãn thành số. Đây là mục đích của một đối tác! Nó lấy dữ liệu được xuất ra bởi Tập dữ liệu PyTorch và được chuyển qua chức năng Bộ thu thập dữ liệu để xuất ra chuỗi cho mô hình của chúng tôi.

Tôi đang giữ tokenizer khỏi Tập dữ liệu PyTorch để làm cho mã sạch hơn và có cấu trúc tốt hơn. Rõ ràng là bạn có thể sử dụng tokenizer bên trong Tập dữ liệu PyTorch và các chuỗi đầu ra có thể được sử dụng thẳng vào mô hình mà không cần sử dụng Bộ thu thập dữ liệu.

Tôi thực sự khuyên bạn nên sử dụng tệp văn bản xác thực để xác định mức độ đào tạo cần thiết để tránh trang bị quá nhiều. Sau khi bạn tìm ra thông số nào mang lại kết quả tốt nhất, tệp xác nhận có thể được kết hợp trong đào tạo và chạy một chuyến tàu cuối cùng với toàn bộ tập dữ liệu.

Bộ đối chiếu dữ liệu được sử dụng để định dạng các đầu ra của Tập dữ liệu PyTorch để khớp với các đầu vào cần thiết cho GPT2.

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

Train

Tôi đã tạo trình tối ưu hóa và sử dụng công cụ lập lịch của PyTorch trong đào tạo. Tôi đã sử dụng các thông số phổ biến nhất được sử dụng bởi các mô hình máy biến áp.

Tôi lặp lại số lượng các kỷ nguyên đã xác định và gọi đào tạo và xác nhận chức năng.

Tôi đang cố gắng xuất thông tin tương tự sau mỗi kỷ nguyên dưới dạng Keras: train_loss: - val_loss: - train_acc: - valid_acc.

Sau khi đào tạo, vẽ biểu đồ của tàu và các đường cong mất mát xác thực và độ chính xác để kiểm tra xem đào tạo diễn ra như thế nào.

Lưu ý: Các lô đào tạo có thể trông hơi kỳ lạ: Độ chính xác xác thực bắt đầu cao hơn độ chính xác đào tạo và mất xác thực bắt đầu thấp hơn mất mát đào tạo. Thông thường điều này sẽ ngược lại. Tôi cho rằng việc phân tách dữ liệu chỉ xảy ra dễ dàng hơn đối với phần xác thực hoặc quá khó đối với phần đào tạo hoặc cả hai. Vì hướng dẫn này là về việc sử dụng GPT2 để phân loại nên tôi sẽ không quá lo lắng về kết quả của mô hình.

# 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
Mất chuyến tàu và xác thực.
Đào tạo và xác nhận độ chính xác.

Đánh giá

Khi xử lý phân loại, rất hữu ích khi xem xét độ thu hồi chính xác và điểm F1.

Một thước đo tốt cần có khi đánh giá một mô hình là ma trận nhầm lẫn.

# 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
Đã chuẩn hóa ma trận nhầm lẫn.

Lưu ý thức

Nếu bạn đã làm nó xa đến mức này Chúc mừng! 🎊 và Cảm ơn bạn! 🙏 cho sự quan tâm của bạn đến hướng dẫn của tôi!

Tôi đã sử dụng mã này một thời gian và tôi cảm thấy nó đã đến mức được ghi lại một cách độc đáo và dễ theo dõi.

Tất nhiên là dễ dàng để tôi làm theo vì tôi đã xây dựng nó. Đó là lý do tại sao mọi phản hồi đều được hoan nghênh và nó giúp tôi cải thiện các hướng dẫn trong tương lai!

Nếu bạn thấy điều gì đó không ổn, vui lòng cho tôi biết bằng cách mở một vấn đề trên Kho lưu trữ ml_things GitHub!

Rất nhiều hướng dẫn trên mạng chủ yếu là hướng dẫn một lần và không được duy trì. Tôi dự định cập nhật các hướng dẫn của mình nhiều nhất có thể.

Bài viết này ban đầu được xuất bản vào Trang web cá nhân của George Mihaila  và được xuất bản lại lên TOPBOTS với sự cho phép của tác giả.

Thích bài viết này? Đăng ký để nhận thêm các bản cập nhật AI.

Chúng tôi sẽ cho bạn biết khi chúng tôi phát hành giáo dục kỹ thuật nhiều hơn.

Nguồn: https://www.topbots.com/gpt2-text-classification-using-hugging-face-transformers/

Dấu thời gian:

Thêm từ HÀNG ĐẦU