抱き締めるフェイストランスフォーマーを使用したテキスト分類のためのGPT2

ソースノード: 809063

テキスト分類

このノートブックは、を使用してテキスト分類のためにGPT2モデルを微調整するために使用されます ハグ顔 トランスフォーマー カスタムデータセットのライブラリ。

Hugging Faceは、GPT2を分類タスクで使用するために必要なすべての機能を含めることができるので非常に便利です。 抱きしめてくれてありがとう!

分類にGPT2を使用する方法について多くの情報を見つけることができなかったので、他のトランスフォーマーモデルと同様の構造を使用してこのチュートリアルを作成することにしました。

この詳細な教育コンテンツがあなたに役立つ場合は、 AIリサーチメーリングリストに登録する 新しい素材がリリースされたときに警告が表示されます。 

本旨: GPT2はデコーダトランスフォーマであるため、入力シーケンスの最後のトークンを使用して、入力に続く次のトークンに関する予測を行います。 これは、入力シーケンスの最後のトークンに、予測に必要なすべての情報が含まれていることを意味します。 これを念頭に置いて、その情報を使用して、生成タスクではなく分類タスクで予測を行うことができます。

つまり、Bertのように最初のトークン埋め込みを使用して予測を行う代わりに、最後のトークン埋め込みを使用してGPT2で予測を行います。

Bertの最初のトークンしか気にしないので、右側にパディングしていました。 現在GPT2では、予測に最後のトークンを使用しているため、左側を埋める必要があります。 HuggingFace Transformersへの優れたアップグレードにより、GPT2Tokenizerを構成してそれを実行できます。

このノートブックについて何を知っておくべきですか?

私はPyTorchを使用してトランスフォーマーモデルを微調整しているので、PyTorchに関する知識は非常に役立ちます。

について少し知っている トランスフォーマー ライブラリも役立ちます。

このノートブックの使い方は?

すべてのプロジェクトと同様に、私はこのノートブックを再利用性を念頭に置いて作成しました。

すべての変更は、PyTorch Dataset、Data Collat​​or、および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から直接インストールします。
  • ml_things さまざまな機械学習関連のタスクに使用されるライブラリ。 このライブラリは、機械学習プロジェクトごとに作成する必要のあるコードの量を減らすために作成しました。
# 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 –バッチ数–最大シーケンス長とGPUメモリによって異なります。 512シーケンス長の場合、10のバッチは通常cudaメモリの問題なしで機能します。 シーケンスの長さが短い場合は、32以上のバッチを試すことができます。 max_length –テキストシーケンスを特定の長さにパディングまたは切り捨てます。 トレーニングをスピードアップするために60に設定します。
  • device –使用するGPUを探します。 GPUが見つからない場合、デフォルトでCPUを使用します。
  • model_name_or_path –トランスフォーマーモデルの名前–すでに事前トレーニングされたモデルを使用します。 トランスフォーマーモデルのパス–ローカルディスクから独自のモデルをロードします。 このチュートリアルでは、 gpt2 モデル。
  • labels_ids –ラベルとそのIDの辞書–これは文字列ラベルを数値に変換するために使用されます。
  • 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(データセット)

以前にPyTorchを使用したことがある場合、これはかなり標準的です。 データセットを読み取り、解析して、関連するラベルとともにテキストを返すには、このクラスが必要です。

このクラスでは、各ファイルのコンテンツを読み込み、fix_textを使用してUnicodeの問題を修正し、ポジティブな感情とネガティブな感情を追跡するだけで済みます。

リスト内のすべてのテキストとラベルを追加します。

このPyTorchデータセットクラスには、次のXNUMXつの主要部分があります。

  • その中に() ここで、データセットを読み取り、テキストとラベルを数値に変換します。
  • len() ここで、読み込んだ例の数を返す必要があります。これは、len(MovieReviewsDataset())を呼び出すときに使用されます。
  • getitem() データセットから返す例の例を表す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]}

Gpt2ClassificationCollat​​or

このクラスを使用してデータコレーターを作成します。 これは、モデルに供給されるデータのバスを作成するためにDataLoaderで使用されます。 各シーケンスでトークナイザーとラベルエンコーダーを使用して、テキストとラベルを数値に変換します。

私たちにとって幸運なことに、Hugging Faceはすべてを考え、トークナイザーにすべての面倒な作業(テキストのトークンへの分割、パディング、切り捨て、テキストの数値へのエンコード)を行わせ、非常に使いやすいです!

このDataCollat​​orクラスには、次のXNUMXつの主要部分があります。

  • その中に() 使用する予定のトークナイザーを初期化する場所、ラベルをエンコードする方法、シーケンスの長さを別の値に設定する必要があるかどうか。
  • コール() データ例のバッチを入力として受け取る関数コレーターとして使用されます。 モデルにフィードできる形式のオブジェクトを返す必要があります。 幸いなことに、トークナイザーはそれを実行し、次の方法でモデルにフィードする準備ができている変数のディクショナリを返します。 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

train(dataloader、optimizer_、scheduler_、device_)

この関数を作成して、DataLoaderオブジェクトのフルパスを実行しました(DataLoaderオブジェクトは、** MovieReviewsDatasetクラスを使用してDataset *タイプのオブジェクトから作成されます)。 これは基本的に、データセット全体を通じたXNUMXつのエポックトレインです。

データローダーは、MovieReviewsDatasetクラスから作成されたオブジェクトを取得し、各例をバッチに配置するPyTorchDataLoaderから作成されます。 このようにして、モデルのデータバッチをフィードできます。

オプティマイザー_とスケジューラー_は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

検証(データローダー、デバイス_)

私はこの関数をtrainと非常によく似た方法で実装しましたが、パラメーターの更新、後方通過、最急降下法の部分はありませんでした。 モデルの予測のみを考慮しているため、これらの非常に計算量の多いタスクをすべて実行する必要はありません。

電車の場合と同じように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

モデルとトークナイザーのロード

事前にトレーニングされたGPT2トランスフォーマーのXNUMXつの重要な部分(構成、トークナイザー、モデル)をロードします。

この例では、 gpt2 HuggingFaceの事前トレーニング済みトランスフォーマーから。 GP2の任意のバリエーションを使用できます。

作成中 model_config 分類タスクに必要なラベルの数について説明します。 ポジティブとネガティブのXNUMXつの感情しか予測できないので、必要なラベルはXNUMXつだけです。 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`

データセットとコレーター

ここで、モデルにデータをフィードするために使用されるDataCollat​​orオブジェクトを使用してPyTorchデータセットとデータローダーを作成します。

これは私が使用する場所です 映画レビューデータセット テキストとラベルを返すPyTorchデータセットを作成するクラス。

モデルに数値を入力する必要があるため、テキストとラベルを数値に変換する必要があります。 これがコレーターの目的です! PyTorchデータセットによって出力され、Data Collat​​or関数を介して渡されたデータを取得して、モデルのシーケンスを出力します。

コードをよりクリーンで構造化するために、トークナイザーをPyTorchデータセットから遠ざけています。 明らかに、PyTorchデータセット内のトークナイザーと、データコレーターを使用せずにモデルに直接使用できる出力シーケンスを使用できます。

過剰適合を回避するために必要なトレーニングの量を決定するために、検証テキストファイルを使用することを強くお勧めします。 どのパラメーターが最良の結果をもたらすかを理解した後、検証ファイルをトレインに組み込み、データセット全体を使用して最終トレインを実行できます。

データコレーターは、GPT2に必要な入力と一致するようにPyTorchデータセット出力をフォーマットするために使用されます。

# 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_thingsGitHubリポジトリ!

そこにある多くのチュートリアルは、ほとんどがXNUMX回限りのものであり、維持されていません。 チュートリアルをできるだけ最新の状態に保つ予定です。

この記事は、最初に公開された ジョージミハイラの個人ウェブサイト  著者の許可を得てTOPBOTSに再公開しました。

この記事をお楽しみください? その他のAIアップデートにサインアップしてください。

技術教育が追加されましたらお知らせします。

ソース:https://www.topbots.com/gpt2-text-classification-using-hugging-face-transformers/

タイムスタンプ:

より多くの トップボット