前面講了這麼多有的沒的,想必還是得來實作一下大家比較知道怎麼用吧~今天就會帶大家來使用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
我們的主要目的為:訓練一個 BERT 分類模型,輸入是一句話,辨識出這句話的情緒傾向。
首先是資料集的處理
- 安裝 huggingface 的 dataset 套件(可以直接透過 pip 安裝是不是很方便)
!pip install datasets
- 載入資料
from datasets import load_dataset
dataset = load_dataset("imdb") # 本次所使用的是情緒分析中常見的IMDB資料集
- 查看資料
dataset
- 檢查資料
有發現文本其實還含有 HTML 中的換行符號(<br/>)嗎?你可以自行決定要不要處理(今天的重點不是這個,所以我們這邊先跳過)。但通常如果是自己從網路上爬蟲蒐集來的文本是需要做資料清洗的~
dataset['train'][0]
- 切分資料集
結合 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)
將資料合併後,將其轉為 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~
如果喜歡這一系列文章,別忘了留下掌聲 👏,後續可以追蹤作者查看更多系列文章喔~