首頁 > 軟體

詳解基於Transformer實現電影評論星級分類任務

2023-11-02 22:00:24

Transformer模型概述

Transformer是一種用於序列到序列學習的神經網路架構,專門用於處理輸入和輸出序列之間的依賴關係。該模型被廣泛應用於機器翻譯、音訊轉錄、語言生成等多個自然語言處理領域。

Transformer基於attention機制來實現序列到序列的學習。 在RNN(迴圈神經網路)中,網路必須按順序遍歷每個單詞,並在每個時間步計算隱層表示。 這樣,在長段文字中,資訊可能會從網路的起點傳遞到終點,這導致了難以捕捉遠距離依賴關係的問題。而attention機制可以根據輸入序列中的詞與其它所有詞的相關性分配不同的權重,從而突破了序列到序列中的侷限。

具體來說,一個Transformer模型由編碼器(encoder)和解碼器(decoder)兩部分組成。編碼器用於接收輸入序列,解碼器用於生成輸出序列。每個編碼器和解碼器均包含多頭attention機制、前饋網路以及殘差連線等元件。

在一個典型的Transformer模型中,首先將輸入序列通過嵌入層進行向量化,然後將向量表示作為Transformer的第一層輸入。處理完輸入向量之後,下一層就是多頭attention層,其中每個頭(head)都可以計算出不同的注意力權重向量(也稱為attention mask)。最後,利用殘差連線和skip connection機制使transformer更易於訓練。

資料集準備

在此任務中,我們將使用來自IMDB的電影評論資料集,該資料集包含50,000條有標籤的電影評論,每個評論標記為正面或負面情感。 其中25,000個用於訓練,另外25,000個用於測試。

由於Transformer是對token進行操作,所以我們需要對文字的每個單詞進行編碼。一種常用的方法是使用Bert Tokenizer。GPT-2等預訓練模型會使用特定的tokenizer。選擇最新版本的transformers包可以快速實現這些操作:

!pip install transformers

接著載入tokenizer:

from transformers import BertTokenizer
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')

上述操作將下載並載入適用於bert的tokenizer。 下一步是讀取IMDB資料集的內容。 在本文中,我們將使用此處的已處理好的CSV形式資料:drive.google.com/file/d/1b_b…

import pandas as pd
train_df = pd.read_csv('imdb_train.csv')
test_df = pd.read_csv('imdb_test.csv')

由於Transformer模型需要固定長度的輸入序列,我們選擇了max_length為100並對所有評論進行padding操作:

train_inputs = tokenizer(list(train_df['review']), padding=True, truncation=True, max_length=100)
test_inputs = tokenizer(list(test_df['review']), padding=True, truncation=True, max_length=100)

現在我們可以將輸入和標籤分別轉換成torch Tensor型別:

import torch
train_labels = torch.tensor(list(train_df['sentiment'].replace({'pos': 1, 'neg':0})))
test_labels = torch.tensor(list(test_df['sentiment'].replace({'pos': 1, 'neg':0})))

train_encoded_dict = {
    'input_ids': torch.tensor(train_inputs['input_ids']),
    'token_type_ids': torch.tensor(train_inputs['token_type_ids']),
    'attention_mask': torch.tensor(train_inputs['attention_mask']),
    'labels': train_labels
}

test_encoded_dict = {
    'input_ids': torch.tensor(test_inputs['input_ids']),
    'token_type_ids': torch.tensor(test_inputs['token_type_ids']),
    'attention_mask': torch.tensor(test_inputs['attention_mask']),
    'labels': test_labels
}

模型訓練

在此任務中,我們將使用PyTorch庫實現Transformer模型。 PyTorch是一種基於Python的科學計算包,其靈活性和易用性使其成為深度學習領域最常用的庫之一。

可以使用Hugging Face的Transformers實現預先訓練好的BERT模型:

from transformers import BertForSequenceClassification, AdamW, BertConfig
model = BertForSequenceClassification.from_pretrained(
    "bert-base-uncased",
    num_labels = 2,
    output_attentions = False,
    output_hidden_states = False,
)

然後,我們需要定義優化器、損失函數和批大小等訓練超引數:

optimizer = AdamW(model.parameters(), lr = 2e-5, eps = 1e-8)

from torch.utils.data import DataLoader, RandomSampler, SequentialSampler
batch_size = 32
train_dataloader = DataLoader(train_encoded_dict, sampler = RandomSampler(train_encoded_dict), batch_size = batch_size)
test_dataloader = DataLoader(test_encoded_dict, sampler = SequentialSampler(test_encoded_dict), batch_size = batch_size)

from transformers import get_linear_schedule_with_warmup
epochs = 4
total_steps = len(train_dataloader) * epochs
scheduler = get_linear_schedule_with_warmup(optimizer, num_warmup_steps = 0, num_training_steps = total_steps)
loss_fn = torch.nn.CrossEntropyLoss()

最後,我們可以定義模型的訓練過程,並進行模型訓練:

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)
model.train()

total_train_loss = 0
for epoch_i in range(epochs):
    print(f"{'':^5}Epoch:{epoch_i + 1:^3}")
    for step, batch in enumerate(train_dataloader):
        b_input_ids = batch['input_ids'].to(device)
        b_token_type_ids = batch['token_type_ids'].to(device)
        b_attention_mask = batch['attention_mask'].to(device)
        b_labels = batch['labels'].to(device)

        model.zero_grad()

        outputs = model(b_input_ids,
                        token_type_ids=b_token_type_ids, 
                        attention_mask=b_attention_mask, 
                        labels=b_labels)
        
        loss = outputs.loss
        total_train_loss += loss.item()
    
        loss.backward()

        torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)

        optimizer.step()

        scheduler.step()

    avg_train_loss = total_train_loss / len(train_dataloader)            
    print("   Average training loss: {avg_train_loss:.2f}")

def evaluate(model, test_dataloader):
    model.eval()

    total_eval_accuracy = 0
    total_eval_loss = 0
    nb_eval_steps = 0

    for batch in test_dataloader:
        b_input_ids = batch['input_ids'].to(device)
        b_token_type_ids = batch['token_type_ids'].to(device)
        b_attention_mask = batch['attention_mask'].to(device)
        b_labels = batch['labels'].to(device)

        with torch.no_grad():       
            outputs = model(b_input_ids, 
                            token_type_ids=b_token_type_ids, 
                            attention_mask=b_attention_mask,
                            labels=b_labels)
        loss = outputs.loss
        logits = outputs.logits

        total_eval_loss += loss.item()
        logits = logits.detach().cpu().numpy()
        label_ids = b_labels.to('cpu').numpy()
        total_eval_accuracy += flat_accuracy(logits, label_ids)

    avg_val_accuracy = total_eval_accuracy / len(test_dataloader)
    avg_val_loss = total_eval_loss / len(test_dataloader)

    return avg_val_accuracy, avg_val_loss

accuracy, val_loss = evaluate(model, test_dataloader)
print(f'Accuracy: {accuracy:.2f}%')

訓練結束後,我們可以使用測試集對模型進行評估。TensorFlow提供了非常好的評估函數可以在別人的工程稍微改下直接拿來用:

from sklearn.metrics import accuracy_score
def flat_accuracy(preds, labels):
    pred_flat = np.argmax(preds, axis=1).flatten()
    labels_flat = labels.flatten()
    return accuracy_score(labels_flat, pred_flat)

模型調整和優化

下面是一些可能有助於Transformer模型效能的調整和優化方法。

(1)最大輸入序列長度: Transformer模型需要固定大小的輸入序列。在IMDB任務中,我們將max_length設定為100。調整這個引數會影響到模型的效能,長時間耗時與視訊記憶體限制等都會影響選擇。

(2)學習率、批大小、迭代次數等訓練超引數的調整: 常用策略包括指數衰減學習率、增加批次大小、增加迭代次數等。

(3)使用預訓練模型:隨著語言模型的發展,預訓練語言模型在各種NLP任務中表現越來越好。因此,在這類任務中,可以通過使用預訓練的模型來提高準確性。適合使用這個方法的資料集規模越大,效果越明顯。

(4) 模型融合或整合: 許多競賽中,採用模型平均等方式提高模型的完整性和穩健性。在結果更重要的大賽中尤為突出。

總結

首先簡要介紹了Transformer的基本結構和工作原理,並解釋了為什麼它適合於序列到序列的學習問題。然後,我們演示瞭如何獲取IMDB電影評論資料,對其進行標記化處理,並將資料轉換為Tensor型別。最後,我們介紹瞭如何使用BertForSequenceClassification載入預處理的去停詞csv資料,及PyTorch庫定義優化器、損失函數和批大小等訓練超引數來執行模型訓練和評估。

以上就是詳解基於Transformer實現電影評論星級分類任務的詳細內容,更多關於Transformer電影評論星級分類的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com