Hugging Face模型微調訓練(基于BERT的中文評價情感分析)

文章目錄

  • 學習視頻地址
  • 項目地址
  • 數據集的下載
  • 模型微調的基本概念與流程
  • 加載數據集
    • 數據集格式
    • 數據集信息
  • 制作Dataset
    • 數據集字段
    • 數據集信息
  • vocab字典操作
    • 詞匯表
    • 文本轉換
  • 下游任務模型設計
  • 模型訓練與保存
    • 數據加載
    • 優化器
    • 訓練循環
  • 最終效果評估與測試
    • 模型加載和測試

學習視頻地址

  • HuggingFace教程

項目地址

  • HuggingFaceStu

數據集的下載

  1. 下載數據集,然后進行文件調整,調整結果如下圖所示
# 將數據集下載到本地
from datasets import load_dataset
# 在代碼開頭添加(抑制所有警告)
import os
os.environ["HF_HUB_DISABLE_SYMLINKS_WARNING"] = "1"# 指定數據集名稱和本地緩存路徑
dataset_name = "lansinuote/ChnSentiCorp"
cache_dir = "data/lansinuote/ChnSentiCorp"# 下載并加載數據集
# 下載并加載數據集(添加信任遠程代碼參數)
dataset = load_dataset(dataset_name,cache_dir=cache_dir,trust_remote_code=True  # 關鍵修復參數
)print(f"數據集已下載到:{cache_dir}")
print("\n第一條數據樣例:")
print(dataset["train"][0])

在這里插入圖片描述

  1. 測試:加載數據,并在終端輸出
from datasets import Dataset
# 取出測試集
test_set = Dataset.from_file("./data/lansinuote/ChnSentiCorp/chn_senti_corp-test.arrow")
print(test_set)
# 查看數據
for data in test_set:print(data)# 取出訓練集
train_set = Dataset.from_file(".//data/lansinuote/ChnSentiCorp/chn_senti_corp-train.arrow")
print(train_set)
# 查看數據
for data in train_set:print(data)
# 取出驗證集
validation_set = Dataset.from_file("./data/lansinuote/ChnSentiCorp/chn_senti_corp-validation.arrow")
print(validation_set)
# 查看數據
for data in validation_set:print(data)

模型微調的基本概念與流程

  • 微調指在預訓練模型的基礎上,通過進一步的訓練來適應特定的下游任務。BERT模型通過預訓練來學習語言的通用模式,然后通過微調來適應特定任務,如情感分析、命名實體識別等。微調過程中,通常凍結BERT的預訓練層,只訓練與下游任務相關的層。

加載數據集

  • 情感分析任務的數據通常包括文本及其對應的情感標簽。使用HuggingFace的datasets庫可以輕松地加載和處理數據集。
from datasets import load_dataset
#加載數據集
dataset =load_dataset('csv',data_files="data/chnsenticorp.csv")
#查看數據集信息
print(dataset)

數據集格式

  • Hugging Face 的 datasets 庫支持多種數據集格式,如 CSV、JSON、TFRecord 等。在本案例中,使用CSV格式,CSV文件應包含兩列:一列是文本數據,另一列是情感標簽。

數據集信息

  • 加載數據集后,可以查看數據集的基本信息,如數據集大小、字段名稱等。

制作Dataset

  • 加載數據集后,需要對其進行處理以適應模型的輸入格式。這包括數據清洗、格式轉換等操作。
from torch.utils.data import Dataset, DataLoader
from datasets import Dataset as HFDataset  # 重命名以避免沖突class MyDataset(Dataset):def __init__(self, split):# 根據 split 確定 .arrow 文件路徑if split == "train":data_path = "./data/train/chn_senti_corp-train.arrow"elif split == "test":data_path = "./data/test/chn_senti_corp-test.arrow"elif split == "validation":data_path = "./data/validation/chn_senti_corp-validation.arrow"else:raise ValueError("無效的數據集類型,必須是 train/test/validation")# 加載 Hugging Face Datasetself.hf_dataset = HFDataset.from_file(data_path)def __len__(self):return len(self.hf_dataset)def __getitem__(self, idx):text = self.hf_dataset[idx]["text"]label = self.hf_dataset[idx]["label"]return text, labelif __name__ == "__main__":# 創建 PyTorch Datasetdataset = MyDataset("train")# 使用 DataLoader 進行迭代dataloader = DataLoader(dataset, batch_size=1, shuffle=True)for data in dataloader:print(data)

數據集字段

  • 在制作Dataset時,需定義數據集的字段。在本案例中,定義了兩個字段:text(文本)和labe1(情感標簽)。每個字段都需要與模型的輸入和輸出匹配。

數據集信息

  • 制作Dataset后,可以通過dataset.info等方法查看其大小、字段名稱等信息,以確保數據集的正確性和完整性。

vocab字典操作

詞匯表

  • BERT模型使用詞匯表(vocab)將文本轉換為模型可以理解的輸入格式。詞匯表包含所有模型已知的單詞及其對應的索引。確保數據集中的所有文本都能找到對應的詞匯索引是至關重要的。
from transformers import BertTokenizer
model_name="./model/google-bert/bert-base-chinese/models--google-bert--bert-base-chinese/snapshots/c30a6ed22ab4564dc1e3b2ecbf6e766b0611a33f"
# 加載字典和分詞工具
# token=BertTokenizer.from_pretrained("bert-base-chinese") # 在線方式
token=BertTokenizer.from_pretrained(model_name) # 使用本地方式(推薦)
'''
sents=["酒店太舊,大堂感覺像三星級水平,在鄭州這樣的酒店水平,絕對算不上四星水平,早餐走了兩圈也沒有可以吃的,太差","已經貼完了,又給小區的媽媽買了一套,值得推薦","屏幕大,本子薄。自帶數字小鍵盤,比較少見,聲音很好,usb接口也很多,性價比高","酒店環境很好,就是有一點偏僻,交通不是很好,不太好打車,酒店應該想辦法解決一下"]
'''
# 批量編碼句子
'''
out=token.batch_encode_plus(batch_text_or_text_pairs=[sents[0],sents[1]],add_special_tokens=True,truncation=True, # 句子過長截斷padding="max_length", # 一律補零到max_length長度max_length=30,return_tensors=None, # 默認返回listreturn_attention_mask=True, # 返回 attention_maskreturn_token_type_ids=False,return_special_tokens_mask=True, #特殊符號標識return_length=True, # 返回length,標識長度)
print(out)
'''
# 獲取字典
# vocab=token.get_vocab()
# print(vocab)
# print("陽" in vocab)
# 添加新詞
token.add_tokens(new_tokens=["陽光","大志"])
# 重新獲取字典
vocab=token.get_vocab()
print("大志" in vocab)
# 添加新的特殊符號 本質鍵值對
# token.add_special_tokens({"eos_token":"[EOS]"})
# 編碼新句子
res=token.encode(text="陽光照在大地上[EOS]",text_pair=None,truncation=True,padding="longest",longest=10,add_special_tokens=True,return_tensors=None)
print(res)
# 解碼為源字符串
print(token.decode(res))

文本轉換

  • 使用tokenizer將文本分割成詞匯表中的單詞,并轉換為相應的索引l。此步驟需要確保文本長度、特殊字符處理等都與BERT模型的預訓練設置相一致。

下游任務模型設計

  • 在微調BERT模型之前,需要設計一個適應情感分析任務的下游模型結構。通常包括一個或多個全連接層,用于將BERT輸出的特征向量轉換為分類結果。
# 加載預訓練模型
from transformers import BertModel
import torch# 定義訓練設備
DEVICE=torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model_dir="./model/google-bert/bert-base-chinese/models--google-bert--bert-base-chinese/snapshots/c30a6ed22ab4564dc1e3b2ecbf6e766b0611a33f"
pretrained=BertModel.from_pretrained(model_dir).to(DEVICE)
# 定義下游任務模型(將主干網絡所提取的特征進行分類)
class Model(torch.nn.Module):def __init__(self):super().__init__()# 上一步 最后輸出全連接模型 Linear(in_features=768, out_features=768, bias=True)self.fc = torch.nn.Linear(768, 2)# 訓練推理def forward(self,input_ids,attention_mask,token_type_ids):# 上游任務不參與訓練 不參與反向傳播,只參與前向訓練with torch.no_grad():out=pretrained(input_ids=input_ids,attention_mask=attention_mask,token_type_ids=token_type_ids)# 下游任務參與訓練output=self.fc(out.last_hidden_state[:0])output=output.softmax(dim=1)return output;

模型訓練與保存

數據加載

  • 使用DataLoader實現批量數據加載。DataLoader自動處理數據的批處理和隨機打亂,確保訓l練的高效性和數據的多樣性。

優化器

  • Adamw是一種適用于BERT模型的優化器,結合了Adam和權重衰減的特點,能夠有效地防止過擬合。

訓練循環

  • 訓練循環包含前向傳播(forward pass)、損失計算(loss calculation)、反向傳播(backward pass)、參數更新(parameter update)等步驟。每個epoch 都會對整個數據集進行一次遍歷,更新模型參數。通常訓練過程中會跟蹤損失值的變化,以判斷模型的收斂情況。
import torch
from torch.optim import AdamWfrom MyData import MyDataset
from torch.utils.data import DataLoader
from Net import Model
from transformers import BertTokenizer# 定義訓練設備
DEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
EPOCHS = 100
BATCH_SIZE = 32
# 加載分詞器
model_name = "./model/google-bert/bert-base-chinese/models--google-bert--bert-base-chinese/snapshots/c30a6ed22ab4564dc1e3b2ecbf6e766b0611a33f"
token = BertTokenizer.from_pretrained(model_name)# 自定義數據編碼處理函數
def collate_fn(data):sente = [i[0] for i in data]label = [i[1] for i in data]# 編碼處理data = token.batch_encode_plus(batch_text_or_text_pairs=sente,truncation=True,padding='max_length',max_length=300,return_tensors='pt',return_length=True)input_ids = data['input_ids']attention_mask = data['attention_mask']token_type_ids = data['token_type_ids']labels = torch.LongTensor(label)return input_ids, attention_mask, token_type_ids, labels# 創建數據集
train_dataset = MyDataset("train")
# 創建數據加載器
train_loader = DataLoader(dataset=train_dataset,batch_size=BATCH_SIZE,shuffle=True,drop_last=True,collate_fn=collate_fn  # 只傳遞函數名
)if __name__ == '__main__':# start trainprint(DEVICE)model = Model().to(DEVICE)# 優化器optimizer = AdamW(model.parameters(), lr=5e-4)# loss functionloss_func=torch.nn.CrossEntropyLoss()# train modelmodel.train()for epoch in range(EPOCHS):for i,(input_ids, attention_mask, token_type_ids, labels) in enumerate(train_loader):# 將數據放到DEVICE上input_ids, attention_mask, token_type_ids, labels=input_ids.to(DEVICE), attention_mask.to(DEVICE), token_type_ids.to(DEVICE), labels.to(DEVICE)# 執行前向計算out=model(input_ids, attention_mask, token_type_ids)# print("Output shape:", out.shape)# 計算損失loss = loss_func(out, labels)# 優化模型 清空權重 反向傳播 更新梯度optimizer.zero_grad()loss.backward()optimizer.step()# 每5個查看一下if i%20==0:out=out.argmax(dim=1)#  準確率acc=(out==labels).sum()/len(labels)print(epoch,i,loss.item(),acc)# 保存模型參數torch.save(model.state_dict(),f"./params/{epoch}bert.pt")print(epoch)

最終效果評估與測試

  • 在模型訓練完成后,需要評估其在測試集上的性能。通常使用準確率、精確率、召回率和F1分數等指標來衡量模型的效果。
    • 準確率是衡量分類模型整體性能的基本指標,計算公式為正確分類的樣本數量除以總樣本數量。
    • 精確率、召回率是分類模型的另兩個重要指標,分別反映模型在正例預測上的精確性和召回能力。
    • F1分數是精確率和召回率的調和平均數,通常用于不均衡數據集的評估。
import torch
from Net import Model
from transformers import BertTokenizer
from MyData import MyDataset
from torch.utils.data import DataLoaderDEVICE = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
# 加載分詞器
model_name = "./model/google-bert/bert-base-chinese/models--google-bert--bert-base-chinese/snapshots/c30a6ed22ab4564dc1e3b2ecbf6e766b0611a33f"
token = BertTokenizer.from_pretrained(model_name)# 自定義數據編碼處理函數
def collate_fn(data):sente = [i[0] for i in data]label = [i[1] for i in data]# 編碼處理data = token.batch_encode_plus(batch_text_or_text_pairs=sente,truncation=True,padding='max_length',max_length=300,return_tensors='pt',return_length=True)input_ids = data['input_ids']attention_mask = data['attention_mask']token_type_ids = data['token_type_ids']labels = torch.LongTensor(label)return input_ids, attention_mask, token_type_ids, labels# 創建數據集
train_dataset = MyDataset("train")
# 創建數據加載器
train_loader = DataLoader(dataset=train_dataset,batch_size=32,shuffle=True,drop_last=True,collate_fn=collate_fn  # 只傳遞函數名
)if __name__ == "__main__":acc=0total=0model=Model().to(DEVICE)model.load_state_dict(torch.load("./params/1bert.pt"))model.eval() # 開啟模型測試模式for i, (input_ids, attention_mask, token_type_ids, labels) in enumerate(train_loader):# 將數據放到DEVICE上input_ids, attention_mask, token_type_ids, labels = input_ids.to(DEVICE), attention_mask.to(DEVICE), token_type_ids.to(DEVICE), labels.to(DEVICE)# 執行前向計算out = model(input_ids, attention_mask, token_type_ids)out=out.argmax(dim=1)acc+=(out==labels).sum().item()total+=len(labels)print(acc/total)

模型加載和測試

  • 使用模型進行測試
import torch
from transformers import BertTokenizerfrom emotionAnalysis.Net import ModelDEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(DEVICE)values=["負向評價","正向評價"]
model=Model().to(DEVICE)# 加載分詞器
model_name = "./model/google-bert/bert-base-chinese/models--google-bert--bert-base-chinese/snapshots/c30a6ed22ab4564dc1e3b2ecbf6e766b0611a33f"
token = BertTokenizer.from_pretrained(model_name)# 自定義數據編碼處理函數
def collate_fn(data):sente = [data]# 編碼處理data = token.batch_encode_plus(batch_text_or_text_pairs=sente,truncation=True,padding='max_length',max_length=300,return_tensors='pt',return_length=True)input_ids = data['input_ids']attention_mask = data['attention_mask']token_type_ids = data['token_type_ids']return input_ids, attention_mask, token_type_idsdef test():model.load_state_dict(torch.load("./params/1bert.pt"))model.eval()while True:data=input("請輸入測試數據(輸入‘q’退出):")if data=="q":print("測試結束")breakinput_ids, attention_mask, token_type_ids=collate_fn(data)input_ids, attention_mask, token_type_ids=input_ids.to(DEVICE), attention_mask.to(DEVICE), token_type_ids.to(DEVICE)with torch.no_grad():out=model(input_ids=input_ids, attention_mask=attention_mask, token_type_ids=token_type_ids)out=out.argmax(dim=1)print("模型判定:",values[out],"\n")if __name__=="__main__":test()
cuda
請輸入測試數據(輸入‘q’退出):酒店服務不錯,環境也還比較好!特別是好像是48樓那個旋轉餐廳滿有特色,至少我覺得住這個酒店還滿滿意!
模型判定: 正向評價 請輸入測試數據(輸入‘q’退出):東西很差
模型判定: 負向評價 請輸入測試數據(輸入‘q’退出):東西很好,我要再買一個
模型判定: 正向評價 請輸入測試數據(輸入‘q’退出):我真的會謝謝你
模型判定: 正向評價 請輸入測試數據(輸入‘q’退出):真的很栓Q
模型判定: 負向評價 

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/75647.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/75647.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/75647.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【藍橋杯】十五屆省賽B組c++

目錄 前言 握手問題 分析 排列組合寫法 枚舉 小球反彈 分析 代碼 好數 分析 代碼 R 格式 分析 代碼 寶石組合 分析 代碼 數字接龍 分析 代碼 拔河 分析 代碼 總結 前言 主播這兩天做了一套藍橋杯的省賽題目(切實感受到了自己有多菜&#x…

必刷算法100題之計算右側小于當前元素的個數

題目鏈接 315. 計算右側小于當前元素的 個數 - 力扣(LeetCode) 題目解析 計算數組里面所有元素右側比它小的數的個數, 并且組成一個數組,進行返回 算法原理 歸并解法(分治) 當前元素的后面, 有多少個比我小(降序) 我們要找到第一比左邊小的元素, 這…

Hyperlane框架:下一代高性能Rust Web框架 [特殊字符]

Hyperlane框架:下一代高性能Rust Web框架 🚀 引言 👋 在當今快速發展的Web開發領域,性能和開發效率的平衡變得越來越重要。Hyperlane作為一個新興的Rust Web框架,完美地解決了這個問題。本文將帶您深入了解Hyperlane…

圖像處理:使用Numpy和OpenCV實現傅里葉和逆傅里葉變換

文章目錄 1、什么是傅里葉變換及其基礎理論 1.1 傅里葉變換 1.2 基礎理論 2. Numpy 實現傅里葉和逆傅里葉變換 2.1 Numpy 實現傅里葉變換 2.2 實現逆傅里葉變換 2.3 高通濾波示例 3. OpenCV 實現傅里葉變換和逆傅里葉變換及低通濾波示例 3.1 OpenCV 實現傅里葉變換 3.2 實現逆傅…

OpenEuler/CentOS一鍵部署OpenGauss數據庫教程(腳本+視頻)

📌OpenEuler/CentOS一鍵安裝OpenGauss數據庫教程 為什么需要OpenGauss一鍵安裝腳本? 手動部署OpenGauss數據庫時,環境適配、依賴沖突等問題常讓開發者頭疼。尤其對新人而言,官方文檔的配置步驟可能耗時數小時甚至引發未知報錯。 …

如何解決 Hive 在創建 MySQL 表時出現亂碼???的問題

1.問題描述 我們啟動Hive建立一個學生students表格 使用desc students;查看表格結構時 發現有出現亂碼的情況 2.解決方案 打開Hive安裝機器上面的MySQL 切換到Hive數據庫 執行以下命令修改字段注釋字符集 mysql -u root -p123456;use hive;alter table COLUMNS_V2 modify col…

自定義組件觸發餓了么表單校驗

餓了么的表單控件,如果存在自定義組件更改了值,例如在el-from中存在原生input組件很有可能沒法觸發表單校驗,下拉框或者彈框組件仍然是報紅邊框。 這是因為餓了么的輸入框或者下拉框更改值的時候會自動觸發表單校驗,但是封裝過后的…

架構思維:查詢分離 - 表數據量大查詢緩慢的優化方案

文章目錄 Pre引言案例何謂查詢分離?何種場景下使用查詢分離?查詢分離實現思路1. 如何觸發查詢分離?方式一: 修改業務代碼:在寫入常規數據后,同步建立查詢數據。方式二:修改業務代碼:…

Linux開發工具——make/makefile

📝前言: 這篇文章我們來講講Linux開發工具——make/makefile: 🎬個人簡介:努力學習ing 📋個人專欄:Linux 🎀CSDN主頁 愚潤求學 🌄其他專欄:C學習筆記&#xf…

python加載訓練好的模型并進行葉片實例分割預測

要基于“GMT: Guided Mask Transformer for Leaf Instance Segmentation”進行代碼復現,可按照以下步驟利用Python實現: 環境配置 克隆倉庫:在終端中使用git clone https://github.com/vios-s/gmt-leaf-ins-seg.git命令,將項目代…

AI平臺初步規劃實現和想法

要實現一個類似Coze的工作流搭建引擎,可以結合SmartEngine作為后端工作流引擎,ReactFlow作為前端流程圖渲染工具,以及Ant Design作為UI組件庫。以下是實現的步驟和關鍵點: ### 1. 后端工作流引擎(SmartEngine&#xf…

Pycharm 啟動時候一直掃描索引/更新索引 Update index/Scanning files to index

多個項目共用一個虛擬環境,有助于加快PyCharm 啟動嗎 chatgpt 4o認為很有幫助,gemini 2.5pro認為沒鳥用,我更認可gemini的觀點。不知道他們誰在一本正經胡說八道。 -------- 打開pycharm的時候,下方的進度條一直顯示在掃描文件…

dify新版本1.1.3的一些問題

本人使用window版本上構建dify,采用docker方法啟動 1、拉取鏡像問題 windows上更改拉取鏡像倉庫地址 優化加速參考:青春不留白/Docker-hub 如果還是拉取比較慢的話,建議科學上網解決。 2、啟動問題 發生報錯Dify:failed to init dify plu…

4.2-3 fiddler抓取手機接口

安卓: 長按手機連接的WiFi,點擊修改網絡 把代理改成手動,服務器主機選擇自己電腦的IP地址,端口號為8888(在dos窗口輸入ipconfig查詢IP地址,為ipv4) 打開手機瀏覽器,輸入http://自己…

Spring Boot中自定義注解的創建與使用

🌟 前言 歡迎來到我的技術小宇宙!🌌 這里不僅是我記錄技術點滴的后花園,也是我分享學習心得和項目經驗的樂園。📚 無論你是技術小白還是資深大牛,這里總有一些內容能觸動你的好奇心。🔍 &#x…

2024第十五屆藍橋杯大賽軟件賽省賽C/C++ 大學 B 組

記錄刷題的過程、感悟、題解。 希望能幫到,那些與我一同前行的,來自遠方的朋友😉 大綱: 1、握手問題-(解析)-簡單組合問題(別人叫她 鴿巢定理)😇,感覺叫高級了…

HTML應用指南:利用POST請求獲取三大運營商5G基站位置信息(一)

在當前信息技術迅猛發展的背景下,第五代移動通信(5G)技術作為新一代的無線通信標準,正逐步成為推動社會進步和產業升級的關鍵驅動力。三大電信運營商(中國移動、中國聯通、中國電信)在全國范圍內的5G基站部署,不僅極大地提升了網絡性能,也為智能城市、物聯網、自動駕駛…

C++學習之線程

目錄 1.進程和線程的概念 2.線程內核三級映射 3.線程優缺點 4.創建線程和獲取線程ID的函數 5.創建子線程 6.循環創建N個子線程 7.子線程傳參地址錯誤演示分析 8.主、子線程共享全局變量、堆空間 9.線程退出 10.pthread join回收線程退出值 11.pthread_cancel 12.殺死…

element-plus中,表單校驗的使用

目錄 一.案例1:給下面的表單添加校驗 1.目的要求 2.步驟 ①給需要校驗的el-form-item項,添加prop屬性 ②定義一個表單校驗對象,里面存放了每一個prop的檢驗規則 ③給el-form組件,添加:rules屬性 ④給el-form組件&#xff0…

團體設計程序天梯賽L2-025 # 分而治之

文章目錄 題目解讀輸入格式輸出格式 思路Ac Code參考 題目解讀 在戰爭中,我們希望首先攻下敵方的部分城市,使其剩余的城市變成孤立無援,然后再分頭各個擊破。為此參謀部提供了若干打擊方案。本題就請你編寫程序,判斷每個方案的可…