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