赞
踩
4.19日凌晨正准备睡觉时,突然审稿项目组的文弱同学说:Meta发布Llama 3系列大语言模型了
一查,还真是
本文以大模型开发者的视角,基于Meta官方博客的介绍:Introducing Meta Llama 3: The most capable openly available LLM to date,帮你迅速梳理下LLama的关键特征,并对比上一个版本的LLama2,且本文后续,将更新用我司paper-review数据集微调llama3的训练过程
此次发布的Llama 3有两个版本:8B 和 70B。由于预训练和指令微调的加强,模型在推理、代码生成和指令跟踪等方面的能力得到比较大的提高,最终在多个榜单上超越Google的gemma 7B、Mistral 7B(当然了,我还是得说一句,榜单肯定能够说明一些东西,但不代表全部)
为了更好的评估llama3的性能,Meta开发了一套新的高质量人类评估集。该评估集包含 1,800 个prompt,涵盖 12 个关键用例:寻求建议、头脑风暴、分类、封闭式问答、编码、创意写作、提取、塑造角色/角色、开放式问答、推理、重写和总结
且为了防止模型在此评估集上过度拟合,即使Meta的建模团队也无法访问它(说白了,保证评估数据集中的数据不被模型事先学到)
下图显示了Meta针对 Claude Sonnet、Mistral Medium 和 GPT-3.5 对这些类别和提示进行人工评估的汇总结果(compared to competing models of comparable size in real-world scenarios,即PK的开源模型也都是70B左右的大小)
且llama3的预训练模型这些榜单上PK同等规模的其他模型时,亦有着相对突出的表现
和Llama 2一样,Llama 3 继续采用相对标准的decoder-only transformer架构,但做了如下几个关键的改进
做大模型开发的都知道,数据的重要性不言而喻,为进一步提高模型的性能
为了有效利用 Llama 3 模型中的预训练数据,他们投入了大量精力来扩大预训练规模。具体来说
为了充分释放预训练模型在聊天用例中的潜力,我们还对指令调整方法进行了创新。我们的后训练方法是监督微调SFT、拒绝采样、近端策略优化PPO(关于PPO详见此文《强化学习极简入门:通俗理解MDP、DP MC TC和Q学习、策略梯度、PPO》的第4部分),和直接策略优化DPO的组合(关于DOP则见此文:《RLHF的替代之DPO原理解析:从RLHF、Claude的RAILF到DPO、Zephyr》)
为了方便让开发者负责任地部署llama3,他们采用了一种新的系统级方法
且指令微调模型已经通过内部和外部的努力进行了安全红队(测试)
红队方法利用人类专家和自动化方法来生成对抗性提示,试图引发有问题的响应。例如,我们应用全面的测试来评估与化学、生物、网络安全和其他风险领域相关的滥用风险
所有这些努力都是迭代的,并用于为正在发布的模型进行安全微调提供信息。可以在模型卡中详细了解我们的努力
更多参见负责任使用指南(RUG),且正如在 RUG 中概述的那样,Meta建议根据适合应用程序的内容指南检查和过滤所有输入和输出
Llama 3 很快将在所有主要平台上提供,包括云提供商、模型 API 提供商等等。 Llama 3 将无处不在
基准测试显示,标记生成器提高了标记效率,与 Llama 2 相比,生成的标记最多减少了 15%。此外,Llama 3 8B 现在也添加了组查询注意 (GQA)。结果观察到,尽管与 Llama 2 7B 相比,模型的参数多了 1B,但改进的分词器效率和 GQA 有助于保持与 Llama 2 7B 相同的推理效率。
有关如何利用所有这些功能的示例,请查看Llama Recipes,其中包含所有的开源代码,这些代码可用于从微调到部署再到模型评估的所有内容
llama 3中最大的模型有超过 400B 个参数,不过这个模型仍在训练中(后续,Meta将发布多个具有新功能的模型,包括多模态、以多种语言交谈的能力、更长的上下文窗口和更强的整体功能。且后续还将发布一份详细的研究论文)
HyperWriteAI 的 CEO Matt Shumer在其推特主页(https://twitter.com/mattshumer_/status/1782576964118675565)上宣布,他自己将 Llama-3-8B 的上下文窗口翻了一番(8k→16K):mattshumer/Llama-3-8B-16K (不过可惜不是instruct模型)
以下是来自huggingface的简介
我一开始还挺好奇,他到底用的啥技术,深入一了解,原来所用的技术来自国外的一家AI初创公司Gradient AI,且他们也在不断把LLama的长度拉长
把LLama3的长度扩展到16K的具体实现步骤如下
“还记得RoPE的构造基础是Sinusoidal位置编码?可以改写为下面的公式「以下内容引用自此文的2.1.2节(注,dear friends,莫慌,如果不太理解是个啥意思,或者你想理解下述公式的来龙去脉,请详看此篇详解位置编码的文章 )
其中,,而这个10000这就是上面说的'base' ”
而对base做放大是ntk-aware插值的操作「如果对ntk-aware插值不太熟悉,建议先看下此文《大模型长度扩展综述:从直接外推ALiBi、插值PI、NTK-aware插值、YaRN到S2-Attention》的第三部分」, 故在当下这个把LLama 3的rope_theta从50 0000放大到100 0000的场景中,就是的ntk-aware插值- # This supports merging as many adapters as you want.
- # python merge_adapters.py --base_model_name_or_path <base_model> --peft_model_paths <adapter1> <adapter2> <adapter3> --output_dir <merged_model>
-
- # 导入transformers库中的模型和分词器
- from transformers import AutoModelForCausalLM, AutoTokenizer
- from peft import PeftModel # 导入PEFT模型类
- import torch # 导入PyTorch库
- import os # 导入操作系统接口库
- import argparse # 导入命令行解析库
-
- def get_args():
- parser = argparse.ArgumentParser() # 创建命令行解析器
- parser.add_argument("--base_model_name_or_path", type=str) # 添加命令行参数:基础模型路径或名称
- parser.add_argument("--peft_model_paths", type=str, nargs='+', help="List of paths to PEFT models") # 添加命令行参数:PEFT模型的路径列表
- parser.add_argument("--output_dir", type=str) # 添加命令行参数:输出目录
- parser.add_argument("--device", type=str, default="cpu") # 添加命令行参数:设备类型,默认为CPU
- parser.add_argument("--push_to_hub", action="store_true") # 添加命令行参数:是否推送到Hugging Face模型中心
- parser.add_argument("--trust_remote_code", action="store_true") # 添加命令行参数:是否信任远程代码
- return parser.parse_args() # 解析命令行输入的参数
-
- def main():
- args = get_args() # 获取命令行参数
- if args.device == 'auto': # 自动设备映射
- device_arg = {'device_map': 'auto'}
- else:
- device_arg = {'device_map': {"": args.device}} # 指定设备映射
-
- print(f"Loading base model: {args.base_model_name_or_path}") # 打印加载基础模型的信息
- base_model = AutoModelForCausalLM.from_pretrained(
- args.base_model_name_or_path,
- return_dict=True,
- torch_dtype=torch.float16,
- trust_remote_code=args.trust_remote_code,
- **device_arg
- ) # 加载基础模型
-
- model = base_model # 将基础模型赋值给model变量
-
- for peft_model_path in args.peft_model_paths: # 遍历所有PEFT模型路径
- print(f"Loading PEFT: {peft_model_path}") # 打印加载PEFT模型的信息
- model = PeftModel.from_pretrained(model, peft_model_path, **device_arg) # 加载PEFT模型
- print(f"Running merge_and_unload for {peft_model_path}") # 打印正在合并和卸载模型的信息
- model = model.merge_and_unload() # 合并并卸载模型
-
- tokenizer = AutoTokenizer.from_pretrained(args.base_model_name_or_path) # 加载分词器
-
- if args.push_to_hub: # 如果指定推送到模型中心
- print(f"Saving to hub ...") # 打印保存到模型中心的信息
- model.push_to_hub(f"{args.output_dir}", use_temp_dir=False) # 推送模型到模型中心
- tokenizer.push_to_hub(f"{args.output_dir}", use_temp_dir=False) # 推送分词器到模型中心
- else:
- model.save_pretrained(f"{args.output_dir}") # 保存模型到指定目录
- tokenizer.save_pretrained(f"{args.output_dir}") # 保存分词器到指定目录
-
- print(f"Model saved to {args.output_dir}") # 打印模型保存的路径
-
- if __name__ == "__main__":
- main()
// 待更
刚开始阿荀因为rope_theta这个取名
- class LlamaRotaryEmbedding(nn.Module):
- def __init__(self, dim, max_position_embeddings=2048, base=10000, device=None, scaling_factor=1.0):
- super().__init__() # 调用父类的初始化函数
- self.scaling_factor = scaling_factor # 缩放因子,用于调整位置编码的尺度
- self.dim = dim # 嵌入的维度
- self.max_position_embeddings = max_position_embeddings # 最大位置嵌入数量
- self.base = base # 计算频率的基数
-
- # 计算逆频率,用于生成位置嵌入的频率部分
- inv_freq = 1.0 / (self.base ** (torch.arange(0, self.dim, 2, dtype=torch.int64).float().to(device) / self.dim))
- self.register_buffer("inv_freq", inv_freq, persistent=False) # 将逆频率注册为模型的一个缓冲区
-
- # 为了向后兼容,注册余弦和正弦的缓存值
- self.max_seq_len_cached = max_position_embeddings # 缓存的最大序列长度
- t = torch.arange(self.max_seq_len_cached, device=device, dtype=torch.int64).type_as(self.inv_freq) # 生成位置序列
- t = t / self.scaling_factor # 应用缩放因子
- freqs = torch.outer(t, self.inv_freq) # 计算每个位置的频率
-
- # 与原始论文不同,这里使用了不同的排列方式以获得相同的计算结果
- emb = torch.cat((freqs, freqs), dim=-1) # 拼接频率以创建嵌入
-
- # 注册余弦和正弦值的缓存,将它们转换为默认数据类型
- self.register_buffer("_cos_cached", emb.cos().to(torch.get_default_dtype()), persistent=False)
- self.register_buffer("_sin_cached", emb.sin().to(torch.get_default_dtype()), persistent=False)
而对于上面的这行代码
- # 计算逆频率,用于生成位置嵌入的频率部分
- inv_freq = 1.0 / (self.base ** (torch.arange(0, self.dim, 2, dtype=torch.int64).float().to(device) / self.dim))
其所对应的公式表达则是
其中,
base 是一个基数常数,例如10000 (而上面说了,LLama 3设置的50万)
dim 是嵌入的维度总数
torch.arange(0,dim,2)则代表生成一个从0开始,步长为2,到 dim(但不包括dim)的序列
再后来,Gradient AI再通过类似的方式把rope_theta继续放大,使得其长度可以达到100万,具体实现方法是
// 待更
llama 3出来后,为了通过paper-review的数据集微调3,有以下各种方式
// 待更
// 待更
LLaMA Factory 现已支持 Llama 3 模型,提供了在 Colab 免费 T4 算力上微调 Llama 3 模型的详细实战教程:https://colab.research.google.com/drive/1d5KQtbemerlSDSxZIfAaWXhKr30QypiK?usp=sharing
同时社区已经公开了两款利用本框架微调的中文版 LLaMA3 模型,分别为:
// 待更
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。