大模型指令微調-技巧篇(NEFT)
作者:uuuuu
文章地址:https://zhuanlan.zhihu.com/p/661962656
寫在前面
今天給大家分享一個新的技巧(20231010),一行代碼可以大幅提升指令微調的效果,相關pr已經合到抱抱臉的repo了,又是一個簡單但是帶來巨大效果提升的策略,作者分析是能降低下游微調過程中的模型過擬合現(xiàn)象。
paper:https://arxiv.org/pdf/2310.05914.pdfgithub:https://github.com/neelsjain/NEFTune/tree/maintrl: https://github.com/huggingface/trl/commit/c4ed3274be9cfd5fb8d9316b2fa0eff534bf6bcb
效果提升非??植?/span>,基于llama2 7b,使用alpaca微調,在AlpacaEval上可以從29.79%提升至64.69%。其他的很多指令微調數(shù)據(jù)集也有很大的提升,Evol-Instruct訓練的模型提升了10%,ShareGPT提升了8%,OpenPlatypus提升了8%。即使是經過RLHF進一步調優(yōu)的強大模型,如LLaMA-2-Chat,也受益于使用NEFTune進行額外訓練。
Noisy Embedding Instruction Finetuning (NEIF)
從原理的偽代碼可以看出來與常規(guī)的微調相比,只是在embedding之后加了一個噪聲。這個在bert之前,使用word2vec作為embedding的時候,印象中似乎也有這種做法。
噪聲是從一個均勻分布中,采樣獨立同分布在[-1, 1]范圍內的值,然后進行
的縮放。其中L為輸入長度,d為embedding維度,α為可調節(jié)參數(shù)。
整個策略就這樣,雖然很簡單,但是有效不就完了,然后看看抱抱臉的實現(xiàn),最后提供一些作者的分析
def neftune_forward(self, input: torch.Tensor):"""Implements the NEFTune forward pass for the model. Note this works only fortorch.nn.Embedding layers. This method is slightly adapted from the original source codethat can be found here: https://github.com/neelsjain/NEFTuneArgs:input (`torch.Tensor`):The input tensor to the model.noise_alpha (`float`):The noise alpha value to use for the NEFTune forward pass."""embeddings = torch.nn.functional.embedding(input, self.weight, self.padding_idx, self.max_norm, self.norm_type, self.scale_grad_by_freq, self.sparse)if self.training:dims = torch.tensor(embeddings.size(1) * embeddings.size(2))mag_norm = self.neftune_noise_alpha / torch.sqrt(dims)embeddings = embeddings + torch.zeros_like(embeddings).uniform_(-mag_norm, mag_norm)return embeddings
如果你有用trl來訓練模型,那用起來很容易了,就是SFTTrainer加個neftune_noise_alpha的參數(shù)即可,否則你可以參照著修改一下,改動比較小。整個過程只在訓練階段生效,不影響推理階段,所以也算是免費的午餐了?
一些分析
假設通過在訓練時向嵌入中添加噪聲,模型對指令微調數(shù)據(jù)集的特定細節(jié)(例如格式細節(jié)、確切措辭和文本長度)的過擬合程度會降低。模型不再完全收斂到精準的微調指令分布,而是更能夠提供融入預訓練基礎模型知識和行為的答案。通過結果觀察到的一個非常明顯的副作用是,模型生成更連貫、更長的結果。在大多數(shù)數(shù)據(jù)集上,人工評測和機器評測都更喜歡更長、更冗長的答案(Dubois等人,2023年)。但我們發(fā)現(xiàn),增加的冗長性僅僅是對指令分布過擬合減少的可見副作用之一;增加的冗長性本身無法解釋性能上的提升。
作者做了一個實驗,在llama2 7b上使用/不適用neft,如上圖,NEFTune模型的訓練損失明顯較高,但測試損失稍低,相比于沒有使用NEFTune的基礎模型。這表明使用NEFTune時過擬合較少,泛化能力更好。
作者發(fā)現(xiàn)在一些榜單評測上,跟答案的長度有強相關性。所以第二個實驗想看下neft答案的長度變長,是否會犧牲文本的多樣性。所以計算使用不同微調數(shù)據(jù)集進行訓練的LLaMA-2模型在有和沒有NEFT的情況下的n-gram重復率。在長的段落中,n-gram會更頻繁地重復出現(xiàn),所以控制段落的長度。在每個樣本的開頭計算重復率和多樣性得分,使用固定長度的片段。對于使用Alpaca進行訓練的模型,固定長度為50;對于使用Evol-Instruct進行訓練的模型,固定長度為100;對于使用ShareGPT訓練的模型和使用OpenPlatypus訓練的模型,固定長度均為150。這些片段長度選取是,以確保至少一半的生成文本長度超過截斷長度,并且長度不足的序列將被丟棄。
結果如下:
從上表前2行可以看到,neft的答案更長,但是后面2行用來評估多樣性的指標基本差不多,然后作者得到新的結論,更長的回答并沒有以多樣性為代價,而是提供了額外的答案細節(jié)。
下面是對NEFT算法中使用均勻噪聲和高斯噪聲進行了剔除實驗,并發(fā)現(xiàn)高斯噪聲會導致更長的輸出,但并不帶來性能改善 ,以及超參數(shù) alpha,變化不明顯
除此之外,作者在附錄還貼了很多額外的實驗,感興趣的可以看原文。
