GPT2 لتصنيف النص باستخدام محولات الوجه المعانقة

عقدة المصدر: 809063

تصنيف النص

يستخدم هذا الكمبيوتر المحمول لضبط نموذج GPT2 لتصنيف النص باستخدام وجه يعانق محولات مكتبة على مجموعة بيانات مخصصة.

يعد Hugging Face أمرًا رائعًا بالنسبة لنا لتضمين جميع الوظائف اللازمة لاستخدام GPT2 في مهام التصنيف. شكرا لك معانقة الوجه!

لم أتمكن من العثور على الكثير من المعلومات حول كيفية استخدام GPT2 للتصنيف ، لذلك قررت أن أجعل هذا البرنامج التعليمي باستخدام بنية مماثلة مع نماذج محولات أخرى.

إذا كان هذا المحتوى التعليمي التفصيلي مفيدًا لك ، اشترك في القائمة البريدية لأبحاث الذكاء الاصطناعي ليتم تنبيهنا عندما نصدر مادة جديدة. 

الفكرة الرئيسية: نظرًا لأن GPT2 عبارة عن محول لفك التشفير ، يتم استخدام الرمز المميز الأخير لتسلسل الإدخال لعمل تنبؤات حول الرمز المميز التالي الذي يجب أن يتبع الإدخال. هذا يعني أن الرمز الأخير لتسلسل الإدخال يحتوي على جميع المعلومات المطلوبة في التنبؤ. مع وضع هذا في الاعتبار ، يمكننا استخدام هذه المعلومات لعمل توقع في مهمة تصنيف بدلاً من مهمة التوليد.

بعبارة أخرى ، بدلاً من استخدام تضمين الرمز المميز الأول لإجراء التنبؤ كما نفعل في Bert ، سنستخدم تضمين الرمز المميز الأخير للتنبؤ باستخدام GPT2.

نظرًا لأننا نهتم فقط بالرمز المميز الأول في Bert ، فقد كنا نضع الحشو على اليمين. الآن في GPT2 ، نستخدم الرمز المميز الأخير للتنبؤ ، لذا سنحتاج إلى التوسعة على اليسار. نظرًا للترقية الرائعة إلى HuggingFace Transformers ، يمكننا تكوين رمز GPT2 للقيام بذلك.

ما الذي يجب أن أعرفه عن هذا الكمبيوتر الدفتري؟

نظرًا لأنني أستخدم PyTorch لضبط نماذج المحولات الخاصة بنا ، فإن أي معرفة عن PyTorch مفيدة للغاية.

معرفة القليل عن محولات مكتبة تساعد أيضا.

كيف تستخدم هذا الكمبيوتر المحمول؟

كما هو الحال مع كل مشروع ، قمت ببناء هذا الكمبيوتر المحمول مع مراعاة إمكانية إعادة الاستخدام.

ستحدث جميع التغييرات في جزء معالجة البيانات حيث تحتاج إلى تخصيص PyTorch Dataset و Data Collator و DataLoader لتناسب احتياجات البيانات الخاصة بك.

جميع المعلمات التي يمكن تغييرها تقع ضمن نطاق واردات الجزء. يتم تعليق كل معلمة بشكل جيد وهيكلها لتكون بديهية قدر الإمكان.

بيانات

سيغطي هذا الكمبيوتر الدفتري محولات التدريب المسبق على مجموعة بيانات مخصصة. سأستخدم تقييمات الأفلام المعروفة إيجابية - سلبية المسمى مجموعة بيانات مراجعة الأفلام الكبيرة.

الوصف المقدم على موقع ستانفورد الإلكتروني:

هذه مجموعة بيانات لتصنيف المشاعر الثنائية تحتوي على بيانات أكثر بكثير من مجموعات البيانات المعيارية السابقة. نحن نقدم مجموعة من 25,000 مراجعة فيلم عالية القطبية للتدريب ، و 25,000 للاختبار. هناك بيانات إضافية غير مصنفة للاستخدام أيضًا. يتم توفير تنسيقات النص الخام وحقيبة الكلمات التي تمت معالجتها بالفعل. راجع ملف README المتضمن في الإصدار لمزيد من التفاصيل.

لماذا مجموعة البيانات هذه؟ أعتقد أنه من السهل فهم واستخدام مجموعة البيانات للتصنيف. أعتقد أن استخدام بيانات المشاعر دائمًا ما يكون ممتعًا.

البرمجة

الآن دعونا نفعل بعض الترميز! سنتناول كل خلية ترميز في دفتر الملاحظات ونصف ما تفعله ، وما هو الرمز ، ومتى يكون مناسبًا - اعرض الإخراج.

لقد جعلت هذا التنسيق سهل المتابعة إذا قررت تشغيل كل خلية رمز في دفتر ملاحظات Python الخاص بك.

عندما أتعلم من برنامج تعليمي أحاول دائمًا تكرار النتائج. أعتقد أنه من السهل المتابعة إذا كان لديك الرمز بجوار التفسيرات.

المرفقات

تحميل مجموعة بيانات مراجعة الأفلام الكبيرة وفك ضغطه محليًا.

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

التثبيت

  • محولات تحتاج المكتبة إلى التثبيت لاستخدام كل الأكواد الرائعة من Hugging Face. للحصول على أحدث إصدار سوف أقوم بتثبيته مباشرة من GitHub.
  • مل_الأشياء مكتبة مستخدمة لمختلف المهام المتعلقة بالتعلم الآلي. لقد أنشأت هذه المكتبة لتقليل مقدار التعليمات البرمجية التي أحتاج إلى كتابتها لكل مشروع من مشاريع التعلم الآلي.
# 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

واردات

قم باستيراد كافة المكتبات المطلوبة لهذا الكمبيوتر المحمول. قم بتعريف المعلمات المستخدمة في دفتر الملاحظات هذا:

  • set_seed(123) - من الجيد دائمًا وضع بذرة ثابتة للتكاثر.
  • epochs - عدد فترات التدريب (يوصي المؤلفون بين 2 و 4).
  • batch_size - عدد الدُفعات - اعتمادًا على أقصى طول للتسلسل وذاكرة وحدة معالجة الرسومات. بالنسبة لطول التسلسل 512 ، تعمل دفعة من 10 عادةً بدون مشاكل ذاكرة cuda. للحصول على طول تسلسل صغير ، يمكنك تجربة دفعة 32 أو أعلى. max_length - وسادة أو اقتطاع تسلسلات نصية بطول معين. سأقوم بتعيينه على 60 لتسريع التدريب.
  • device - ابحث عن GPU لاستخدامها. سيتم استخدام وحدة المعالجة المركزية بشكل افتراضي إذا لم يتم العثور على وحدة معالجة الرسومات.
  • model_name_or_path - اسم نموذج المحولات - سيستخدم نموذجًا تم اختباره مسبقًا. مسار نموذج المحول - سيتم تحميل النموذج الخاص بك من القرص المحلي. سأستخدم في هذا البرنامج التعليمي gpt2 نموذج.
  • labels_ids - قاموس التسميات ومعرفها - سيُستخدم لتحويل تسميات السلسلة إلى أرقام.
  • n_labels - كم عدد الملصقات التي نستخدمها في مجموعة البيانات هذه. يستخدم هذا لتحديد حجم رأس التصنيف.
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)

وظائف المساعد

أحب الاحتفاظ بجميع الفئات والوظائف التي سيتم استخدامها في هذا الكمبيوتر الدفتري ضمن هذا القسم للمساعدة في الحفاظ على مظهر نظيف للكمبيوتر الدفتري:

MovieReviewsDataset (Dataset)

إذا كنت قد عملت مع PyTorch من قبل ، فهذا قياسي جدًا. نحتاج إلى هذا الفصل للقراءة في مجموعة البيانات الخاصة بنا وتحليلها وإرجاع النصوص مع التسميات المرتبطة بها.

في هذا الفصل ، أحتاج فقط إلى قراءة محتوى كل ملف ، واستخدام fix_text لإصلاح أي مشاكل في Unicode وتتبع المشاعر الإيجابية والسلبية.

سألحق جميع النصوص والتسميات في القوائم.

هناك ثلاثة أجزاء رئيسية لفئة PyTorch Dataset هذه:

  • فيه() حيث نقرأ في مجموعة البيانات ونحول النص والتسميات إلى أرقام.
  • لين () حيث نحتاج إلى إعادة عدد الأمثلة التي قرأناها. يستخدم هذا عند استدعاء len (MovieReviewsDataset ()).
  • تحصل على البند() يأخذ دائمًا كمدخل قيمة int التي تمثل أي مثال من أمثلةنا يتم إرجاعه من مجموعة البيانات الخاصة بنا. إذا تم تمرير القيمة 3 ، فسنقوم بإرجاع المثال من مجموعة البيانات الخاصة بنا في الموضع 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

أستخدم هذا الفصل لإنشاء أداة تجميع البيانات. سيتم استخدام هذا في DataLoader لإنشاء أحواض البيانات التي يتم تغذيتها إلى النموذج. أستخدم أداة التشفير والتشفير على كل تسلسل لتحويل النصوص والتسميات إلى أرقام.

من حسن حظنا ، أن Hugging Face فكر في كل شيء وجعل الرمز المميز يقوم بكل المهام الثقيلة (قسّم النص إلى رموز ، وحشو ، واقتطاع ، وترميز النص إلى أرقام) وهو سهل الاستخدام للغاية!

يوجد جزءان رئيسيان من فئة Data Collator هذه:

  • فيه() حيث نقوم بتهيئة الرمز المميز الذي نخطط لاستخدامه ، وكيفية تشفير ملصقاتنا وما إذا كنا بحاجة إلى ضبط طول التسلسل على قيمة مختلفة.
  • يتصل() تستخدم كمضاد للوظيفة يأخذ كمدخل دفعة من أمثلة البيانات. يحتاج إلى إرجاع كائن بالتنسيق الذي يمكن تغذيته لنموذجنا. لحسن الحظ ، يقوم برنامج التوكن الخاص بنا بذلك من أجلنا ويعيد قاموسًا للمتغيرات الجاهزة للتغذية إلى النموذج بهذه الطريقة: model(**inputs). نظرًا لأننا نقوم بضبط النموذج ، فقد قمت أيضًا بتضمين الملصقات.
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

القطار (أداة تحميل البيانات ، مُحسِّن_ ، مجدول_ ، جهاز_)

لقد أنشأت هذه الوظيفة لأداء تمريرة كاملة عبر كائن DataLoader (يتم إنشاء كائن DataLoader من كائن نوع Dataset * الخاص بنا باستخدام فئة ** MovieReviewsDataset). هذا هو في الأساس قطار حقبة واحد من خلال مجموعة البيانات بأكملها.

يتم إنشاء أداة تحميل البيانات من PyTorch DataLoader الذي يأخذ الكائن الذي تم إنشاؤه من فئة MovieReviewsDataset ويضع كل مثال على دفعات. بهذه الطريقة يمكننا تغذية مجموعات البيانات النموذجية الخاصة بنا!

المُحسِّن_ والجدول شائعان جدًا في PyTorch. مطلوب منهم تحديث معلمات نموذجنا وتحديث معدل التعلم لدينا أثناء التدريب. هناك أكثر من ذلك بكثير ، لكنني لن أخوض في التفاصيل. يمكن أن يكون هذا في الواقع حفرة ضخمة للأرانب حيث يحدث الكثير وراء هذه الوظائف التي لا داعي للقلق. شكرا لك PyTorch!

في هذه العملية ، نتتبع التسميات الفعلية والتسميات المتوقعة جنبًا إلى جنب مع الخسارة.

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

التحقق من الصحة (أداة تحميل البيانات ، الجهاز_)

لقد قمت بتنفيذ هذه الوظيفة بطريقة مشابهة جدًا للقطار ولكن بدون تحديث المعلمات ، وتمرير خلفي وجزء لائق متدرج. لا نحتاج إلى القيام بكل تلك المهام الحاسوبية المكثفة للغاية لأننا نهتم فقط بتنبؤات نموذجنا.

أستخدم DataLoader بطريقة مماثلة كما في القطار لإخراج الدُفعات لإطعام نموذجنا.

في هذه العملية ، أتابع الملصقات الفعلية والتسميات المتوقعة جنبًا إلى جنب مع الخسارة.

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

نموذج التحميل و Tokenizer

تحميل الأجزاء الثلاثة الأساسية لمحول GPT2 مسبق الصنع: التكوين والرمز المميز والنموذج.

في هذا المثال سأستخدم gpt2 من محولات HuggingFace مسبقة الصنع. يمكنك استخدام أي أشكال تريدها من GP2.

في إنشاء ملف model_config سأذكر عدد الملصقات التي أحتاجها لمهمة التصنيف الخاصة بي. بما أنني أتوقع فقط شاعرين: إيجابي وسلبي ، سأحتاج فقط إلى تسميتين num_labels.

خلق tokenizer قياسي جدًا عند استخدام مكتبة Transformers. بعد إنشاء الرمز المميز ، من المهم أن يقوم هذا البرنامج التعليمي بضبط المساحة المتروكة على اليسار tokenizer.padding_side = "left" وتهيئة رمز الحشو إلى tokenizer.eos_token وهو رمز النهاية الأصلي للتسلسل الخاص بـ GPT2. هذا هو الجزء الأكثر أهمية في هذا البرنامج التعليمي نظرًا لأن GPT2 تستخدم الرمز المميز الأخير للتنبؤ ، لذلك نحتاج إلى التوسعة إلى اليسار.

قام HuggingFace بالفعل بمعظم العمل بالنسبة لنا وأضاف طبقة تصنيف إلى نموذج GPT2. في إنشاء النموذج الذي استخدمته GPT2ForSequenceClassification. نظرًا لأن لدينا رمزًا مخصصًا للحشو ، نحتاج إلى تهيئته للنموذج باستخدام model.config.pad_token_id. أخيرًا ، سنحتاج إلى نقل النموذج إلى الجهاز الذي حددناه سابقًا.

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

مجموعة البيانات والمجمع

هذا هو المكان الذي أقوم فيه بإنشاء مجموعة بيانات PyTorch ومحمل البيانات باستخدام كائنات Data Collator التي سيتم استخدامها لتغذية البيانات في نموذجنا.

هذا هو المكان الذي أستخدم فيه ملف مجموعة بيانات مراجعات الأفلام فئة لإنشاء مجموعة بيانات PyTorch التي ستعيد النصوص والتسميات.

نظرًا لأننا نحتاج إلى إدخال أرقام في نموذجنا ، فنحن بحاجة إلى تحويل النصوص والتسميات إلى أرقام. هذا هو الغرض من التجميع! يأخذ البيانات التي تم إخراجها بواسطة PyTorch Dataset وتمريرها من خلال وظيفة Data Collator لإخراج التسلسل لنموذجنا.

احتفظ بالرمز المميز بعيدًا عن PyTorch Dataset لجعل الكود أكثر نظافة وتنظيمًا. من الواضح أنه يمكنك استخدام الرمز المميز داخل مجموعة بيانات PyTorch وتسلسلات الإخراج التي يمكن استخدامها مباشرة في النموذج دون استخدام أداة تجميع البيانات.

أوصي بشدة باستخدام ملف نصي للتحقق من أجل تحديد مقدار التدريب المطلوب لتجنب الإفراط في التجهيز. بعد معرفة المعلمات التي تحقق أفضل النتائج ، يمكن دمج ملف التحقق في القطار وتشغيل قطار نهائي مع مجموعة البيانات بأكملها.

يتم استخدام أداة تجميع البيانات لتنسيق مخرجات PyTorch Dataset لتتناسب مع المدخلات المطلوبة لـ 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!

قطار

لقد قمت بإنشاء مُحسِّن وجدولة استخدام بواسطة PyTorch في التدريب. لقد استخدمت المعلمات الأكثر شيوعًا التي تستخدمها نماذج المحولات.

لقد مررت عبر عدد من العصور المحددة واستدعيت قطار و  التحقق من صحة الوظائف.

أحاول إخراج معلومات مماثلة بعد كل حقبة مثل Keras: train_loss: - val_loss: - train_acc: - valid_acc.

بعد التدريب ، قم بتخطيط منحنيات التدريب وفقدان التحقق والدقة للتحقق من كيفية سير التدريب.

ملحوظة: قد تبدو مخططات التدريب غريبة بعض الشيء: تبدأ دقة التحقق من الصحة أعلى من دقة التدريب ويبدأ فقدان التحقق من الصحة أقل من خسارة التدريب. عادة ما يكون هذا عكس ذلك. أفترض أن تقسيم البيانات أصبح أسهل بالنسبة لجزء التحقق من الصحة أو صعبًا جدًا بالنسبة لجزء التدريب أو كليهما. نظرًا لأن هذا البرنامج التعليمي يتعلق باستخدام GPT2 للتصنيف ، فلن أقلق كثيرًا بشأن نتائج النموذج.

# 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
تدريب وفقدان التحقق من الصحة.
دقة التدريب والتحقق من الصحة.

تقييم

عندما يكون التعامل مع التصنيف مفيدًا لإلقاء نظرة على استدعاء الدقة ودرجة F1.

مقياس جيد عند تقييم نموذج هو مصفوفة الارتباك.

# 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
مصفوفة الارتباك طبيعية.

ملاحظة أخيرة

إذا كنت قد وصلت إلى هذا الحد مبروك! 🎊 و شكرًا لك! 🙏 لاهتمامك في البرنامج التعليمي الخاص بي!

لقد كنت أستخدم هذا الرمز لفترة من الوقت الآن وأشعر أنه وصل إلى نقطة حيث يتم توثيقه بشكل جيد ويسهل متابعته.

بالطبع من السهل علي اتباعها لأنني قمت ببنائها. هذا هو السبب في أن أي تعليقات مرحب بها وتساعدني في تحسين البرامج التعليمية المستقبلية!

إذا رأيت شيئًا خاطئًا ، فيرجى إبلاغي بذلك من خلال فتح مشكلة في مستودع ml_things GitHub!

هناك الكثير من البرامج التعليمية الموجودة في الغالب لمرة واحدة ولا يتم صيانتها. أخطط للحفاظ على تحديث دروسي التعليمية قدر الإمكان.

تم نشر هذه المقالة في الأصل الموقع الشخصي لجورج محيلا  وإعادة النشر إلى TOPBOTS بإذن من المؤلف.

استمتع بهذا المقال؟ قم بالتسجيل للحصول على المزيد من تحديثات الذكاء الاصطناعي.

سنخبرك عندما نصدر المزيد من التعليم التقني.

المصدر: https://www.topbots.com/gpt2-text-classification-using-hugging-face-transformers/

الطابع الزمني:

اكثر من توب بوتس