大模型開發(五):P-Tuning項目——新零售決策評價系統(下)

P-Tuning項目——新零售決策評價系統(下)

  • 0 前言
  • 1 P-Tuning原理
  • 2 數據處理

0 前言

上篇文章我們介紹了使用PET方式微調BERT模型,PET屬于提示詞微調的一種,另一種比較常見的提示詞微調是P-Tuning,我們今天在相同的項目上面用P-Tuning看看。

1 P-Tuning原理

P-Tuning 的目標是減少對人工設計模板(硬模板)的依賴,使用特殊字符(特殊字符可以自由學習也可以自己指定),將模版與原始文本拼在一起輸入預訓練模型,預訓練模型會對模板中的mask做預測,得到一個label。
在這里插入圖片描述
圖中[u1][u2][u3][u4][u5][u6]都是偽標記,它們都是詞表中沒有使用過的token,所謂沒有使用,指的是沒有在訓練集和驗證集中出現過,所以構建軟模板時,要找那種肯定不會出現在訓練集和驗證集的token。也就是說,軟模板不再是人能理解的,只有模型能理解。

本項目的結構和PET大致相同,除了數據處理部分,其他代碼只需要略微修改即可,因此我們這里只講數據處理部分。

2 數據處理

數據處理的代碼在 data_handle/data_preprocess.py 中,大致過程就是先插入Mask,后插入偽標記,我做了比較詳細的注釋,代碼如下:

import torch
import numpy as np
from rich import print
from functools import partial
from datasets import load_dataset
from transformers import AutoTokenizerdef convert_example(examples: dict,tokenizer,max_seq_len: int,max_label_len: int,p_embedding_num=6,train_mode=True,return_tensor=False
) -> dict:"""將樣本數據轉換為模型接收的輸入數據。Args:examples (dict): 訓練數據樣本, e.g. -> {"text": ['娛樂	嗨放派怎么停播了','體育	世界杯為何遲遲不見宣傳',...]}max_label_len (int): 最大label長度,若沒有達到最大長度,則padding為最大長度p_embedding_num (int): p-tuning token(偽標記) 的個數train_mode (bool): 訓練階段 or 推理階段。return_tensor (bool): 是否返回tensor類型,如不是,則返回numpy類型。Returns:dict (str: np.array) -> tokenized_output = {'input_ids': [[101, 3928, ...], [101, 4395, ...]],'token_type_ids': [[0, 0, ...], [0, 0, ...]],'mask_positions': [[5, 6, ...], [3, 4, ...]],'mask_labels': [[183, 234], [298, 322], ...]}"""# 定義輸出格式(Bert模型的接收格式)tokenized_output = {'input_ids': [],'attention_mask': [],'mask_positions': [],  # 記錄label的位置(即MASK Token的位置)'mask_labels': []  # 記錄MASK Token的原始值(即Label值)}# 遍歷樣本數據,將樣本填充到模板中,并轉化為Bert模型的輸入格式for i, example in enumerate(examples['text']):try:# 將[MASK]插在[CLS]之后,[MASK]的位置可以在任何位置,但提示詞的開頭和結尾必須為[CLS]和[SEP]start_mask_position = 1if train_mode:# 如果是訓練模式,則既有樣本的label,也有樣本的文本內容label, content = example.strip().split('\t', 1) # 第二個參數為1表示最多分割1次,結果列表中最多包含2個元素else:# 如果是評估(推理)模式,則只有樣本的文本內容content = example.strip()# 將文本轉換為Bert模型的輸入格式encoded_inputs = tokenizer(text=content,truncation=True,max_length=max_seq_len,padding='max_length')# encoded_inputs包含三個鍵:'input_ids', 'token_type_ids', 'attention_mask'except:continue# 生成 MASK Tokens, 和label長度一致mask_tokens = ['[MASK]'] * max_label_len# 將 MASK Tokens 轉為 idmask_ids = tokenizer.convert_tokens_to_ids(mask_tokens)# 構建 prompt token(s),即構建偽標記,[[unused1] [unused2] ... [unused6]]p_tokens = ["[unused{}]".format(i + 1) for i in range(p_embedding_num)]# 偽標記 轉 idp_tokens_ids = tokenizer.convert_tokens_to_ids(p_tokens)# 獲取input_idsinput_ids = encoded_inputs['input_ids']# 去掉最后的[SEP]tmp_input_ids = input_ids[:-1]# 裁剪content的長度tmp_input_ids = tmp_input_ids[:max_seq_len - len(mask_ids) - len(p_tokens_ids) - 1]# 因為要插入 p_embedding_num 個偽標記,并且標簽長度為 max_label_len,并且最后要加上[SEP]# 所以原來的 input_ids 只能保存 max_seq_len - len(mask_ids) - len(p_tokens_ids) - 1 個token# 插入[MASK]對應的idtmp_input_ids = tmp_input_ids[:start_mask_position] + mask_ids + tmp_input_ids[start_mask_position:]# 插入后,tmp_input_ids 變為 [CLS][MASK][MASK]世界杯...# 補上[SEP]input_ids = tmp_input_ids + [input_ids[-1]]# 插入偽標記input_ids = p_tokens_ids + input_ids  # [unused1][unused2]...[CLS][MASK][MASK]世界杯...[SEP]# 將 Mask Tokens 的位置記錄下來mask_positions = [len(p_tokens_ids) + start_mask_position + i for i in range(max_label_len)]# 將填充后的提示詞加入到輸出字典中tokenized_output['input_ids'].append(input_ids)# 如果輸入需要token_type_ids,可以進行添加,if 'token_type_ids' in encoded_inputs:  # 兼容不需要 token_type_id 的模型, e.g. Roberta-Basetmp = encoded_inputs['token_type_ids']if 'token_type_ids' not in tokenized_output:# 循環第一輪時,'token_type_ids'不在字典tokenized_output中,所以需要增加鍵值對tokenized_output['token_type_ids'] = [tmp]else:# 從第二輪循環開始,直接在列表里添加tokenized_output['token_type_ids'].append(tmp)# 收集Bert模型需要的其他信息tokenized_output['attention_mask'].append(encoded_inputs['attention_mask'])tokenized_output['mask_positions'].append(mask_positions)# 對于訓練模式,則需要將label轉化為Bert模型的輸入格式if train_mode:mask_labels = tokenizer(text=label)  # label token 轉 idmask_labels = mask_labels['input_ids'][1:-1]  # 丟掉[CLS]和[SEP]mask_labels = mask_labels[:max_label_len]   # 如果標簽的長度大于max_label_len,則截斷mask_labels += [tokenizer.pad_token_id] * (max_label_len - len(mask_labels))  # 將 label 補到最長tokenized_output['mask_labels'].append(mask_labels)     # 收集處理后的標簽# 將數據轉化為torch.tensor或者numpy.array格式,方便后續處理for k, v in tokenized_output.items():if return_tensor:tokenized_output[k] = torch.LongTensor(v)else:tokenized_output[k] = np.array(v)return tokenized_outputif __name__ == '__main__':# 導入數據train_dataset = load_dataset('text', data_files={'train': '../data/train.txt'})print(f'train_dataset==>{train_dataset}')print(train_dataset['train']['text'][0])print('-'*80)# 創建分詞器tokenizer = AutoTokenizer.from_pretrained('../../預訓練模型/bert-base-chinese')# 函數式編程new_func = partial(convert_example,tokenizer=tokenizer,max_seq_len=20,max_label_len=2,p_embedding_num=6)# 數據批處理new_dataset = train_dataset.map(new_func, batched=True)# 打印print(f'dataset---》{new_dataset}')for value in new_dataset['train']:# value將是一個字典,包含輸入的text、input_ids、token_type_id、attention_mask、mask_position和mask_labelprint(type(value))for k, v in value.items():print(k, v)print(len(value['input_ids']))break

輸出

train_dataset==>DatasetDict({train: Dataset({features: ['text'],num_rows: 63})
})
電腦	(1)這款筆記本外觀感覺挺漂亮的,分量嗎,對我來說不算沉。 (2)安裝了WindowsXP系統后,運行的速度挺快。發熱量沒有想象中那么大。可能尚未運行很耗資源的程序,沒有感到內存的弊病。不過,1G的內存確實有點小。 (3)附贈的包很不錯,挺有手感的。但是附贈的鼠標實在是太小了,幸好同時訂了一個雙飛燕的鼠標喲。
--------------------------------------------------------------------------------
dataset---》DatasetDict({train: Dataset({features: ['text', 'input_ids', 'attention_mask', 'mask_positions', 'mask_labels', 'token_type_ids'],num_rows: 63})
})
<class 'dict'>
text 電腦	(1)這款筆記本外觀感覺挺漂亮的,分量嗎,對我來說不算沉。 (2)安裝了WindowsXP系統后,運行的速度挺快。發熱量沒有想象中那么大。可能尚未運行很耗資源的程序,沒有感到內存的弊病。不過,1G的內存確實有點小。 (3)附贈的包很不錯,挺有手感的。但是附贈的鼠標實在是太小了,幸好同時訂了一個雙飛燕的鼠標喲。
input_ids [1, 2, 3, 4, 5, 6, 101, 103, 103, 113, 122, 114, 6821, 3621, 5011, 6381, 3315, 1912, 6225, 102]
attention_mask [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
mask_positions [7, 8]
mask_labels [4510, 5554]
token_type_ids [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
20

我個人有幾個暫時理解不了的點:

  1. 上面這段程序,構建的軟模板為:[unused1] [unused2] ... [unused5] [unused6] [CLS] [MASK] [MASK] {text} [SEP],而start_mask_position=1,也就是說start_mask_position竟然是 [MASK] 插入到文本中的位置,假如start_mask_position不是1的話,是不是意味著要在文本中間插入?
  2. 為什么模板不是以 [CLS]開頭?我查到的資料是,P-Tuning允許 [CLS]位置調整,也可以把模板改成這樣: [CLS] [unused1] [unused2] [MASK][MASK] [unused3] [unused4] [unused5] [unused6] {text} [SEP]
  3. 似乎[unused1] [unused2]...[unused6] [CLS] {MASK} {text} [SEP],和前面PET的模板這是一條{MASK}評論:{textA},沒有本質區別,都是人工構建的模板,指定偽標記為哪些token([unused1][unused2]等),出現在哪些位置,指定{MASK}在什么位置({textA}的前面),這些都是人工指定的,并不是模型生成的。既然都是人配置的,它為什么能比硬模板效果好呢?我的理解是,在微調之前,模板中的每個token,模型都是理解的,而軟模板在微調之前,里面的[unused1] [unused2]模型并不認識,是在微調過程中,模型逐漸理解了;而硬模板的話,預訓練模型本來就知道你的硬模板的token是什么意思,他們之間本來就存在一些聯系。
  4. 很多人都說軟模版是一種可學習模板,但模板好像從訓練開始到結束,始終沒改變過,這個“可學習”該如何理解?

AI鄰域的很多問題搞不明白很正常,上面的部分解釋很牽強,但這種方式卻能起作用,這可能就是這個學科的特點吧。

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

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

相關文章

分布式中間件:Redis介紹

目錄 Redis 概述 Redis 的特點 高性能 豐富的數據結構 持久化 分布式特性 簡單易用 Redis 的數據結構 字符串&#xff08;String&#xff09; 哈希&#xff08;Hash&#xff09; 列表&#xff08;List&#xff09; 集合&#xff08;Set&#xff09; 有序集合&…

在昇騰GPU上部署DeepSeek大模型與OpenWebUI:從零到生產的完整指南

引言 隨著國產AI芯片的快速發展&#xff0c;昇騰&#xff08;Ascend&#xff09;系列GPU憑借其高性能和兼容性&#xff0c;逐漸成為大模型部署的重要選擇。本文將以昇騰300i為例&#xff0c;手把手教你如何部署DeepSeek大模型&#xff0c;并搭配OpenWebUI構建交互式界面。無論…

系統思考—組織診斷

“未經過診斷的行動是盲目的。” — 托馬斯愛迪生 最近和一家教育培訓機構溝通時&#xff0c;發現他們面臨一個有意思的問題&#xff1a;每年招生都挺不錯&#xff0c;但教師的整體績效一直提升緩慢&#xff0c;導致師生之間存在長期的不匹配。管理層試了很多辦法&#xff0c;…

AI大模型學習(五): LangChain(四)

Langchian讀取數據庫 案例&#xff1a;在數據庫中表格數據上的問題系統的基本方法,將涵蓋使用鏈和代理的視線,通過查詢數據庫中的數據并得到自然語言的答案,兩者之間的主要區別在于,我們代理可以根據多次循環查詢數據庫以回答問題 實現思路: 1.將問題轉換成DSL查詢,模型將用…

人工智能與深度學習的應用案例:從技術原理到實踐創新

第一章 引言 人工智能(AI)作為21世紀最具變革性的技術之一,正通過深度學習(Deep Learning)等核心技術推動各行業的智能化進程。從計算機視覺到自然語言處理,從醫療診斷到工業制造,深度學習通過模擬人腦神經網絡的層次化學習機制,實現了對復雜數據的高效分析與決策。本…

支持向量機的深度解析:從理論到C++實現

支持向量機(SVM)是一種強大的監督學習算法,廣泛應用于分類和回歸任務。本文詳細探討了SVM的理論基礎,包括最大間隔分離超平面、軟間隔和核技巧(Kernel Trick)的數學原理,并通過LaTeX公式推導其優化目標。接著,我們用C++實現了一個簡單的線性SVM,包括梯度下降優化求解支…

企業如何選擇研發項目進度管理軟件?盤點15款實用工具

這篇文章介紹了以下工具: 1. PingCode&#xff1b; 2. Worktile&#xff1b; 3. 騰訊 TAPD&#xff1b; 4. 華為 DevCloud&#xff1b; 5. 億方云&#xff1b; 6. 阿里云效&#xff1b; 7. CODING 碼云&#xff1b; 8. 明道云&#xff1b; 9. 進度貓&#xff1b; 10. 輕流等。 …

c++: 容器vector

文章目錄 介紹initializer_list與string的不同底層總代碼 介紹 C 中的 vector 是一種序列容器&#xff0c;它允許你在運行時動態地插入和刪除元素。 vector 是基于數組的數據結構&#xff0c;但它可以自動管理內存&#xff0c;這意味著你不需要手動分配和釋放內存。 與 C 數組相…

Qt常用控件之表格QTableWidget

表格QTableWidget QTableWidget 是一個表格控件&#xff0c;行和列交匯形成的每個單元格&#xff0c;是一個 QTableWidgetItem 對象。 1. QTableWidget屬性 QTableWidget 的屬性只有兩個&#xff1a; 屬性說明rowCount當前行的個數。columnCount當前列的個數。 2. QTableW…

Golang學習筆記_47——訪問者模式

Golang學習筆記_44——命令模式 Golang學習筆記_45——備忘錄模式 Golang學習筆記_46——狀態模式 文章目錄 一、核心概念1. 定義2. 解決的問題3. 核心角色4. 類圖 二、特點分析三、適用場景1. 編譯器實現2. 財務系統3. UI組件系統 四、Go語言實現示例完整實現代碼執行結果 五、…

棧概念和結構

文章目錄 1. 棧的概念2. 棧的分類3. 棧的實現&#xff08;數組棧&#xff09;3.1 接口設計&#xff08;Stack.h&#xff09;3.2 接口實現&#xff08;Stack.c&#xff09;1&#xff09;初始化銷毀2&#xff09;棧頂插入刪除3&#xff09;棧頂元素、空棧、大小 3.3 完整代碼Stac…

GitCode 助力 vue3-element-admin:開啟中后臺管理前端開發新征程

源碼倉庫&#xff1a; https://gitcode.com/youlai/vue3-element-admin 后端倉庫&#xff1a; https://gitcode.com/youlai/youlai-boot 開源助力&#xff0c;開啟中后臺快速開發之旅 vue3-element-admin 是一款精心打造的免費開源中后臺管理前端模板&#xff0c;它緊密貼合…

算法.習題篇

算法 — 地大復試 模擬 while循環和MOD循環計數 1.約瑟夫問題 http://bailian.openjudge.cn/practice/3254 using namespace std;bool isNoPeople(vector<bool> c)//判斷當前數組是否一個小孩都沒有了 {bool nopeople true;for (bool ival : c){if ( ival true)nop…

大白話JavaScript實現一個函數,將字符串中的每個單詞首字母大寫。

大白話JavaScript實現一個函數&#xff0c;將字符串中的每個單詞首字母大寫。 答題思路 理解需求&#xff1a;要寫一個函數&#xff0c;它能接收一個字符串&#xff0c;然后把這個字符串里每個單詞的第一個字母變成大寫。分解步驟 拆分單詞&#xff1a;一般單詞之間是用空格隔…

react中如何使用使用react-redux進行數據管理

以上就是react-redux的使用過程&#xff0c;下面我們開始優化部分&#xff1a;當一個組件只有一個render生命周期&#xff0c;那么我們可以改寫成一個無狀態組件&#xff08;UI組件到無狀態組件&#xff0c;性能提升更好&#xff09;

廣告營銷,會被AI重構嗎?

DeepSeek設計&#xff0c;即夢AI繪圖&#xff0c;剪映成片。 DeepSeek的熱度還在高開瘋走。 用戶對于各個場景下DS應用的探索也還在持續&#xff0c;各種DS的模式被挖掘出來&#xff0c;超級個體們開始給手下的大模型團隊進行分工&#xff0c;實踐出各種場景下最佳的排列組合方…

國產編輯器EverEdit - 宏功能介紹

1 宏 1.1 應用場景 宏是一種重復執行簡單工作的利器&#xff0c;可以讓用戶愉快的從繁瑣的工作中解放出來&#xff0c;其本質是對鍵盤和菜單的操作序列的錄制&#xff0c;并不會識別文件的內容&#xff0c;屬于無差別無腦執行。 特別是對一些有規律的重復按鍵動作&#xff0c;…

vscode離線配置遠程服務器

目錄 一、前提 二、方法 2.1 查看vscode的commit_id 2.2 下載linux服務器安裝包 2.3 安裝包上傳到遠程服務器&#xff0c;并進行文件解壓縮 三、常見錯誤 Failed to set up socket for dynamic port forward to remote port&#xff08;vscode報錯解決方法&#xff09;-C…

OmniDrive(1): 論文解讀

多模態大語言模型(MLLMs)的發展推動了基于 LLM 的自動駕駛研究,以利用其強大的推理能力。然而,利用多模態大語言模型(MLLMs)強大的推理能力來改進planning具有挑戰性,因為這需要超越二維推理的完整三維情境感知能力。因為這不單單需要 2D 推理還需要完整的 3D 場景感知能…

ubuntu22.04安裝RAGFlow配合DeepSeek搭建本地知識庫

一、簡介 RAGFlow 是一個基于對文檔的深入理解的開源 RAG&#xff08;檢索增強生成&#xff09;引擎。當與 LLM 集成時&#xff0c;它能夠提供真實的問答功能&#xff0c;并以來自各種復雜格式數據的有根據的引用為后盾。 二、安裝 1.環境要求 CPU ≥ 4 核 &#xff08;x86…