NEFTune
[2023年10月17日] NEFTune已集成到Huggingface的TRL(Transformer强化学习)库和HF Trainer中。查看公告。
[2023年11月25日] NEFTune已集成到Ludwig.ai用于LLM微调。查看PR。
请查看下方我们研究的局限性。此外,对于生成任务,我们建议使用贪婪解码,重复惩罚设为$1.2$。请注意,如果不使用重复惩罚,我们观察到性能会下降,生成结果会退化。
如有疑问,欢迎联系我(邮箱在论文第1页底部)。
概述
在本文中,我们提出在微调的前向传播过程中向训练数据的嵌入向量添加随机噪声。我们表明,这个简单的技巧可以显著改善指令微调的效果,且不需要额外的计算或数据开销。Noisy Embedding Instruction Fine Tuning(NEFTune)虽然简单,但对下游对话质量有很大影响。当使用流行的Alpaca数据集对LLaMA-2-7B等原始LLM进行嘈杂嵌入微调时,其在AlpacaEval上的性能从29.8%提高到64.7%——令人印象深刻的35个百分点提升。NEFTune在对话任务上带来了这一惊人且巨大的性能跃升,同时保持了事实问答基准测试的性能。使用嘈杂嵌入似乎是LLM微调的免费午餐。论文可在这里找到。
注意:在训练过程中,我们观察到训练损失值可能非常接近。论文分析部分的损失直方图是在关闭噪声时的损失值。这里应该会显示出差异。
代码
将NEFTune集成到您的训练过程中最简单的方法是重写嵌入的前向传播。下面提供了一个针对LLaMA的示例实现。请注意,不同的分布式训练需要不同的实现。
from torch.nn import functional as F
def NEFTune(model, noise_alpha=5):
def noised_embed(orig_embed, noise_alpha):
def new_func(x):
# 在训练期间,我们向嵌入添加噪声
# 在生成期间,我们不向嵌入添加噪声
if model.training:
embed_init = orig_embed(x)
dims = torch.tensor(embed_init.size(1) * embed_init.size(2))
mag_norm = noise_alpha/torch.sqrt(dims)
return embed_init + torch.zeros_like(embed_init).uniform_(-mag_norm, mag_norm)
else:
return orig_embed(x)
return new_func
##### 注意:这是针对LLaMA模型的 #####
##### 对于不同的模型,您需要更改嵌入的属性路径 #####
orig_forward = model.base_model.embed_tokens.forward
model.base_model.embed_tokens.forward = noised_embed(orig_forward, noise_alpha)
return model
我们用于运行实验的代码可以在experiment_code
文件夹中找到。
局限性
我们的研究有几个局限性。我们采用AlpacaEval作为衡量LLM指令跟随能力的主要指标,这受制于单一评判者(GPT-4)的偏见。此外,由于计算资源有限,我们无法在多个数据集上验证NEFTune对更大的70B版本LLaMA-2的成功性,并且我们不得不依赖固定的超参数进行大多数NEFTune运行,而不是进行参数扫描。最后,尽管进行了实证研究,我们仍然没有对NEFTune为何有效形成明确的理解。
征求反馈
我们的研究仅限于我们探索的设置。如果您发现NEFTune有任何缺陷,请随时提出问题。我们希望公开讨论NEFTune的任何问题,以帮助未来的研究和用户。