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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

基于 BERT 实现的情感分析(文本分类)----概念与应用

發布時間:2023/12/29 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于 BERT 实现的情感分析(文本分类)----概念与应用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • 基于 BERT 的情感分析(文本分類)
      • 基本概念理解
        • 簡便的編碼方式: One-Hot 編碼
        • 突破: Word2Vec編碼方式
        • 新的開始: Attention 與 Transformer 模型
        • 四方來降: 超一流預處理模型 BERT 誕生
      • BERT 實現情感分析
        • 數據預處理并創建數據集
        • 定義網絡模型
        • 定義訓練函數與評估函數
        • 設置損失函數、優化方法、BertTokenizer詞嵌入
      • 訓練模型并預測結果
      • 小結

2023/2/17更新,已上傳數據集和對應的代碼至 Github。

基于 BERT 的情感分析(文本分類)

2018年的10月11日,Google發布一篇論文《Pre-training of Deep Bidirectional Transformers for Language Understanding》,成功在 11 項 NLP 任務中取得 SOTA(最優) 結果,贏得自然語言處理學界的一片贊譽之聲。

從此各種類BERT模型如雨后春筍般不斷破土而出,創造了 NLP 領域一項又一項新的記錄,本次我將帶領大家在 18 多萬條數據集上微調BERT實現情感分析(文本分類)。

基本概念理解

是什么導致了 BERT 的誕生?

BERT 有哪些優勢?

簡便的編碼方式: One-Hot 編碼

我們都知道,大家說的話都是人類語言,而計算機本質只認識數字信息,那計算機理解人類語言信息又是必須過程,那么我們該如何設計數字編碼表示語言信息呢?

此時,最初的編碼方式誕生了,即One-Hot編碼,又稱獨熱編碼方式。假設現在有四個詞 ['鋼琴 ', ‘繪畫’, '舞蹈 ', ‘籃球’] ,則編碼方式如下:

鋼琴 → [1, 0, 0, 0]

繪畫 → [0, 1, 0, 0]

舞蹈 → [0, 0, 1, 0]

籃球 → [0, 0, 0, 1]

每個詞在向量中都會有一個 1 與之對應,代表該詞元的編碼信息。最初很多文本信息都是這種編碼方式,但是久而久之,這種編碼方式的兩種缺陷便顯露出來:

1、可能產生維度爆炸的問題,即當詞元的個數超級多的時候,每個詞元的向量長度均為詞元個數 n ,導致計算機無法存儲,運算速度極慢。

2、無法有效表示詞元的相似關系,每個詞元只能獨立表示。

突破: Word2Vec編碼方式

為了改進 One-Hot 編碼的缺陷,一種新的編碼方式應運而生。2013年,Google團隊發布了論文《Efficient Estimation of Word Representations inVector Space》,Word2Vec編碼方式由此誕生,很大程度上推動了 NLP 領域的發展。其編碼方式有以下兩種:

1、Skip-Gram模型,即跳元模型。其原理是根據中心詞預測上下文詞

2、CBOW模型,即連續詞袋模型。其原理是根據上下文詞預測中心詞

通過計算 中心詞與上下文詞的余弦相似度,來確定不同詞元直接的關系。最終將所有詞元都轉化為長度為 embedding_dim(50~300)的向量。

這樣不僅能夠很大程度上縮減詞元的存儲空間,又能獲得詞元與詞元之間的相似度。但是這種方法也有一些缺陷:

1、由于詞和向量是一對一的關系,所以多義詞的問題無法解決。

2、Word2vec 是一種靜態的方式,雖然通用性強,但是無法針對特定任務做動態優化

關于Word2Vec的原理與代碼實現,請看這幾部分內容Word2Vec的詳情原理。

新的開始: Attention 與 Transformer 模型

2017年6月,Google團隊再次發布論文 《Attention Is All You Need》 關于注意力機制的 Transformer模型。

該論文主張使用注意力的機制,完全拋棄CNN,RNN等網絡模型結構。起初主要應用在自然語言處理NLP中,后面也逐漸應用到了計算機視覺中。

僅僅通過 注意力機制(self-attention)前饋神經網絡(Feed Forward Neural Network),不需要使用序列對齊的循環架構就實現了較好的效果。

模型結構如下圖:

其存在兩方面優點:

1、摒棄了RNN的網絡結構模式,其能夠很好的并行運算

2、其注意力機制能夠幫助當前詞獲取較好的上下文信息

由于Transformer部分的原理內容較多,所以暫時跳過,有興趣的朋友可閱讀此篇文章。

四方來降: 超一流預處理模型 BERT 誕生

Bert基于Transformer編碼器塊架構進行設計,同時采用了兩種方法來提升 NLP 處理水平:

1、MLM(Maked Language Model)掩蔽語言模型,Bert通過MLM方法來隨機掩蔽句子中的一個詞元,設計模型根據上下文信息去預測該詞元。通過此種方法,使模型能夠很好地解決多義詞匹配上下文語義理解問題。

2、NSP(Next Sentence Prediction)下一句預測,隨機選取多組 兩個連接或兩個不連接的句子,設置它們是否連續(為上下文)的標記,從而進行訓練,得到文本對之間的關系,能夠解決文本對之間的關系問題,即上下文關系問題

另外,Bert將普遍模型處理的 特定NLP任務 轉化為了在Bert模型下的 不可知NLP任務,也就是說,Bert只是一個語料庫的預處理模型,和One-Hot、Word2Vec一致,均是語言預訓練模型。用戶可以在Bert預訓練模型下作 微調(fine-tune) 操作,使其能夠處理多種NLP任務,如:

(1)單一文本分類(如情感分析)

(2)文本對分類(如自然語言推斷)

(3)問答

(4)文本標記(如命名實體識別)。

比如文本分類,也就是我們這次的任務(情感分析),只需得到整個評論語句的上下文綜合信息(‘<cls>’),再接上一層全連接層,便可實現分類任務。
其它不可知任務類似。

本模型的詳情參考這篇文章。

BERT 實現情感分析

前提準備:

  • 準備18多萬條手機評論信息和對應的情感標簽, 0, 1, 2 代表 差中好 評。
  • 因為個人計算機資源無法訓練出Bert預訓練模型,我們使用 transformer 庫中的 BertTokenizer、 BertModel模型。BertTokenizer將輸入的評論語句轉化為輸入Bert模型的向量信息,BertModel根據輸入信息輸出結果。
  • 數據預處理并創建數據集

    讀取文件中的評論信息,并對數據進行去重。

    import csv import pandas as pd import random import torch from transformers import BertTokenizer, BertModel from torch import nn from d2l import torch as d2l from tqdm import tqdm""" 讀取評論文件的評論信息 """ def read_file(file_name):comments_data = None# 讀取評論信息with open(file_name, 'r', encoding='UTF-8') as f:reader = csv.reader(f)# 讀取評論數據和對應的標簽信息comments_data = [[line[0], int(line[1])] for line in reader if len(line[0]) > 0] # 打亂數據集random.shuffle(comments_data)data = pd.DataFrame(comments_data)same_sentence_num = data.duplicated().sum() # 統計重復的評論內容個數if same_sentence_num > 0:data = data.drop_duplicates() # 刪除重復的樣本信息f.close()return data

    讀取數據集信息,并輸出樣本的長度

    comments_data = read_file('./file/comments.csv') len(comments_data) 181945

    查看所有樣本信息

    comments_data 0101234...186528186529186530186531186532
    外形外觀:時尚精美拍照效果:華為拍照效果杠杠的2
    本來我是想買蘋果13,后來想了想還是支持下華為畢竟是國產之光,但拿到手機用起來感覺系統有時候...1
    手機畢竟是處理器流暢的很手機還比較輕薄還有微顏功能和功能第一感覺很棒流行一些大型游戲十分流暢...2
    京東送貨非常快辛苦快遞小哥啦手機看著挺好的選了黑色的畢竟年紀大了各種彩色已經不適合我了的屏幕...2
    外形外觀在京東買手機好幾臺了這次是最差的手機像是二手的包裝簡陋一看就是拆封的裝手機的盒子都布...0
    ......
    手機贈品一起寄回去了也顯示收貨了到你們哪邊就說我沒退回贈品扣我贈品的錢一天兩天就算了能理解慢...0
    手機已經拿到了。使用感覺很棒!手機的顏值可以的。特別是屏幕,采用了3D曲屏設計,感覺很棒。總...2
    從開始一直都是用蘋果好用是好用就是電池真的不想說1
    第一次在京東買手機手機剛收到包裝很好完整手機顏色很漂亮手感不錯才開始使用看看效果怎么樣總體感...2
    好不容易搶到的,但是信號真的太差了,惆悵!天天卡的要命!1

    181945 rows × 2 columns

    以 6:4 的比例拆分訓練集與測試集,設定切分線。

    split = 0.6 split_line = int(len(comments_data) * split) split_line 109167

    劃分訓練集 train_comments, train_lables 與測試集 test_comments,test_lables 并輸出它們的長度

    # 劃分訓練集與測試集,并將pandas數據類型轉化為列表類型 train_comments, train_labels = list(comments_data[: split_line][0]), list(comments_data[: split_line][1]) test_comments, test_labels = list(comments_data[split_line:][0]), list(comments_data[split_line:][1])len(train_comments),len(train_labels), len(test_comments), len(test_labels) (109167, 109167, 72778, 72778)

    定義網絡模型

    現在我們來微調Bert,使用Bert來實現情感分析(文本分類)的效果。

    默認這里使用基本模型Bert_base(bert-base-chinese),使用12層Transformer編碼器塊,768個隱藏單元和12個自注意頭。

    只需要在Bert的輸出信息中提取出綜合上下文信息 ‘<cls>’,并外接一層全連接層,即可完成情感分析(文本分類)效果。如下圖

    仍不太懂的小伙伴可以參考transform_bert官方文檔,對于Bert的參數和返回有詳細說明。

    """ 定義BERTClassifier分類器模型 """ class BERTClassifier(nn.Module):# 初始化加載 bert-base-chinese 原型,即Bert中的Bert-Base模型def __init__(self, output_dim, pretrained_name='bert-base-chinese'):super(BERTClassifier, self).__init__()# 定義 Bert 模型self.bert = BertModel.from_pretrained(pretrained_name)# 外接全連接層self.mlp = nn.Linear(768, output_dim)def forward(self, tokens_X):# 得到最后一層的 '<cls>' 信息, 其標志全部上下文信息res = self.bert(**tokens_X)# res[1]代表序列的上下文信息'<cls>',外接全連接層,進行情感分析 return self.mlp(res[1])

    定義訓練函數與評估函數

    設計以下的評估函數和訓練函數,用以對模型進行訓練測試

    """ 評估函數,用以評估數據集在神經網絡下的精確度 """ def evaluate(net, comments_data, labels_data):sum_correct, i = 0, 0while i <= len(comments_data):comments = comments_data[i: min(i + 8, len(comments_data))]tokens_X = tokenizer(comments, padding=True, truncation=True, return_tensors='pt').to(device=device)res = net(tokens_X) # 獲得到預測結果y = torch.tensor(labels_data[i: min(i + 8, len(comments_data))]).reshape(-1).to(device=device)sum_correct += (res.argmax(axis=1) == y).sum() # 累加預測正確的結果i += 8return sum_correct/len(comments_data) # 返回(總正確結果/所有樣本),精確率""" 訓練bert_classifier分類器 """ def train_bert_classifier(net, tokenizer, loss, optimizer, train_comments, train_labels, test_comments, test_labels,device, epochs):max_acc = 0.5 # 初始化模型最大精度為0.5# 先測試未訓練前的模型精確度train_acc = evaluate(net, train_comments, train_labels)test_acc = evaluate(net, test_comments, test_labels)# 輸出精度print('--epoch', 0, '\t--train_acc:', train_acc, '\t--test_acc', test_acc)# 累計訓練18萬條數據 epochs 次,優化模型for epoch in tqdm(range(epochs)):i, sum_loss = 0, 0 # 每次開始訓練時, i 為 0 表示從第一條數據開始訓練# 開始訓練模型while i < len(train_comments):comments = train_comments[i: min(i + 8, len(train_comments))] # 批量訓練,每次訓練8條樣本數據# 通過 tokenizer 數據化輸入的評論語句信息,準備輸入bert分類器tokens_X = tokenizer(comments, padding=True, truncation=True, return_tensors='pt').to(device=device)# 將數據輸入到bert分類器模型中,獲得結果res = net(tokens_X)# 批量獲取實際結果信息y = torch.tensor(train_labels[i: min(i + 8, len(train_comments))]).reshape(-1).to(device=device)optimizer.zero_grad() # 清空梯度l = loss(res, y) # 計算損失l.backward() # 后向傳播optimizer.step() # 更新梯度sum_loss += l.detach() # 累加損失i += 8 # 樣本下標累加# 計算訓練集與測試集的精度train_acc = evaluate(net, train_comments, train_labels)test_acc = evaluate(net, test_comments, test_labels)# 輸出精度print('\n--epoch', epoch+1, '\t--loss:', sum_loss / (len(train_comments) / 8), '\t--train_acc:', train_acc,'\t--test_acc', test_acc)# 如果測試集精度 大于 之前保存的最大精度,保存模型參數,并重設最大值if test_acc > max_acc:# 更新歷史最大精確度max_acc = test_acc# 保存模型torch.save(net.state_dict(), 'bert.parameters')

    設置損失函數、優化方法、BertTokenizer詞嵌入

    本次實驗中,我們這里使用交叉熵損失函數、小批量隨機梯度下降,并定義 BertTokenizer 將輸入的評論語句(次元序列)轉化為輸入Bert的數據。

    device = d2l.try_gpu() # 獲取GPUnet = BERTClassifier(output_dim=3) # BERTClassifier分類器,因為最終結果為3分類,所以輸出維度為3,代表概率分布 net = net.to(device) # 將模型存放到GPU中,加速計算# 定義tokenizer對象,用于將評論語句轉化為BertModel的輸入信息 tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')loss = nn.CrossEntropyLoss() # 損失函數 optimizer = torch.optim.SGD(net.parameters(), lr=1e-4) # 小批量隨機梯度下降算法

    訓練模型并預測結果

    train_bert_classifier(net, tokenizer, loss, optimizer, train_comments, train_labels, test_comments, test_labels, device, 20)

    運行結果如下

    經過5個小時左右的模型訓練,在測試集上的精確度最高能夠達到82.38%,相對于之前的RNN系列的結果(75%左右),提升了7個百分比左右,而且我們并沒有作任何調整優化操作,所以Bert預訓練模型還是很強大的。

    現在,我們再次可視化測試一下模型預測的準確度(測試集上),如下

    # 定義模型 net = BERTClassifier(output_dim=3) net = net.to(device)# 加載訓練好的模型參數 net.load_state_dict(torch.load('./bert.parameters'))start = 0 while start < 20:comment = test_comments[start]token_X = tokenizer(comment, padding=True, truncation=True, return_tensors='pt').to(device)label = test_labels[start] # 實際結果result = net(token_X).argmax(axis=1).item() # 得到預測結果# 打印評論語句print(comment)# 輸出預測結果if result == 0:print('預測結果: ', 0, '----》差評', end='\t')elif result == 1:print('預測結果: ', 1, '----》中評', end='\t')else:print('預測結果: ', 2, '----》好評', end='\t')# 輸出實際結果if label == 0:print('實際結果: ', 0, '----》差評', end='\t')elif label == 1:print('實際結果: ', 1, '----》中評', end='\t')else:print('實際結果: ', 2, '----》好評', end='\t')if result == label:print('預測正確')else:print('預測錯誤')start += 1

    運行結果如下:

    小結

    本次使用Bert實現情感分類總體上得到了不錯的效果,但是仍有值得改進的地方,如未對評論數據作預處理操作,也未改善優化Bert分類器的基本結構,僅僅是外接了一個全連接層,未采用更佳的優化算法、未支持動態學習率變化等。

    另外,Bert模型也存在一些缺陷,Bert是基于字粒度對文本數據進行劃分的,我們也可以采用Bert的改進模型RoBERTa模型,或者中文語義更強的ERNIE模型來構建預訓練模型。

    希望本次分享可以幫助到大家。

    總結

    以上是生活随笔為你收集整理的基于 BERT 实现的情感分析(文本分类)----概念与应用的全部內容,希望文章能夠幫你解決所遇到的問題。

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