Hugging Face預訓練GPT微調ChatGPT(微調入門!新手友好!)

Hugging Face預訓練GPT微調ChatGPT(微調入門!新手友好!)

在實戰中,?多數情況下都不需要從0開始訓練模型,?是使?“??”或者其他研究者開源的已經訓練好的?模型。

在各種?模型開源庫中,最具代表性的就是Hugging FaceHugging Face是?家專注于NLP領域的AI公司,開發了?個名為Transformers的開源庫,該開源庫擁有許多預訓練后的深度學習模型,如BERT、GPT-2、T5等。Hugging FaceTransformers開源庫使研究?員和開發?員能夠更輕松地使?這些模型進?各種NLP任務,例如?本分類、問答、?本?成等。這個庫也提供了簡潔、?效的API,有助于快速實現?然語?處理應?。

從Hugging Face下載?個GPT-2并微調成ChatGPT,需要遵循的步驟如下。

image-20250319144401279

1.安裝Hugging Face Transformers庫

pip install transformers

2.載入預訓練GPT-2模型和分詞器

import torch # 導?torch
from transformers import GPT2Tokenizer # 導?GPT-2分詞器
from transformers import GPT2LMHeadModel # 導?GPT-2語?模型
model_name = "gpt2" # 也可以選擇其他模型,如"gpt2-medium" "gpt2-large"等
tokenizer = GPT2Tokenizer.from_pretrained(model_name) # 加載分詞器
tokenizer.pad_token = '' # 為分詞器添加pad token
tokenizer.pad_token_id = tokenizer.convert_tokens_to_ids('')
device = "cuda" if torch.cuda.is_available() else "cpu" # 判斷是否有可?的GPU
model = GPT2LMHeadModel.from_pretrained(model_name).to(device) # 將模型加載到設備上(CPU或GPU)
vocab = tokenizer.get_vocab() # 獲取詞匯表
print("模型信息:", model)
print("分詞器信息:",tokenizer)
print("詞匯表??:", len(vocab))
print("部分詞匯示例:", (list(vocab.keys())[8000:8005]))

3.準備微調數據集

from torch.utils.data import Dataset  # 導入PyTorch的Dataset# 自定義ChatDataset類,繼承自PyTorch的Dataset類
class ChatDataset(Dataset):def __init__(self, file_path, tokenizer, vocab):self.tokenizer = tokenizer  # 分詞器self.vocab = vocab  # 詞匯表# 加載數據并處理,將處理后的輸入數據和目標數據賦值給input_data和target_dataself.input_data, self.target_data = self.load_and_process_data(file_path)# 定義加載和處理數據的方法def load_and_process_data(self, file_path):with open(file_path, "r") as f:  # 讀取文件內容lines = f.readlines()input_data, target_data = [], []for i, line in enumerate(lines):  # 遍歷文件的每一行if line.startswith("User:"):  # 如以"User:"開頭,移除"User: "前綴,并將張量轉換為列表tokens = self.tokenizer(line.strip()[6:], return_tensors="pt")["input_ids"].tolist()[0]tokens = tokens + [self.tokenizer.eos_token_id]  # 添加結束符input_data.append(torch.tensor(tokens, dtype=torch.long))  # 添加到input_dataelif line.startswith("AI:"):  # 如以"AI:"開頭,移除"AI: "前綴,并將張量轉換為列表tokens = self.tokenizer(line.strip()[4:], return_tensors="pt")["input_ids"].tolist()[0]tokens = tokens + [self.tokenizer.eos_token_id]  # 添加結束符target_data.append(torch.tensor(tokens, dtype=torch.long))  # 添加到target_datareturn input_data, target_data# 定義數據集的長度,即input_data的長度def __len__(self):return len(self.input_data)# 定義獲取數據集中指定索引的數據的方法def __getitem__(self, idx):return self.input_data[idx], self.target_data[idx]file_path = "/kaggle/input/hugging-face-chatgpt-chat-data/chat.txt"  # 加載chat.txt數據集
chat_dataset = ChatDataset(file_path, tokenizer, vocab)  # 創建ChatDataset對象,傳入文件、分詞器和詞匯表# 打印數據集中前2個數據示例
for i in range(2):input_example, target_example = chat_dataset[i]print(f"示例 {i + 1}:")print("輸入:", tokenizer.decode(input_example))print("輸出:", tokenizer.decode(target_example))

4.準備微調數據加載器

from torch.utils.data import DataLoader  # 導入DataLoadertokenizer.pad_token = ''  # 為分詞器添加pad token
tokenizer.pad_token_id = tokenizer.convert_tokens_to_ids('')# 定義pad_sequence函數,用于將一批序列補齊到相同長度
def pad_sequence(sequences, padding_value=0, length=None):# 計算最大序列長度,如果length參數未提供,則使用輸入序列中的最大長度max_length = max(len(seq) for seq in sequences) if length is None else length# 創建一個具有適當形狀的全零張量,用于存儲補齊后的序列result = torch.full((len(sequences), max_length), padding_value, dtype=torch.long)# 遍歷序列,將每個序列的內容復制到張量result中for i, seq in enumerate(sequences):end = len(seq)result[i, :end] = seq[:end]return result# 定義collate_fn函數,用于將一個批次的數據整理成適當的形狀
def collate_fn(batch):# 從批次中分離源序列和目標序列sources, targets = zip(*batch)# 計算批次中的最大序列長度max_length = max(max(len(s) for s in sources), max(len(t) for t in targets))# 使用pad_sequence函數補齊源序列和目標序列sources = pad_sequence(sources, padding_value=tokenizer.pad_token_id, length=max_length)targets = pad_sequence(targets, padding_value=tokenizer.pad_token_id, length=max_length)# 返回補齊后的源序列和目標序列return sources, targets# 創建DataLoader
chat_dataloader = DataLoader(chat_dataset, batch_size=2, shuffle=True, collate_fn=collate_fn)# 檢查Dataloader輸出
for input_batch, target_batch in chat_dataloader:print("Input batch tensor size:", input_batch.size())print("Target batch tensor size:", target_batch.size())breakfor input_batch, target_batch in chat_dataloader:print("Input batch tensor:")print(input_batch)print("Target batch tensor:")print(target_batch)break

5.對GPT-2進行微調

import torch.nn as nn
import torch.optim as optim# 定義損失函數,忽略pad_token_id對應的損失值
criterion = nn.CrossEntropyLoss(ignore_index=tokenizer.pad_token_id)# 定義優化器
optimizer = optim.Adam(model.parameters(), lr=0.0001)# 進行500個epoch的訓練
for epoch in range(500):for batch_idx, (input_batch, target_batch) in enumerate(chat_dataloader):  # 遍歷數據加載器中的批次optimizer.zero_grad()  # 梯度清零input_batch, target_batch = input_batch.to(device), target_batch.to(device)  # 輸入和目標批次移至設備outputs = model(input_batch)  # 前向傳播logits = outputs.logits  # 獲取logits# 計算損失loss = criterion(logits.view(-1, len(vocab)), target_batch.view(-1))loss.backward()  # 反向傳播optimizer.step()  # 更新參數if (epoch + 1) % 100 == 0:  # 每100個epoch打印一次損失值print(f'Epoch: {epoch + 1:04d}, cost = {loss:.6f}')

6.用約束解碼函數生成回答

# 定義集束解碼函數
def generate_text_beam_search(model, input_str, max_len=50, beam_width=5):model.eval()  # 將模型設置為評估模式(不計算梯度)# 對輸入字符串進行編碼,并將其轉換為張量,然后將其移動到相應的設備上input_tokens = tokenizer.encode(input_str, return_tensors="pt").to(device)# 初始化候選序列列表,包含當前輸入序列和其對數概率得分(我們從0開始)candidates = [(input_tokens, 0.0)]# 禁用梯度計算,以加速預測過程with torch.no_grad():# 迭代生成最大長度的序列for _ in range(max_len):new_candidates = []# 對于每個候選序列for candidate, candidate_score in candidates:# 使用模型進行預測outputs = model(candidate)# 獲取輸出logitslogits = outputs.logits[:, -1, :]# 獲取對數概率得分的top-k值(即beam_width)及其對應的tokenscores, next_tokens = torch.topk(logits, beam_width, dim=-1)final_results = []# 遍歷top-k token及其對應的得分for score, next_token in zip(scores.squeeze(), next_tokens.squeeze()):# 在當前候選序列中添加新的tokennew_candidate = torch.cat((candidate, next_token.unsqueeze(0).unsqueeze(0)), dim=-1)# 更新候選序列的得分new_score = candidate_score - score.item()# 如果新的token是結束符(eos_token),則將該候選序列添加到最終結果中if next_token.item() == tokenizer.eos_token_id:final_results.append((new_candidate, new_score))# 否則,將新的候選序列添加到新候選序列列表中else:new_candidates.append((new_candidate, new_score))# 從新候選序列列表中選擇得分最?的top-k個序列candidates = sorted(new_candidates, key=lambda x: x[1])[:beam_width]# 選擇得分最?的候選序列best_candidate, _ = sorted(candidates, key=lambda x: x[1])[0]# 將輸出token轉換回文本字符串output_str = tokenizer.decode(best_candidate[0])# 移除輸入字符串并修復空格問題input_len = len(tokenizer.encode(input_str))output_str = tokenizer.decode(best_candidate.squeeze()[input_len:])return output_str# 測試模型
test_inputs = ["what is the weather like today?","can you recommend a good book?"
]# 輸出測試結果
for i, input_str in enumerate(test_inputs, start=1):generated_text = generate_text_beam_search(model, input_str)print(f"測試 {i}:")print(f"User: {input_str}")print(f"AI: {generated_text}")
測試1:
User: what is the weather like today?<|endoftext|>
AI: you need an current time for now app with app app app app
測試2:
User: Can you recommend a good book?<|endoftext|>
AI: ockingbird Lee Harper Harper Taylor

模型的回答雖然稱不上完美,但是,我們?少能夠看出,微調數據集中的信息起到了?定的作?。第?個問題問及天?,模型敏銳地指向“app”(應?)這個存在于訓練語料庫中的信息,?查看“應?”確實是我們希望模型給出的答案。回答第?個問題時,模型給出了語料庫中所推薦圖書的作者的名字“Lee Harper”,?書名“To kill a Mockingbird”中的mockingbird是?個未知token,模型把它拆解成了三個token。具體信息如下。

tokenizer.encode('Mockingbird')[44/76, 8629, 16944]
tokenizer.decode(44)'M'
tokenizer.decode(8629)'ocking'
tokenizer.decode(16944)'bird'

因此,在解碼時,出現了ockingbird這樣的不完整信息,但是其中也的確包含了?定的語料庫內部的知識。

?微調則針對特定任務進?優化。這?模式的優勢在于,微調過程通常需要較少的訓練數據和計算資源,同時仍能獲得良好的性能。

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

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

相關文章

Redis BitMap 用戶簽到

Redis Bitmap Bitmap&#xff08;位圖&#xff09;是 Redis 提供的一種用于處理二進制位&#xff08;bit&#xff09;的特殊數據結構&#xff0c;它基于 String 類型&#xff0c;每個 bit 代表一個布爾值&#xff08;0 或 1&#xff09;&#xff0c;可以用于存儲大規模的二值狀…

Spring Boot 3 新特性實戰:從理論到實踐

引言 Spring Boot 自發布以來&#xff0c;憑借其簡潔的配置和強大的功能&#xff0c;迅速成為 Java 開發者的首選框架。隨著 Spring Boot 3 的發布&#xff0c;開發者們迎來了更多令人興奮的新特性。本文將深入探討 Spring Boot 3 的新特性&#xff0c;并通過實戰示例展示如何…

Nodejs使用redis

框架&#xff1a;koa&#xff0c;通過koa-generator創建 redis: 本地搭建&#xff0c;使用默認帳號&#xff0c;安裝說明地址以及默認啟動設置&#xff1a;https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-on-linux/ 中間件&#x…

調研報告:Hadoop 3.x Ozone 全景解析

Ozone 是 Hadoop 的分布式對象存儲系統,具有易擴展和冗余存儲的特點。 Ozone 不僅能存儲數十億個不同大小的對象,還支持在容器化環境(比如 Kubernetes)中運行。 Apache Spark、Hive 和 YARN 等應用無需任何修改即可使用 Ozone。Ozone 提供了 Java API、S3 接口和命令行接口…

AI學習——卷積神經網絡(CNN)入門

作為人類&#xff0c;我們天生擅長“看”東西&#xff1a;一眼就能認出貓狗、分辨紅綠燈、讀懂朋友的表情……但計算機的“眼睛”最初是一片空白。直到卷積神經網絡&#xff08;CNN&#xff09;?的出現&#xff0c;計算機才真正開始理解圖像。今天&#xff0c;我們就用最通俗的…

除自身以外數組的乘積——面試經典150題(力扣)

題目 給你一個整數數組 nums&#xff0c;返回 數組 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘積 。 題目數據 保證 數組 nums之中任意元素的全部前綴元素和后綴的乘積都在 32 位 整數范圍內。 請 不要使用除法&#xff0c;且在 O(n) 時…

?算法OJ?二叉樹的前序遍歷【樹的遍歷】(C++實現)Binary Tree Preorder Traversal

?算法OJ?二叉樹的中序遍歷【樹的遍歷】&#xff08;C實現&#xff09;Binary Tree Inorder Traversal Given the root of a binary tree, return the preorder traversal of its nodes’ values. Example 1: Input: root [1,null,2,3] Output: [1,2,3]Explanation: Exam…

計算機二級MS之Excel

聲明&#xff1a;跟著大貓和小黑學習隨便記下一些筆記供大家參考&#xff0c;二級考試之前將持續更新&#xff0c;希望大家二級都能輕輕松松過啦&#xff0c;過了二級的大神也可以在評論區留言給點建議&#xff0c;感謝大家&#xff01;&#xff01; 文章目錄 考題難點&#x…

【Linux】VMware Workstation Pro 17 安裝教程

目錄 安裝 VMware Workstation Pro 17 一、CDS Repository 獲取安裝包 二、網盤獲取安裝包 三、Broadcom官方獲取安裝包 后續安裝過程沒啥特殊要求 安裝 VMware Workstation Pro 17 目前VMware Workstation pro 17已經對個人用戶免費開放使用。 Broadcom官網地址&#x…

如何在云端平臺上建立 30,000 名用戶的網頁 MMO游戲環境-2 (服務器)

接續上一篇「如何在云端平臺上建立 30,000 名用戶的網頁 MMO游戲環境」&#xff0c;接下來討論模擬連結上的問題。 最初計劃使用35臺伺服器來完成這個實驗&#xff0c;希望能夠有大量的用戶連接&#xff0c;以驗證真實的連接狀況。然而&#xff0c;我們高估了這方面&#xff0c…

架構設計的靈魂交響曲:系統設計各維度的深度解析與實戰指南

引言: 系統設計的背景與重要性 在快速變化的技術環境中&#xff0c;數字化轉型成為企業生存與發展的核心驅動力。系統設計能力不僅是技術團隊的核心競爭力&#xff0c;也是推動業務創新和提升整體效率的關鍵因素。根據Gartner的研究&#xff0c;超過70%的數字化轉型項目未能實…

C語言指針(詳細總結)

目錄 1.初始C指針 幾個重要的概念&#xff1a; 指針的加減 &與* 二級指針 2.指針與數組 指針數組 數組指針變量 一維數組與二維數組傳參的本質 ?編輯?編輯 ?編輯 3.指針與函數 函數指針數組 4.指針與結構體 5.野指針以及常見的內存管理錯誤 常見的內存錯…

JAVA學習-練習試用Java實現“編寫一個Spark程序,結合Elasticsearch對大數據進行全文搜索和篩選“

問題&#xff1a; 編寫一個Spark程序&#xff0c;結合Elasticsearch對大數據進行全文搜索和篩選。 解答思路&#xff1a; 為了編寫一個結合Apache Spark和Elasticsearch進行全文搜索和篩選的程序&#xff0c;你需要按照以下步驟操作&#xff1a; 1. 設置Spark環境&#xff1a;…

VLLM專題(二十一)—分布式推理與服務

1. 如何決定分布式推理策略? 在深入探討分布式推理和服務之前,我們首先需要明確何時使用分布式推理以及可用的策略是什么。常見的做法如下: 單 GPU(無需分布式推理): 如果你的模型可以放入單個 GPU 中,那么你可能不需要使用分布式推理。直接使用單個 GPU 運行推理即可。…

torcharrow gflags版本問題

問題描述 其實仍然是很簡單的編譯問題&#xff0c;但是又弄了一整個下午加幾乎整個晚上&#xff0c;進度緩慢&#xff0c;又吸取了教訓&#xff0c;因而還是來記錄一下。 在試圖使用torcharrow進行推薦系統模擬的時候&#xff0c;撰寫的python程序報錯&#xff1a;ERROR: flag…

介紹一下TiDB、RocksDb、levelDB、LSM 樹、SSTable。

LSM 樹&#xff08;Log-Structured Merge-Tree&#xff09; 核心原理&#xff1a;通過將隨機寫轉換為順序寫優化寫入性能&#xff0c;適用于寫密集型場景。數據首先寫入內存中的 MemTable&#xff08;有序結構&#xff0c;如跳表&#xff09;&#xff0c;當達到閾值后轉為 Imm…

ESP32 BLE 初步學習筆記

前言 藍牙作為一個龐大的知識體系&#xff0c;其學習和運用對于初學者來說顯得有些復雜且凌亂。我整理了這段時間的學習筆記&#xff0c;涵蓋了協議棧、工作流程、參數等內容。在實際應用中&#xff0c;我們主要使用 GAP 和 GATT&#xff0c;協議棧中的其他部分只需了解即可。…

dfs(二十四)47. 全排列 II

47. 全排列 II 給定一個可包含重復數字的序列 nums &#xff0c;按任意順序 返回所有不重復的全排列。 示例 1&#xff1a; 輸入&#xff1a;nums [1,1,2] 輸出&#xff1a; [[1,1,2],[1,2,1],[2,1,1]]示例 2&#xff1a; 輸入&#xff1a;nums [1,2,3] 輸出&#xff1a;[[1,…

代碼隨想錄算法訓練營第五十二天 |101. 孤島的總面積102. 沉沒孤島103. 水流問題104.建造最大島嶼

101. 孤島的總面積 卡碼網&#xff1a;101. 孤島的總面積(opens new window) 題目描述 給定一個由 1&#xff08;陸地&#xff09;和 0&#xff08;水&#xff09;組成的矩陣&#xff0c;島嶼指的是由水平或垂直方向上相鄰的陸地單元格組成的區域&#xff0c;且完全被水域單…

Simple-BEV的bilinear_sample 作為view_transformer的解析,核心是3D-2D關聯點生成

文件路徑models/view_transformers 父類 是class BiLinearSample(nn.Module)基于https://github.com/aharley/simple_bev。 函數解析 函數bev_coord_to_feature_coord的功能 將鳥瞰圖3D坐標通過多相機&#xff08;針孔/魚眼&#xff09;內外參投影到圖像特征平面&#xff0…