日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

BERT实战(1):使用DistilBERT作为词嵌入进行文本情感分类,与其它词向量(FastText,Word2vec,Glove)进行对比

發布時間:2023/12/14 编程问答 74 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BERT实战(1):使用DistilBERT作为词嵌入进行文本情感分类,与其它词向量(FastText,Word2vec,Glove)进行对比 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

這次根據一篇教程Jay Alammar: A Visual Guide to Using BERT for the First Time學習下如何在Pytorch框架下使用BERT。

主要參考了中文翻譯版本

教程提供了可用的代碼,可以在colab或者github獲取。

1. huggingface/transformers

Transformers提供了數千個預訓練的模型來執行文本任務,如100多種語言的分類、信息提取、問答、摘要、翻譯、文本生成等。

文檔:https://huggingface.co/transformers/
模型:https://huggingface.co/models

huggingface團隊用pytorch復現許多模型,本次要使用它們提出的DistilBERT模型。

2. 數據集

本次使用的數據集是 SST2,是一個電影評論的數據集。用標簽 0/1 代表情感正負。

3. 模型


句子的情感分類模型由兩部分組成:

  • DistilBERT處理輸入的句子,并將它從句子中提取的一些信息傳遞給下一個模型。 DistilBERT 是一個更小版本的 BERT 模型,是由 HuggingFace 團隊開源的。它保留了 BERT 能力的同時,比 BERT 更小更快。
  • 一個基本的 Logistic Regression 模型,它將處理 DistilBERT 的輸出結果并且將句子進行分類,輸出0或1。

在這兩個模型之間傳遞的數據是一個 768 維的向量。
假設句子長度為n,那及一個句子經過BERT應該得到n個768 維的向量。

實際上只使用[CLS]位置的向量看作是我們用來分類的句子的embedding向量。

4. 訓練與預測

4.1 訓練

雖然我們使用了兩個模型,但是只需要訓練回歸模型(Logistic Regression)即可。
對于 DistilBERT 模型,使用該模型預訓練的參數即可,這個模型沒有被用來做句子分類任務的訓練和微調。
使用 Scikit Learn 工具包進行操作。將整個BERT輸出的數據分成 train/test 數據集。

將75%的數據劃為訓練集,將25%的數據劃分為測試集。
sklearn的train/test split在進行分割之前會對示例進行shuffles。
接下來就用機器學習的方法訓練回歸模型就行了。

4.2 預測

如何使用模型進行預測呢?
比如,我們要對句子 “a visually stunning rumination on love” 進行分類
第一步,用 BERT 的分詞器(tokenizer)將句子分成 tokens;
第二步,添加特殊的 tokens 用于句子分類任務(在句子開頭加上 [CLS],在句子結尾加上 [SEP]);
第三步,分詞器(tokenizer)會將每個 token 替換成 embedding 表中的ID,embedding 表是我們預訓練模型自帶的;

下面這一行代碼就完成了上述3步。

tokenizer.encode("a visually stunning rumination on love", add_special_tokens=True)

每個token的輸出都是一個一個768維的向量。

由于這是一個句子分類任務,我們只取第一個向量(與 [CLS] token有關的向量)而忽略其他的 token 向量。
將該向量作為 邏輯回歸的輸入。

5. 代碼(加入圖片注釋)

環境的配置就不細說了,可以在transformers的github頁面查閱

5.1 導入所需的工具包

import numpy as np import pandas as pd from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression from sklearn.model_selection import GridSearchCV from sklearn.model_selection import cross_val_score import torch import transformers as ppb import warnings warnings.filterwarnings('ignore')

5.2 導入數據集

數據集的鏈接,這里我已經提前下載到本地了。

df = pd.read_csv('./train.tsv', delimiter='\t', header=None) # 為做示例只取前2000條數據 batch_1 = df[:2000] # 查看正負例的數量 batch_1[1].value_counts()

5.3 導入預訓練模型

下載大概花費了40s

# For DistilBERT: model_class, tokenizer_class, pretrained_weights = (ppb.DistilBertModel, ppb.DistilBertTokenizer, 'distilbert-base-uncased')## Want BERT instead of distilBERT? Uncomment the following line: #model_class, tokenizer_class, pretrained_weights = (ppb.BertModel, ppb.BertTokenizer, 'bert-base-uncased')# Load pretrained model/tokenizer tokenizer = tokenizer_class.from_pretrained(pretrained_weights) model = model_class.from_pretrained(pretrained_weights)

5.4 數據預處理

包括token化和padding
token化的過程與4.2中圖片相同

tokenized = batch_1[0].apply((lambda x:tokenizer.encode(x, add_special_tokens = True)))


需要把所有的向量用 id 0 來填充較短的句子到一個相同的長度。

max_len = 0 for i in tokenized.values:if len(i) > max_len:max_len = len(i) padded = np.array([i + [0] * (max_len - len(i)) for i in tokenized.values]) np.array(padded).shape # Masking # attention_mask(也就是input_mask)的0值只作用在padding部分 # np.where(condition, x, y) 滿足條件(condition),輸出x,不滿足輸出y attention_mask = np.where(padded != 0, 1, 0) attention_mask.shape

padding的過程如下圖所示,值得注意的是,如果我們直接把padded發給BERT,那會讓它有點混亂。我們需要創建另一個變量,告訴它在處理輸入時忽略(屏蔽)我們添加的填充。這就是attention_mask:

5.5 使用BERT

# 基本可以看作又進行了一次embedding input_ids = torch.LongTensor(padded) attention_mask = torch.tensor(attention_mask)with torch.no_grad():last_hidden_states = model(input_ids, attention_mask=attention_mask)# BERT模型輸出的張量尺寸為[2000, 59, 768] # 取出[CLS]token對應的向量 features = last_hidden_states[0][:,0,:].numpy() labels = batch_1[1] # 取出標簽


5.5 訓練一個Logistic回歸模型

# 劃分訓練集和測試集 train_features, test_features, train_labels, test_labels = train_test_split(features, labels) # 搜索正則化強度的C參數的最佳值。 parameters = {'C': np.linspace(0.0001, 100, 20)} grid_search = GridSearchCV(LogisticRegression(), parameters) grid_search.fit(train_features, train_labels)print('best parameters: ', grid_search.best_params_) print('best scrores: ', grid_search.best_score_)lr_clf = LogisticRegression(C = 10.526405263157894) lr_clf.fit(train_features, train_labels) lr_clf.score(test_features, test_labels)


在使用完整數據集的時候,預測的準確率約為0.847。

6.結果評估

from sklearn.dummy import DummyClassifier clf = DummyClassifier()scores = cross_val_score(clf, train_features, train_labels) print("Dummy classifier score: %0.3f (+/- %0.2f)" % (scores.mean(), scores.std() * 2))

可以發現訓練出的分類器的結果明顯好于隨即預測的結果。
但這個例子恐怕完全沒有體現出BERT的性能,因為缺少了fine-tuning階段。根據19年的教程,該數據集上最高的準確率是 96.8。

通過fine-tuning 更新 BERT 的參數權重, 可以提升DistilBERT 模型在句子分類任務(稱為下游任務)上得到的分數。原教程中表示,通過對 DistilBERT 進行 fine-tuned 之后達到了 91.3 的準確率(模型見huggingface官網),全參數量的 BERT 模型能達到 92.7 的分數。

訓練參數如下圖所示:

接下來我們將數據集按照8:1:1切分為訓練集,驗證集和測試集。
通過在訓練集上的微調,模型在測試集上的準確度為0.8876,可能因為參數設置問題,沒有達到原文中的效果。

代碼見我的GitHub倉庫:Comparison-of-Word-Vectors

7. 與常規的詞向量對比

很多工作表明使用句子中所有詞匯的Glove向量平均,比直接使用不經fine-tune的BERT [CLS]嵌入表現得更好。 為了驗證這個觀點,在數據集SST2上分別使用fastText,word2vec, Glove做詞嵌入,再訓練分類器,比較它們與BERT的效果。
代碼見我的GitHub倉庫:Comparison-of-Word-Vectors

7.1 fastText

fastText是Facebook于2016年開源的一個詞向量計算和文本分類工具,在文本分類任務中,fastText(淺層網絡)往往能取得和深度網絡相媲美的精度,卻在訓練時間上比深度網絡快許多數量級。在標準的多核CPU上, 能夠訓練10億詞級別語料庫的詞向量在10分鐘之內,能夠在1分鐘之內分類有著30萬多類別的50多萬句子。

  • fastText在輸入時對每個詞加入了n-gram特征,在輸出時使用分層softmax加速訓練。
  • fastText將整篇文章的詞向量求平均作為輸入得到文檔向量,用文本分類做有監督訓練,對輸出進行softmax回歸,詞向量為副產品。
  • fastText也可以無監督訓練詞向量,與CBOW非常相似。

fastText論文地址
fastText的github地址
使用fasttext預訓練的英文詞向量下載地址

這里我們使用的預訓練詞向量是上圖中的1。

結果如下:

條件準確度
直接使用預訓練的fasttext詞向量0.7951
使用預訓練的fasttext詞向量并用訓練集微調0.7847
只使用訓練集訓練0.7899

總體來說,效果比不進行微調的BERT差了不少,但是我們選用的fasttext詞向量維數為300,比DistilBERT產生的768維的詞向量小了不少。

參考資料:
https://blog.csdn.net/ymaini/article/details/81489599
https://blog.csdn.net/sinat_26917383/article/details/83041424

7.2 word2vec

使用word2vec預訓練的英文詞向量下載地址
word2vec說明文檔
gensim文檔
關于word2vec的原理,可見我的這篇博客:NLP方向組會內容整理(1)詞向量

結果如下:

條件準確度
直接使用google提供預訓練的word2vec詞向量0.7917
只使用訓練集訓練0.6685

可以發現,使用預訓練詞向量的準確度和fasttext相差無幾。同時,由于word2vec不具備fasttext的識別OOV詞的能力,在較少數據集上訓練出的詞向量效果不佳。

筆者未能實現在預訓練詞向量的基礎上使用訓練集繼續訓練,根據gensim3.8的文檔,Google提供的預訓練詞向量,只能以KeyedVectors形式讀取,不支持繼續訓練,只有完整的word2vec模型(model.word2vec.Word2Vec)才能繼續訓練。

7.3 Glove

Glove將Word2Vec原本預測一個詞和它的語境是否會共現的任務,升級成預測兩個詞之間的共現頻率大小的問題。

GloVe官網
GloVe的github地址

使用方法與word2vec類似,也是通過gensim使用,這里不再贅述。

7.4 總結對比

在本任務中,只是用預訓練的DistilBERT模型做詞嵌入的效果要好于預訓練的fasttext和word2vec,也好于在訓練集上微調過的fasttext。

7.5 更多詞向量

https://github.com/Embedding/Chinese-Word-Vectors/blob/master/README_zh.md
https://ai.tencent.com/ailab/nlp/en/embedding.html

總結

以上是生活随笔為你收集整理的BERT实战(1):使用DistilBERT作为词嵌入进行文本情感分类,与其它词向量(FastText,Word2vec,Glove)进行对比的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。