实现mini智能助理—模型训练
背景
距離上篇打帶你實現自己迷你chatgpt文章,到現在已經過去快兩個月。自制mini chatgpt文章一直沒有更新,原因有二:1.一直在找合適體量表現不錯模型 2.公司內部太卷了,沒太多時間好好梳理文章。這篇文章會給大家介紹一些大模型訓練的概念,然后會給大家介紹pretrain model在自己數據集合上的微調學習。
大家一直在講大模型,但是感覺大家也只是在講大模型。到現在似乎還沒看到一篇文章介紹大模型的整個工藝流程是如何的,1.需要經歷哪幾個步驟 2.有哪些手段學習知識 3.如何做特定域知識增強 4.如何去讓機器更懂人(適應不同人表達方式,精準給出他們想要答案;其實就是增強智能體的模糊適應性)。
這篇文章會嘗試去回答上面幾個問題,當然一些技術細節和技術流程沒法完全覆蓋到。原因有二:1.不同情況解決方案不同,只能講個大方向 2.公司也不允許我把所有細節公布,畢竟這個關系錢財之事。
大模型訓練流程
1.pretain model:這個階段大部分情況是設計成無監督或者弱監督學習,讓模型成為博覽群書有知識的通才
2.模型微調:這部分主要對pretrain model做少量標簽或者知識補充,讓通才把自己的知識結構做梳理成為體系
3.上游任務學習:這部分任務訓練模型專業技能,讓模型在有通識時也有更強工作力,同時也會重塑通識體系
4.對齊學習:淵博且有能力,但是還得讓它更懂人話,更容易和他溝通,所以需要做alignment,這部分現在主流是RLHF
上面的幾個過程并非只做一輪,經常是需要做很多輪的迭代才可能讓模型有較好表現。上面的流程分工在開始的幾輪是順序進行,有相對明顯的界限。但是越到后面的迭代邊界越模糊,往往是同時幾種方法一起上。所以大家知道有這些流程和手段就好,不需要去糾結他們清晰邊界。
大模型訓練手段
finetune
Fine-tune的核心思想是利用在大型數據集(例如ImageNet、COCO等)上訓練好的預訓練模型,然后使用較小數據集(小于參數數量)對其進行微調[3]。這樣做的優勢在于,相對于從頭開始訓練模型,Fine-tune可以省去大量的計算資源和時間成本,提高了計算效率,甚至可以提高準確率[1][2]。
finetune是指在預訓練模型的基礎上,針對特定任務進行微調,以提高模型的性能。Fine-tune的具體方法有多種,但一般而言,可以通過調整模型的層數、調整學習率、調整批量大小等方式進行微調[2]。
Finetune的優勢在于不用完全重新訓練模型,從而提高效率,因為一般新訓練模型準確率都會從很低的值開始慢慢上升,但是finetune能夠讓我們在比較少的迭代次數之后得到一個比較好的效果。
雖然Fine-tune有很多優勢,但也存在一些不足之處。例如,Fine-tune需要大量的數據集才能提高模型的性能,這可能會導致一些任務難以實現。此外,Fine-tune的性能很大程度上依賴于預訓練模型的質量和適用性,如果預訓練模型和微調數據集之間存在差異,則Fine-tune可能無法提高模型性能[1]。
未來,Fine-tune技術將繼續得到廣泛的應用。一方面,隨著深度學習模型的不斷發展和改進,預訓練模型的質量和適用性將會不斷提高,從而更加適用于Fine-tune技術。另一方面,Fine-tune技術也將有助于解決一些實際應用中的難題,例如小數據集、數據集標注困難等問題[1][3]。
prompt learn
Prompt Learning的基本概念:Prompt Learning是一種自然語言處理技術,它通過在預訓練模型的輸入前面加上簡短的提示文本來引導模型完成不同的任務[1]。這些提示文本通常是問題或指令形式,用來告訴模型如何理解輸入并生成輸出。Prompt Learning的優點在于它可以用少量的數據完成多個任務[2]。
Multi-Prompt Learning:Multi-Prompt Learning是Prompt Learning的一種擴展形式,它可以將多個Prompt應用于一個問題,達到數據增強或問題分解等效果[1]。常見的Multi-Prompt Learning方法包括并行方法、增強方法和組合方法[2]。并行方法將多個Prompt并行進行,并通過加權或投票的方式將多個單Prompt的結果匯總;增強方法會將一個與當前問題相似的案例與當前輸入一起輸入,以便模型能夠更準確地進行預測;組合方法則將多個Prompt組合在一起使用,以便訓練模型進行更復雜的任務[2]。
如何選擇合適的預訓練模型:選擇合適的預訓練模型是Prompt Learning的關鍵步驟之一。在選擇模型時,需要考慮以下因素:任務類型、數據集、模型大小和訓練時間等[1]。通常情況下,預訓練模型的大小越大,它在各種任務上的表現也越好,但同時需要消耗更多的計算資源[1]。
如何調整Prompt的訓練策略:Prompt Learning的另一個關鍵步驟是如何調整Prompt的訓練策略。可以采用全數據下單純提高模型效果的方法,也可以采用few-shot/zero-shot下使用Prompt作為輔助的方法,或者固定預訓練模型并僅訓練Prompt[[1]。
如上圖所示,finetune的做法pre-traning使用PLMs作為基礎編碼器,finetune下游任務時候添加額外的神經層以進行特定任務,調整所有參數。預訓練和微調任務之間存在差距。
如上圖所示prompt,在pre-traing和finetuning下游任務時候使用同樣的MLM任務。彌合模型調整和預訓練之間的差距來增強 few-shot 學習能力。使用PLMs作為基礎編碼器,添加額外的上下文(模板)和[MASK]位置,將標簽投影到標簽詞(verbalizer),縮小預訓練和微調之間的差距。
上面是用戶評論問題轉prompt的一個流程示意圖,包括模版選擇、模版包裹、MLM輸出詞選擇、詞映射到評論正負性這個幾個流程。
模版選擇
人工模版設計包括,就是專家根據對問題的了解,設計一套模版把專用問題的解決方法轉成適合自然語言生成方式的表述方法。下面就是人針對QA問題做的結構化模版,把QA問題轉成生成模型生成輸出的問題。
自動搜索生成prompt模版,選擇一個元模版,然基于現有單詞的梯度搜索生成最優prompt模版。
利用T5對輸入的多個句子,做模版自動化生成。操作如下圖,大致步驟:1.利用已有模版訓練一個T5模型,讓模型學會如何通過語料(把所有任務輸入拉平作為向量輸入,輸出就是最后模版)2.把任務輸入作為輸入,用訓好的模型做模版生成
讓pre-model自動化的生成模版,思路如下,fix主pre-train模型,讓模型對有標注的任務做訓練,模型學習后改的輸入的句子embbeding,當然輸入原句是不改的,只是讓模型改非輸入句子部分,最后就可以自動化的學習到最有prompt模版了。當然這模版有可能人是看不懂的。
P-tuning v1:將提示用于輸入層(使用重新參數化)
P-tuning v2:將提示用于每個層(如前綴調整)
填入詞選擇
在做prompt任務設計適合,把任務都轉成生成模式了,所以會存在怎么把生成的東西映射到想要結果這樣一個轉化過程,這中間詞表的設計和選擇對最后結果影響很大,所以我們需要對輸出深詞作設計。
Positive: great, wonderful, good.. Negative: terrible, bad, horrible…
手動生成
人腦爆生成一波關鍵詞或者句子短語,然后利用已經有的知識庫去召回更多相關的詞、概念或者短語句子,然后再對召回的這些詞、句子短語作排序精選。
自動化生成
和自動化模版生成很像,模型固定,用打標注的數據來訓練,梯度反傳時候改的是輸入embedding的詞。
delta learn
整體思路,通過增加一些控制參數,來讓表現力強大的大模型可以可控的學習和使用。用個例子作比喻:控制論里面,用簡單線性控制矩陣,來控制龐大且復雜系統;這個比喻不一定完全準確,因為deta learn其實還是可以合并到原模型,那其實就是對所學知識鏈路的重整理了。
實際操作就是使用增量調整來模擬具有數十億參數的模型,并優化一小部分參數。
這張圖表示的意思是,我還是我,但是我經過簡單變化和學習后,我就可以成為多樣不一樣的我,但是pre-train模型是不動的,動的只是參入的參數,眼睛、一幅、裝飾。很形象的表示訓練過程,但是感覺對于表意不夠。但這圖傳的很廣,這邊也就順帶放上來了。
Addtion:方法引入了額外的可訓練神經模塊或參數,這些模塊或參數在原始模型中不存在;
Specification:方法指定原始模型或過程中的某些參數變為可訓練,而其他參數被凍結;
Reparameterization:方法通過變換將現有參數重新參數化為參數高效形式。
detaleran很重要的3個因素:
1.插哪:和原有網絡序列性插入,還是橋接式插入
2.怎么插:只插入某些層,還是整個網絡每層都插入
3.多大矩陣控制:參入控制層參數多大,一bit、還是原參數0.5%
不同的插入方式、不同參數對于模型效果差異還是比較大的,這個大家可以在實際作模型微調時候去體會,上面表是對不同的方法做的數學抽象表示。大家在實操時候發現沒有思路時候會過來看這個表,在結合問題想想會有不一樣幫助。
實操部分
這部分是以chatglm 6B模型來做實驗,具體的代碼在這個鏈接:GitHub - liangwq/Chatglm_lora_multi-gpu: chatglm多gpu用deepspeed和
模型不一定非的要chatglm、llama或者其他什么模型都是可以的。用到了huggingface的peft來做delta學習,deepspeed做多卡分布式訓練。
測試過:2卡A100 80G,8卡 A100 80G硬件配置數據和速度如下
50萬 selefinstruct的數據,2卡、32核cpu、128G mem
batch 2 ,gd 4 也就是每個batch size=16;2個epoch lora_rank=8,插入參數量在7M左右,要訓練20個小時
8卡差不多在5小時左右
微調,模型收斂很穩定效果不錯
代碼講解:
數據處理邏輯
def data_collator(features: list) -> dict:len_ids = [len(feature["input_ids"]) for feature in features]longest = max(len_ids) + 1input_ids = []attention_mask_list = []position_ids_list = []labels_list = []for ids_l, feature in sorted(zip(len_ids, features), key=lambda x: -x[0]):ids = feature["input_ids"]seq_len = feature["seq_len"]labels = ([-100] * (seq_len - 1)+ ids[(seq_len - 1) :]+ [tokenizer.eos_token_id]+ [-100] * (longest - ids_l - 1))ids = ids + [tokenizer.eos_token_id] * (longest - ids_l)_ids = torch.LongTensor(ids)attention_mask, position_ids = get_masks_and_position_ids(ids, seq_len, longest, _ids.device, gmask=False)labels_list.append(torch.LongTensor(labels))input_ids.append(_ids)attention_mask_list.append(attention_mask)position_ids_list.append(position_ids)input_ids = torch.stack(input_ids)labels = torch.stack(labels_list)attention_mask = torch.stack(attention_mask_list)position_ids = torch.stack(position_ids_list)return {"input_ids": input_ids,"labels": labels,"attention_mask": attention_mask,"position_ids": position_ids,}插入lora,允許對在其它數據訓練的lora加入訓練,意思就是可以部分數據部分數據分開訓練lora,需要可以把訓練好的lora整合做共同訓練,非常方便牛逼。對于機器配置不夠的朋友絕對是好事
# setup peft peft_config = LoraConfig(task_type=TaskType.CAUSAL_LM,inference_mode=False,r=finetune_args.lora_rank,lora_alpha=32,lora_dropout=0.1, ) model = get_peft_model(model, peft_config)if finetune_args.is_resume and finetune_args.resume_path:print("=====>load lora pt from =====》:", finetune_args.is_resume, finetune_args.resume_path)model.load_state_dict(torch.load(finetune_args.resume_path), strict=False)accelerate整合部分,因為它不會保留checkpoint,所以我hardcode寫了每2000步保留一個checkpoint,這部分還沒來得急把只保留最新兩個checkpount代碼寫上去,所以會產生很多哥checkpount文件夾,這塊如果大家用不到可以注釋了,或則自己寫下保留兩個的代碼。當然后面我會update。
if i%2000 ==0 and accelerator.is_main_process:#accelerator.wait_for_everyone()path = training_args.output_dir+'/checkpoint_{}'.format(i)os.makedirs(path) accelerator.save(lora.lora_state_dict(accelerator.unwrap_model(model)), os.path.join(path, "chatglm-lora.pt"))#save_tunable_parameters(model, os.path.join(path, "chatglm-lora.pt"))i +=1小結
1.介紹了預訓練大模型的訓練流程是怎么樣的
2.介紹了常用的訓練手段
3.詳細介紹了兩種主流的預訓練手段原理:promt、delta
4.給了一個multi-gpu chatglm訓練的例子
預告:
下面一篇文章會給大家介紹RLHF部分,大家可以關注我
總結
以上是生活随笔為你收集整理的实现mini智能助理—模型训练的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 香港舞蹈家荣毅捷“回乡”办学记:民族的就
- 下一篇: 【论文学习】关于联邦学习激励机制的2篇T