NLP 實戰教學 -BERT 情緒分析(上)

HsiuChun
7 min readOct 7, 2023

--

前面講了這麼多有的沒的,想必還是得來實作一下大家比較知道怎麼用吧~今天就會帶大家來使用BERT來做影評的情緒分析!透過 huggingface 提供的平台,我們可以輕易取得許多已經預訓練好的模型權重,主要會使用 PyTorch 去實作!不會安裝的朋友可以先在 colab 上實作喔~~

本次所使用的資料集為 Learning Word Vectors for Sentiment Analysis.

程式碼參考自: huggingface

資料集說明 (imdb)

Large Movie Review Dataset. This is a dataset for binary sentiment classification containing substantially more data than previous benchmark datasets. We provide a set of 25,000 highly polar movie reviews for training and 25,000 for testing. There is additional unlabeled data for use at all.

本次主要使用的模型為 BERT

BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding

圖1.BERT架構示意圖(BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding)

可搭配李宏毅大大的影片學習

我們的主要目的為:訓練一個 BERT 分類模型,輸入是一句話,辨識出這句話的情緒傾向。

首先是資料集的處理

  • 安裝 huggingface 的 dataset 套件(可以直接透過 pip 安裝是不是很方便)
!pip install datasets
  • 載入資料
from datasets import load_dataset

dataset = load_dataset("imdb") # 本次所使用的是情緒分析中常見的IMDB資料集
  • 查看資料
dataset
圖2.資料集示意圖
  • 檢查資料 有發現文本其實還含有 HTML 中的換行符號(<br/>)嗎?你可以自行決定要不要處理(今天的重點不是這個,所以我們這邊先跳過)。但通常如果是自己從網路上爬蟲蒐集來的文本是需要做資料清洗的~
dataset['train'][0]
圖3.文本示意圖
  • 切分資料集

結合 huggingface 上 imdb 的介紹 及圖 2,我們可以發現 unsupervised 的資料是沒有正負向標籤的,因此本次只採用 train 與 test 資料。

在這步驟,我們需要將原資料重新進行分割。將 train 與 test 資料合併後切割成 3:1:1 或是 8:1:1 的一組新的 train/val/test 資料集。

作者於此處將資料合併重切,是為了得到驗證集和增加訓練筆數。當然也可以直接從測試集直接 sample 驗證集,每個人的作法不一定相同~但若要與其他模型比較,需採用一致的測試集。

import pandas as pd

all_data = [] # a list to save all data

for data in dataset['train']:
all_data.append({'text':data['text'], 'label':data['label']})
for data in dataset['test']:
all_data.append({'text':data['text'], 'label':data['label']})

all_df = pd.DataFrame(all_data, columns=['text', 'label'])
all_df.head(5)
圖4.DataFrame 示意圖

將資料合併後,將其轉為 DataFrame。在這裡,我們可以先小小的檢查一下資料是否有類別不平衡的狀況~可以發現兩個類別的占比皆為 0.5,所以沒有類別不平衡的問題。

all_df.label.value_counts() / len(all_df)
'''[Output]
0 0.5
1 0.5
Name: label, dtype: float64
'''

那就可以開切啦!我們使用 sklearn 的套件直接幫我們切,詳細參數設定可以查看 train_test_split。因為 train_test_split 一次切一刀,但我們總共三份,得切兩刀,所以要分兩次切(要自己算好怎麼切喔)由於文本內可能含有逗號,為避免 csv 檔案在使用時有切分上的失誤,所以將副檔名改為 tsv 並採用 tab 分隔。

# 使用 sklearn 的套件直接幫我們切(如果還未安裝 sklearn 的話,在命令列執行 "!pip install sklearn" 即可)
from sklearn.model_selection import train_test_split

# random_state 是固定資料 random 的結果,才不會每次切出來的資料集不一樣喔~
# train_size:指定 output 中前者資料數量占比
train_df, temp_data = train_test_split(all_df, random_state=parameters['seed'], train_size=0.8)
val_df, test_df = train_test_split(temp_data, random_state=parameters['seed'], train_size=0.5)
print('# of train_df:', len(train_df))
print('# of val_df:', len(val_df))
print('# of test_df data:', len(test_df))

# save data
# 這裡指定sep='\t',且不儲存DataFrame前面的index
train_df.to_csv('./train.tsv', sep='\t', index=False)
dev_df.to_csv('./val.tsv', sep='\t', index=False)
test_df.to_csv('./test.tsv', sep='\t', index=False)
  • 建立 Dataset 與 Dataloader

接下來會是 pytorch 中比較特別的地方了!你可能會很好奇說,資料做完了之後,要怎麼丟給模型呢?這邊教給大家的會是比較基礎的寫法,但一通百通XD

既然我們是做 NLP 任務,那 transformers 肯定是必不可少的阿!我們下節接續介紹 transformers~

如果喜歡這一系列文章,別忘了留下掌聲 👏,後續可以追蹤作者查看更多系列文章喔

參考資源

--

--