返回文章列表

PyTorch文字分類別詞嵌入與Torchtext應用

本文介紹如何使用 PyTorch 和 Torchtext 構建文字分類別模型,以推文情感分析為例,涵蓋詞嵌入、資料預處理、模型訓練和評估等關鍵步驟,並探討了資料增強技術的應用,包括隨機插入、刪除、交換和回譯等方法,以提升模型效能和泛化能力。

深度學習 自然語言處理

深度學習技術已廣泛應用於自然語言處理領域,其中文字分類別是重要的應用之一。本文將以推文情感分析為例,示範如何利用 PyTorch 和 Torchtext 這個方便的函式庫來構建文字分類別模型。我們會逐步介紹資料預處理、詞嵌入的應用、模型的建立與訓練,以及如何使用訓練好的模型進行推文情感分類別。此外,我們還會探討一些常見的資料增強技術,例如隨機插入、刪除、交換和回譯,以及如何在 PyTorch 中應用這些技術來提升模型的效能。透過這些技術,我們可以有效地擴充訓練資料,提升模型的泛化能力,使其在面對未見資料時表現更佳。

使用 PyTorch 進行文字分類別:詞嵌入與 Torchtext

在深度學習的自然語言處理(NLP)領域中,文字分類別是一項重要的任務。PyTorch 提供了一個強大的函式庫 torchtext,用於處理文字資料的預處理和載入。在本章中,我們將探討如何使用 PyTorch 和 torchtext 來建立一個情感分析模型。

詞嵌入(Word Embeddings)

詞嵌入是一種將單詞表示為向量空間中的向量的方法。這種表示方法能夠捕捉單詞之間的語義關係。一個著名的詞嵌入例子是 word2vec,它由 Google 在 2013 年發布。Word2vec 使用淺層神經網路訓練詞向量,從而揭示了詞向量似乎捕捉到了單詞背後的概念。

在 PyTorch 中,使用詞嵌入非常簡單:

embed = nn.Embedding(vocab_size, dimension_size)

這將建立一個大小為 vocab_size x dimension_size 的張量,每個單詞在詞彙表中對應一個 dimension_size 維的向量。

內容解密:

  1. nn.Embedding 是 PyTorch 中的一個模組,用於建立詞嵌入層。
  2. vocab_size 是詞彙表的大小,即資料集中不同單詞的數量。
  3. dimension_size 是每個單詞向量的維度。

Torchtext 簡介

Torchtext 是 PyTorch 的官方函式庫,用於處理文字資料的預處理和載入。雖然它不如 torchvision 那樣成熟,但仍然是一個強大的工具,可以幫助我們處理文字資料。

安裝 torchtext 可以使用 pip 或 conda:

pip install torchtext

conda install -c derickl torchtext

我們還需要安裝 spaCy(一款 NLP 函式庫)和 pandas(用於資料處理)。

取得資料:推文情感分析

在本文中,我們將建立一個情感分析模型,使用 Sentiment140 資料集。該資料集包含來自 Twitter 的推文,每條推文都被標記為 0(負面)、2(中立)或 4(正面)。

下載資料集並解壓縮後,我們可以使用 pandas 載入資料:

import pandas as pd
tweetsDF = pd.read_csv("training.1600000.processed.noemoticon.csv", engine="python", header=None)

內容解密:

  1. pd.read_csv 用於載入 CSV 檔案。
  2. engine="python" 指定使用 Python 引擎解析 CSV 檔案,因為預設的 C 引擎可能無法正確處理某些 Unicode 字元。

資料預處理

檢視資料的前五行:

>>> tweetsDF.head(5)

我們發現資料集沒有標題行,但透過檢視網站和憑直覺,我們可以確定最後一列是推文文字,第一列是標籤。

內容解密:

  1. tweetsDF.head(5) 用於顯示資料的前五行。
  2. 我們需要根據資料的結構進行相應的處理。

定義欄位(Fields)

Torchtext 提供了一種直接的方法來生成資料集:定義欄位(Fields)。欄位類別有多個引數,可以用於控制資料的預處理。

內容解密:

  1. 欄位(Fields)用於指定如何處理資料中的不同欄位。
  2. Field 類別有多個引數,例如 sequentialuse_vocabinit_token,可以用於控制資料的預處理。

使用 Torchtext 處理文字資料

在進行文字分類別任務時,資料的預處理是非常重要的一步。Torchtext 是 PyTorch 中用於處理文字資料的函式庫,提供了一系列工具來簡化資料的載入、預處理和批次化。

定義欄位

首先,我們需要定義資料中的欄位。Torchtext 中的 Field 物件用於指定如何處理資料中的每個欄位。

from torchtext import data

LABEL = data.LabelField()
TWEET = data.Field(tokenize='spacy', lower=True)

在這裡,我們定義了兩個欄位:LABELTWEETLABEL 是一個 LabelField,用於表示分類別標籤;TWEET 是一個 Field,用於表示文字資料,並指定使用 spaCy 進行分詞和轉換為小寫。

內容解密:

  1. data.LabelField():建立一個標籤欄位,用於分類別任務。
  2. data.Field(tokenize='spacy', lower=True):建立一個文字欄位,使用 spaCy 分詞並轉為小寫。

定義資料集

接下來,我們需要將欄位對映到 CSV 檔案中的列。

fields = [('score', None), ('id', None), ('date', None), ('query', None),
          ('name', None), ('tweet', TWEET), ('category', None), ('label', LABEL)]

這裡,我們定義了一個列表 fields,其中每個元素都是一個 tuple,包含欄位名稱和對應的 Field 物件。如果某個欄位不需要被處理,則對應的 Field 物件設為 None

內容解密:

  1. 將 CSV 中的欄位對映到對應的 Field 物件。
  2. 將不需要處理的欄位設為 None

載入資料集

使用 TabularDataset 載入 CSV 檔案。

twitterDataset = torchtext.data.TabularDataset(
    path="training-processed.csv",
    format="CSV",
    fields=fields,
    skip_header=False)

內容解密:

  1. path:指定 CSV 檔案的路徑。
  2. format:指設定檔案格式為 CSV。
  3. fields:指定欄位對映。
  4. skip_header:指定是否跳過檔案頭。

分割資料集

將資料集分割為訓練集、測試集和驗證集。

(train, test, valid) = twitterDataset.split(split_ratio=[0.8, 0.1, 0.1])

內容解密:

  1. 使用 split 方法分割資料集。
  2. split_ratio:指定分割比例。

建立詞彙表

建立詞彙表並限制詞彙表大小。

vocab_size = 20000
TWEET.build_vocab(train, max_size=vocab_size)

內容解密:

  1. build_vocab:根據訓練集建立詞彙表。
  2. max_size:限制詞彙表大小。

建立資料迭代器

建立資料迭代器用於訓練模型。

train_iterator, valid_iterator, test_iterator = data.BucketIterator.splits(
    (train, valid, test),
    batch_size=32,
    device=device)

內容解密:

  1. BucketIterator.splits:建立多個資料迭代器。
  2. batch_size:指定批次大小。
  3. device:指定運算裝置。

深度學習在文字分類別中的應用:以推文情感分析為例

在深度學習的領域中,文字分類別是一項重要的任務,尤其是在社交媒體監控、市場研究和客戶服務等領域。本篇文章將介紹如何使用PyTorch和torchtext函式庫來建立一個簡單的文字分類別模型,以對推文進行情感分析。

資料處理

首先,我們需要處理資料。我們使用torchtext函式庫中的TabularDataset類別來載入和預處理資料。

import torch
from torchtext import data
from torchtext import datasets

# 設定裝置(GPU或CPU)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

# 定義資料欄位
fields = [('tweet', TWEET), ('label', LABEL)]

# 載入資料集
twitterDataset = data.TabularDataset(
    path='path_to_your_dataset.csv',
    format='CSV',
    fields=fields,
    skip_header=False
)

# 分割資料集為訓練集、測試集和驗證集
(train, test, valid) = twitterDataset.split(split_ratio=[0.8, 0.1, 0.1])

# 建立詞彙表
vocab_size = 20002
TWEET.build_vocab(train, max_size=vocab_size)

# 建立迭代器
train_iterator, valid_iterator, test_iterator = data.BucketIterator.splits(
    (train, valid, test),
    batch_size=32,
    device=device
)

內容解密:

  1. 資料載入與分割:使用TabularDataset載入CSV格式的資料集,並將其分割為訓練集、測試集和驗證集。
  2. 詞彙表建立:使用build_vocab方法建立詞彙表,將文字資料轉換為數值表示。
  3. 迭代器建立:使用BucketIterator建立迭代器,以便於批次處理資料。

建立模型

接下來,我們需要建立一個簡單的文字分類別模型。我們使用PyTorch中的nn.Module類別來定義模型。

import torch.nn as nn

class OurFirstLSTM(nn.Module):
    def __init__(self, hidden_size, embedding_dim, vocab_size):
        super(OurFirstLSTM, self).__init__()
        self.embedding = nn.Embedding(vocab_size, embedding_dim)
        self.encoder = nn.LSTM(input_size=embedding_dim, hidden_size=hidden_size, num_layers=1)
        self.predictor = nn.Linear(hidden_size, 2)

    def forward(self, seq):
        output, (hidden, _) = self.encoder(self.embedding(seq))
        preds = self.predictor(hidden.squeeze(0))
        return preds

model = OurFirstLSTM(100, 300, 20002)
model.to(device)

內容解密:

  1. 嵌入層:使用nn.Embedding將輸入的文字資料轉換為向量表示。
  2. LSTM層:使用nn.LSTM對向量表示進行序列建模。
  3. 預測層:使用nn.Linear將LSTM的輸出轉換為預測結果。

訓練模型

import torch.optim as optim

# 定義最佳化器和損失函式
optimizer = optim.Adam(model.parameters(), lr=2e-2)
criterion = nn.CrossEntropyLoss()

def train(epochs, model, optimizer, criterion, train_iterator, valid_iterator):
    for epoch in range(1, epochs + 1):
        training_loss = 0.0
        valid_loss = 0.0
        model.train()
        for batch_idx, batch in enumerate(train_iterator):
            optimizer.zero_grad()
            predict = model(batch.tweet)
            loss = criterion(predict, batch.label)
            loss.backward()
            optimizer.step()
            training_loss += loss.data.item() * batch.tweet.size(0)
        training_loss /= len(train_iterator)
        model.eval()
        for batch_idx, batch in enumerate(valid_iterator):
            predict = model(batch.tweet)
            loss = criterion(predict, batch.label)
            valid_loss += loss.data.item() * batch.tweet.size(0)
        valid_loss /= len(valid_iterator)
        print('Epoch: {}, Training Loss: {:.2f}, Validation Loss: {:.2f}'.format(epoch, training_loss, valid_loss))

內容解密:

  1. 最佳化器和損失函式定義:使用Adam最佳化器和交叉熵損失函式。
  2. 訓練迴圈:在訓練集中進行前向傳播、計算損失、反向傳播和引數更新。
  3. 驗證集評估:在驗證集中評估模型的效能。

分類別推文

def classify_tweet(tweet):
    categories = {0: "Negative", 1: "Positive"}
    processed = TWEET.process([TWEET.preprocess(tweet)])
    return categories[model(processed).argmax().item()]

內容解密:

  1. 推文預處理:使用preprocess方法對推文進行預處理。
  2. 模型預測:使用訓練好的模型對預處理後的推文進行預測。
  3. 類別對映:將預測結果對映到對應的類別標籤。

資料增強技術在文字分類別中的應用

在處理文字分類別任務時,資料增強(Data Augmentation)是一種常見且有效的技術,能夠提升模型的效能和泛化能力。本篇文章將探討幾種常見的文字資料增強技術,包括隨機插入、隨機刪除、隨機交換和回譯等方法。

隨機插入

隨機插入技術會檢視一個句子,然後隨機插入現有非停止詞(non-stop-words)的同義詞到句子中 n 次。假設我們有辦法取得一個詞的同義詞和消除停止詞(如 “and”、“it”、“the” 等),以下是一個簡單的實作:

def random_insertion(sentence, n):
    words = remove_stopwords(sentence)
    for _ in range(n):
        new_synonym = get_synonyms(random.choice(words))
        sentence.insert(randrange(len(sentence)+1), new_synonym)
    return sentence

內容解密:

  1. remove_stopwords(sentence):移除句子中的停止詞,傳回一個詞列表。
  2. get_synonyms(random.choice(words)):從現有的詞中隨機選擇一個,並取得其同義詞。
  3. sentence.insert(randrange(len(sentence)+1), new_synonym):將取得的同義詞隨機插入到句子中的某個位置。

舉例來說,原句 “The cat sat on the mat” 可能會變成 “The cat mat sat on feline the mat”,其中 “feline” 是 “cat” 的同義詞。

隨機刪除

隨機刪除技術根據給定的機率引數 p,遍歷句子並決定是否刪除某個詞。

def random_deletion(words, p=0.5):
    if len(words) == 1:
        return words
    remaining = list(filter(lambda x: random.uniform(0,1) > p, words))
    if len(remaining) == 0:
        return [random.choice(words)]
    else:
        return remaining

內容解密:

  1. 如果句子中只有一個詞,則直接傳回該詞。
  2. filter(lambda x: random.uniform(0,1) > p, words):根據機率 p 過濾詞,保留那些隨機數大於 p 的詞。
  3. 如果過濾後沒有詞剩下,則隨機傳回原句子中的一個詞。

隨機交換

隨機交換技術會對句子中的詞進行 n 次隨機交換。

def random_swap(sentence, n=5):
    length = range(len(sentence))
    for _ in range(n):
        idx1, idx2 = random.sample(length, 2)
        sentence[idx1], sentence[idx2] = sentence[idx2], sentence[idx1]
    return sentence

內容解密:

  1. random.sample(length, 2):從句子長度範圍內隨機選取兩個不同的索引。
  2. sentence[idx1], sentence[idx2] = sentence[idx2], sentence[idx1]:交換這兩個索引對應的詞。

回譯

回譯(Back Translation)是另一種流行的資料增強方法。它涉及將句子從目標語言翻譯成一種或多種其他語言,然後再翻譯回原來的語言。可以使用 Python 函式庫 googletrans 來實作。

import googletrans
from googletrans import Translator

translator = Translator()
sentences = ['The cat sat on the mat']
translation_fr = translator.translate(sentences, dest='fr')
fr_text = [t.text for t in translation_fr]
translation_en = translator.translate(fr_text, dest='en')
en_text = [t.text for t in translation_en]
print(en_text)

內容解密:

  1. 將句子從英文翻譯成法文。
  2. 再將法文翻譯回英文,從而得到增強的句子。

為了進一步增強,可以隨機選擇一種語言進行翻譯:

available_langs = list(googletrans.LANGUAGES.keys())
tr_lang = random.choice(available_langs)
translations = translator.translate(sentences, dest=tr_lang)
t_text = [t.text for t in translations]
translations_en_random = translator.translate(t_text, src=tr_lang, dest='en')
en_text = [t.text for t in translations_en_random]

內容解密:

  1. 隨機選擇一種語言進行翻譯。
  2. 將句子翻譯成該語言,然後再翻譯回英文。

資料增強與 torchtext

目前為止討論的資料增強技術並未直接涉及 torchtext。由於 torchtext 不提供像 torchvisiontorchaudio 那樣的轉換管道,因此建議在 PyTorch 外部進行資料增強,然後將增強的資料輸入模型。